theVakhovskeIsTaken hai 4 meses
pai
achega
e0c8ffa4ad
Modificáronse 8 ficheiros con 927 adicións e 424 borrados
  1. 33 10
      WARP.md
  2. 676 156
      package-lock.json
  3. 2 9
      package.json
  4. 47 45
      public/posts/20250929-170-pixels-sharpening-included.md
  5. 1 1
      public/posts/index.json
  6. 8 42
      src/App.jsx
  7. 36 114
      src/components/PostEditor.jsx
  8. 124 47
      src/index.css

+ 33 - 10
WARP.md

@@ -159,14 +159,26 @@ The application uses an extensive MarkdownIt setup with multiple plugins:
 2. Changes will be reflected immediately via API
 
 ### Markdown Features Supported
-- Standard markdown syntax
-- Emoji (`:emoji_name:` syntax)
-- Footnotes (`[^ref]` and `[^ref]: content`)
-- Custom containers (`:::info`, `:::warning`, `:::spoiler`)
-- Abbreviations, subscript/superscript, insertions, marks
-- Definition lists
-- Spoiler text with custom syntax
-- Tables (automatically made scrollable)
+**WYSIWYG Editor Features**:
+- **Visual toolbar**: Quick access to formatting (bold, italic, headers, lists, links, images, code)
+- **Multiple editing modes**: Edit, Preview, and Live (split) modes
+- **Syntax highlighting**: Enhanced code editing with monospace font
+- **Drag-to-resize**: Adjustable panes in live mode
+
+**Standard Markdown Syntax Support**:
+- **Text formatting**: Bold, italic, strikethrough
+- **Headers**: All levels (H1-H6)
+- **Lists**: Ordered and unordered (with nesting)
+- **Links and images**: Standard `[text](url)` and `![alt](src)` syntax
+- **Code**: Inline `code` and fenced code blocks with syntax highlighting
+- **Tables**: GitHub-style tables (automatically made scrollable)
+- **Blockquotes**: Standard `>` syntax, great for callouts with emoji
+- **Horizontal rules**: `---` or `***`
+- **HTML support**: Standard HTML tags when needed
+- **Emoji**: GitHub-style `:emoji_name:` syntax
+- **Footnotes**: Standard `[^ref]` syntax
+- **Collapsible content**: HTML `<details><summary>` tags
+- **Line breaks**: Proper paragraph handling
 
 ### Code Style
 - Uses ESLint with React-specific rules
@@ -174,6 +186,12 @@ The application uses an extensive MarkdownIt setup with multiple plugins:
 - ES2020+ features enabled
 - JSX support configured
 
+### Markdown Compatibility
+- **Standards-compliant**: Uses only widely-supported markdown features
+- **Portable content**: Markdown files work with GitHub, GitLab, and other platforms
+- **No custom extensions**: Avoids proprietary syntax that doesn't work elsewhere
+- **HTML fallback**: When markdown isn't enough, standard HTML tags are supported
+
 ## Custom Implementation Notes
 
 ### State Management
@@ -254,8 +272,13 @@ The codebase contains intentionally obscure function names (e.g., `giveFoxHerHei
 
 ### Post Editor (`/admin/post/new` or `/admin/post/:slug/edit`) - **Requires Authentication**
 - Rich form interface for post metadata (title, description, tags)
-- Large textarea for markdown content
-- Live preview tab with full markdown rendering
+- **WYSIWYG Markdown Editor** with multiple editing modes:
+  - **Edit Mode**: Source code editing with syntax highlighting
+  - **Preview Mode**: Live rendered markdown preview
+  - **Live Mode**: Split view with edit and preview side-by-side
+- Visual toolbar with formatting buttons (bold, italic, headers, lists, links, etc.)
+- Drag-to-resize editor panes in live mode
+- Full support for standard markdown features (tables, footnotes, emoji, HTML tags)
 - Save/cancel actions with error handling
 - Automatic slug generation from title for new posts
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 676 - 156
package-lock.json


+ 2 - 9
package.json

@@ -14,20 +14,13 @@
     "preview": "vite preview"
   },
   "dependencies": {
-    "@digitalocean/do-markdownit": "^1.16.1",
     "@tailwindcss/vite": "^4.1.13",
+    "@uiw/react-markdown-preview": "^5.1.5",
+    "@uiw/react-md-editor": "^4.0.8",
     "dompurify": "^3.2.6",
     "markdown-it": "^14.1.0",
-    "markdown-it-abbr": "^2.0.0",
-    "markdown-it-container": "^4.0.0",
-    "markdown-it-deflist": "^3.0.0",
     "markdown-it-emoji": "^3.0.0",
     "markdown-it-footnote": "^4.0.0",
-    "markdown-it-ins": "^4.0.0",
-    "markdown-it-mark": "^4.0.0",
-    "markdown-it-spoiler": "^1.1.1",
-    "markdown-it-sub": "^2.0.0",
-    "markdown-it-sup": "^2.0.0",
     "marked": "^16.2.1",
     "react": "^19.1.1",
     "react-dom": "^19.1.1",

+ 47 - 45
public/posts/20250715.md → public/posts/20250929-170-pixels-sharpening-included.md

@@ -1,45 +1,47 @@
-title:170 pixels (sharpening included)
-
-desc:Eradicate all edges. _Or how OEMs reiterate their meaning of portraits._
-
-For years, OEMs have been keen on working with portrait modes on phones, each with their own varieties and quirks. But in the past four years, portrait mode has been redefined from the ground up, prioritizing hardware over software to better separate the subject from the background and maintain compression ratios [^first].
-
-[^first]: _The difference in how flattened subject is, related to background, and directly correlating to the final bokeh look._
-
-This shift marks a significant evolution from the early days of portrait photography on phones. Initially, portrait modes heavily relied on software algorithms to create a blurred background effect, but now, the mode relies on both the provided hardware background blur and the supplementary effect from mode. 
-
-These methods often _actually, mostly_ produced inconsistent results, with jagged edges around the subject and an unnatural, sometimes "painted" look to the bokeh.
-
-
-
-With all of that being taken in account, the main source of improvements is now, _**wow**_, hardware!
-
-## Test subjects
-
-| | HONOR Magic 7 Pro | OPPO Find X7 Ultra | vivo X200 (CN, Base model) |
-| :--- | :--- | :--- | :--- |
-| **Processor** | Qualcomm Snapdragon 8 Elite | Qualcomm Snapdragon 8 Gen 3 | MediaTek Dimensity 9400 |
-| **Telephoto Camera (3x, primary portrait camera)**| 200MP 1/1.4" 0.56µm (2.24µm @ Hexa-deca-bayer) Samsung S5KHP3 based telephoto | 50MP 1/1.56" 1.0µm (2.0µm @ Quad-bayer) Sony IMX890 based telephoto | 50MP 1/1.95" 0.8µm (1.6µm @ Quad-bayer) Sony IMX882/LYT-600 based telephoto |
-| **EFL & Aperture** | 72mm at ƒ2.6 | 62mm (cropped to 70mm) at ƒ2.6 | 70mm at ƒ2.6 |
-| **Portrait Profiles** | Harcourt-tuned | No portrait profiles provided by Hasselblad | Zeiss-tuned |
-| **Software version**| MagicOS meafnaf[^second] 9.0.0.123 (C185E1R3P2)|ColorOS CN 15.0.0.731(CN01)|OriginOS CN 15.0.31.15|
-
-[^second]: _Middle East, North Africa, Africa. Also common region for Hong Kong units._
-
-## _Why these three?_
-Because it would be fun to see three different types of hardware stacked against each other, wouldn't it? And to make people speculate whether each of these phones would be above either just based on raw specs.
-
-# Chapter 1: Loss of detail (LoD)
-Loss of detail is a common consequence of lower-resolution shots, that portrait shots usually are, since they're being shot with a "fusion" technique by combining the monochromatic information from auxiliary camera to separate foreground subject from background.
-
-In this case, the auxiliary cameras are not needed, as we have enough data to split FG from BG:
-- Natural telephoto DoF provides an understandable canvas for image processing
-- Laser AF provides information for distance between the foreground and camera, to provide accurate measurements to be used later
-
-Our test devices work exactly in accordance to these principles, and do not require monochrome segmentation source to acquire differential information.
-
-However, some devices without hardware capabilities to precisely differ S/FG use software depth map, like Google's Pixel devices do:
-
-:::spoiler clickme
-![alt text](image.png)
-:::
+title: 170 pixels (sharpening included)
+desc: Eradicate all edges. Or how OEMs reiterate their meaning of portraits.
+
+For years, OEMs have been keen on working with portrait modes on phones, each with their own varieties and quirks. But in the past four years, portrait mode has been redefined from the ground up, prioritizing hardware over software to better separate the subject from the background and maintain compression ratios [^first].
+
+[^first]: _The difference in how flattened subject is, related to background, and directly correlating to the final bokeh look._
+
+This shift marks a significant evolution from the early days of portrait photography on phones. Initially, portrait modes heavily relied on software algorithms to create a blurred background effect, but now, the mode relies on both the provided hardware background blur and the supplementary effect from mode. 
+
+These methods often _actually, mostly_ produced inconsistent results, with jagged edges around the subject and an unnatural, sometimes "painted" look to the bokeh.
+
+
+
+With all of that being taken in account, the main source of improvements is now, _**wow**_, hardware!
+
+## Test subjects
+
+| | HONOR Magic 7 Pro | OPPO Find X7 Ultra | vivo X200 (CN, Base model) |
+| :--- | :--- | :--- | :--- |
+| **Processor** | Qualcomm Snapdragon 8 Elite | Qualcomm Snapdragon 8 Gen 3 | MediaTek Dimensity 9400 |
+| **Telephoto Camera (3x, primary portrait camera)**| 200MP 1/1.4" 0.56µm (2.24µm @ Hexa-deca-bayer) Samsung S5KHP3 based telephoto | 50MP 1/1.56" 1.0µm (2.0µm @ Quad-bayer) Sony IMX890 based telephoto | 50MP 1/1.95" 0.8µm (1.6µm @ Quad-bayer) Sony IMX882/LYT-600 based telephoto |
+| **EFL & Aperture** | 72mm at ƒ2.6 | 62mm (cropped to 70mm) at ƒ2.6 | 70mm at ƒ2.6 |
+| **Portrait Profiles** | Harcourt-tuned | No portrait profiles provided by Hasselblad | Zeiss-tuned |
+| **Software version**| MagicOS meafnaf[^second] 9.0.0.123 (C185E1R3P2)|ColorOS CN 15.0.0.731(CN01)|OriginOS CN 15.0.31.15|
+
+[^second]: _Middle East, North Africa, Africa. Also common region for Hong Kong units._
+
+## _Why these three?_
+Because it would be fun to see three different types of hardware stacked against each other, wouldn't it? And to make people speculate whether each of these phones would be above either just based on raw specs.
+
+# Chapter 1: Loss of detail (LoD)
+Loss of detail is a common consequence of lower-resolution shots, that portrait shots usually are, since they're being shot with a "fusion" technique by combining the monochromatic information from auxiliary camera to separate foreground subject from background.
+
+In this case, the auxiliary cameras are not needed, as we have enough data to split FG from BG:
+- Natural telephoto DoF provides an understandable canvas for image processing
+- Laser AF provides information for distance between the foreground and camera, to provide accurate measurements to be used later
+
+Our test devices work exactly in accordance to these principles, and do not require monochrome segmentation source to acquire differential information.
+
+However, some devices without hardware capabilities to precisely differ S/FG use software depth map, like Google's Pixel devices do:
+
+<details>
+<summary>Click to view image comparison</summary>
+
+![Comparison of portrait modes](image.png)
+
+</details>

+ 1 - 1
public/posts/index.json

@@ -1,3 +1,3 @@
 [
-  "20250715.md"
+  "20250929-170-pixels-sharpening-included.md"
 ]

+ 8 - 42
src/App.jsx

@@ -2,16 +2,7 @@ import React, { useState, useEffect } from 'react';
 import { BrowserRouter as Router, Routes, Route, Link, useParams } from 'react-router-dom';
 import MarkdownIt from 'markdown-it';
 import { full as emoji } from 'markdown-it-emoji';
-import container from "markdown-it-container";
-import abbr from "markdown-it-abbr";
-import deflist from "markdown-it-deflist";
 import footnote from "markdown-it-footnote";
-import mark from "markdown-it-mark";
-import sub from "markdown-it-sub";
-import sup from "markdown-it-sup";
-import ins from "markdown-it-ins";
-import doMarkdownit from "@digitalocean/do-markdownit";
-import spoiler from "markdown-it-spoiler";
 import DOMPurify from 'dompurify';
 import { AuthProvider, useAuth } from './contexts/AuthContext';
 import AdminDashboard from './components/AdminDashboard';
@@ -38,39 +29,14 @@ const scrollableTablesPlugin = (md) => {
 };
 
 const md = new MarkdownIt({
-  html: true,
-  linkify: true,
-  typographer: true,
-});
-md.use(scrollableTablesPlugin)
-  .use(emoji)
-  .use(abbr)
-  .use(sub)
-  .use(sup)
-  .use(ins)
-  .use(mark)
-  .use(deflist)
-  .use(footnote)
-  .use(spoiler)
-  //.use(doMarkdownit)
-  .use(container, "info")
-  .use(container, "spoiler", {
-    render(tokens, idx) {
-      const token = tokens[idx];
-      if (token.nesting === 1) {
-        const m = token.info.trim().match(/^spoiler\s+(.*)$/);
-        const title = m ? m[1] : "Spoiler";
-        return `<details class="spoiler"><summary>${title}</summary>\n`;
-      } else {
-        return "</details>\n";
-      }
-    },
-  })
-  .use(container, "warning");
-
-md.renderer.rules.footnote_block_open = () => {
-  return '<section class="footnotes"><ol class="list-decimal pl-6 mt-4">';
-};
+  html: true,        // Enable HTML tags in source
+  linkify: true,     // Auto-convert URL-like text to links
+  typographer: true, // Enable some language-neutral replacement + quotes beautification
+  breaks: false      // Convert '\n' in paragraphs into <br>
+})
+.use(scrollableTablesPlugin)  // Keep our table scrolling enhancement
+.use(emoji)                   // GitHub-style emoji :emoji_name:
+.use(footnote);               // Standard footnotes [^1]
 
 const API_BASE = 'http://localhost:3001/api';
 

+ 36 - 114
src/components/PostEditor.jsx

@@ -1,73 +1,13 @@
 import React, { useState, useEffect } from 'react';
 import { useNavigate, useParams, Link } from 'react-router-dom';
-import MarkdownIt from 'markdown-it';
-import { full as emoji } from 'markdown-it-emoji';
-import container from "markdown-it-container";
-import abbr from "markdown-it-abbr";
-import deflist from "markdown-it-deflist";
-import footnote from "markdown-it-footnote";
-import mark from "markdown-it-mark";
-import sub from "markdown-it-sub";
-import sup from "markdown-it-sup";
-import ins from "markdown-it-ins";
-import spoiler from "markdown-it-spoiler";
-import DOMPurify from 'dompurify';
-
+import MDEditor from '@uiw/react-md-editor';
+import '@uiw/react-md-editor/markdown-editor.css';
+import '@uiw/react-markdown-preview/markdown.css';
 const API_BASE = 'http://localhost:3001/api';
 
-// Markdown renderer setup (same as original App.jsx)
-const scrollableTablesPlugin = (md) => {
-  const defaultRenderOpen = md.renderer.rules.table_open || function (tokens, idx, options, env, self) {
-    return self.renderToken(tokens, idx, options);
-  };
-
-  const defaultRenderClose = md.renderer.rules.table_close || function (tokens, idx, options, env, self) {
-    return self.renderToken(tokens, idx, options);
-  };
-
-  md.renderer.rules.table_open = function (tokens, idx, options, env, self) {
-    return '<div class="overflow-x-auto">' + defaultRenderOpen(tokens, idx, options, env, self);
-  };
-
-  md.renderer.rules.table_close = function (tokens, idx, options, env, self) {
-    return defaultRenderClose(tokens, idx, options, env, self) + '</div>';
-  };
-};
-
-const md = new MarkdownIt({
-  html: true,
-  linkify: true,
-  typographer: true,
-});
-
-md.use(scrollableTablesPlugin)
-  .use(emoji)
-  .use(abbr)
-  .use(sub)
-  .use(sup)
-  .use(ins)
-  .use(mark)
-  .use(deflist)
-  .use(footnote)
-  .use(spoiler)
-  .use(container, "info")
-  .use(container, "spoiler", {
-    render(tokens, idx) {
-      const token = tokens[idx];
-      if (token.nesting === 1) {
-        const m = token.info.trim().match(/^spoiler\s+(.*)$/);
-        const title = m ? m[1] : "Spoiler";
-        return `<details class="spoiler"><summary>${title}</summary>\n`;
-      } else {
-        return "</details>\n";
-      }
-    },
-  })
-  .use(container, "warning");
-
-md.renderer.rules.footnote_block_open = () => {
-  return '<section class="footnotes"><ol class="list-decimal pl-6 mt-4">';
-};
+// Note: MDEditor handles its own markdown processing for the editor interface
+// The final blog rendering uses the MarkdownIt instance in App.jsx
+// This separation prevents footnote duplication issues
 
 function PostEditor() {
   const navigate = useNavigate();
@@ -84,7 +24,6 @@ function PostEditor() {
   const [loading, setLoading] = useState(isEditing);
   const [saving, setSaving] = useState(false);
   const [error, setError] = useState(null);
-  const [previewMode, setPreviewMode] = useState(false);
 
   useEffect(() => {
     if (isEditing) {
@@ -173,12 +112,6 @@ function PostEditor() {
     }
   };
 
-  const renderPreview = () => {
-    if (!formData.content) return '<p class="text-gray-500">Write some content to see the preview...</p>';
-    
-    const htmlContent = md.render(formData.content);
-    return DOMPurify.sanitize(htmlContent);
-  };
 
   if (loading) {
     return (
@@ -287,51 +220,40 @@ function PostEditor() {
 
           {/* Content Editor */}
           <div className="bg-white shadow rounded-lg">
-            <div className="px-6 py-4 border-b border-gray-200 flex justify-between items-center">
+            <div className="px-6 py-4 border-b border-gray-200">
               <h2 className="text-lg font-semibold text-gray-900">Content</h2>
-              <div className="flex space-x-2">
-                <button
-                  type="button"
-                  onClick={() => setPreviewMode(false)}
-                  className={`px-3 py-1 text-sm rounded ${!previewMode ? 'bg-blue-100 text-blue-700' : 'text-gray-500 hover:text-gray-700'}`}
-                >
-                  Edit
-                </button>
-                <button
-                  type="button"
-                  onClick={() => setPreviewMode(true)}
-                  className={`px-3 py-1 text-sm rounded ${previewMode ? 'bg-blue-100 text-blue-700' : 'text-gray-500 hover:text-gray-700'}`}
-                >
-                  Preview
-                </button>
-              </div>
+              <p className="text-sm text-gray-600 mt-1">
+                Use the WYSIWYG editor below. Click the tabs to switch between Edit and Preview modes.
+              </p>
             </div>
             
             <div className="px-6 py-4">
-              {!previewMode ? (
-                <div>
-                  <textarea
-                    id="content"
-                    required
-                    rows={20}
-                    value={formData.content}
-                    onChange={(e) => handleInputChange('content', e.target.value)}
-                    className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono text-sm"
-                    placeholder="Write your post content in Markdown..."
-                  />
-                  <div className="mt-2 text-xs text-gray-500">
-                    <p><strong>Supported Markdown features:</strong></p>
-                    <p>Basic syntax, tables, footnotes, emoji, custom containers (:::info, :::warning, :::spoiler), and more.</p>
-                  </div>
-                </div>
-              ) : (
-                <div className="border border-gray-300 rounded-lg p-4 min-h-[500px]">
-                  <div 
-                    className="markdown-content prose max-w-none"
-                    dangerouslySetInnerHTML={{ __html: renderPreview() }}
-                  />
-                </div>
-              )}
+              <div className="border border-gray-300 rounded-lg overflow-hidden">
+                <MDEditor
+                  value={formData.content}
+                  onChange={(value) => handleInputChange('content', value || '')}
+                  height={500}
+                  preview="edit"
+                  hideToolbar={false}
+                  data-color-mode="light"
+                  visibleDragBar={false}
+                  textareaProps={{
+                    placeholder: 'Write your post content in Markdown...',
+                    style: { fontSize: '14px', fontFamily: 'ui-monospace, monospace' },
+                    required: true
+                  }}
+                />
+              </div>
+              <div className="mt-3 text-xs text-gray-500 bg-blue-50 p-3 rounded-lg">
+                <p><strong>WYSIWYG Editor Features:</strong></p>
+                <ul className="list-disc list-inside mt-1 space-y-1">
+                  <li>Toggle between <strong>Edit</strong>, <strong>Preview</strong>, and <strong>Live</strong> modes using the tabs</li>
+                  <li>Use toolbar buttons for quick formatting (bold, italic, headers, lists, etc.)</li>
+                  <li>Standard markdown features: tables, footnotes, emoji (:emoji:), HTML support</li>
+                  <li>Collapsible content: Use <code>&lt;details&gt;&lt;summary&gt;</code> HTML tags</li>
+                  <li>Drag the divider to resize edit/preview panes in Live mode</li>
+                </ul>
+              </div>
             </div>
           </div>
 

+ 124 - 47
src/index.css

@@ -192,7 +192,7 @@ body {
   padding-right: 2rem;
 }
 
-/* Subscript & Superscript */
+/* Standard HTML elements support */
 .markdown-content sub {
   font-size: 0.8em;
   vertical-align: sub;
@@ -202,39 +202,30 @@ body {
   vertical-align: super;
 }
 
-/* Inserted text */
-.markdown-content ins,
-.markdown-content u {
-  text-decoration: underline;
-  color: #a7f3d0; /* teal-200 */
-}
-
-/* Marked / highlighted text */
-.markdown-content mark {
-  background-color: #facc15; /* yellow-400 */
-  color: #000;
-  padding: 0.1em 0.3em;
-  border-radius: 0.25rem;
+/* Details/Summary for collapsible content */
+.markdown-content details {
+  border: 1px solid #d1d5db;
+  border-radius: 0.5rem;
+  padding: 1rem;
+  margin: 1rem 0;
+  background-color: #f9fafb;
 }
 
-/* Definition lists */
-.markdown-content dl {
-  margin: 1.5rem 0;
-}
-.markdown-content dt {
+.markdown-content details summary {
+  cursor: pointer;
   font-weight: 600;
-  margin-top: 1rem;
+  margin-bottom: 0.5rem;
+  color: #374151;
 }
-.markdown-content dd {
-  margin-left: 1.5rem;
-  margin-bottom: 1rem;
-  color: #6e6e6e;
+
+.markdown-content details[open] {
+  background-color: #f3f4f6;
 }
 
-/* Abbreviations */
-.markdown-content abbr[title] {
-  border-bottom: 1px dotted #9ca3af;
-  cursor: help;
+.markdown-content details[open] summary {
+  margin-bottom: 1rem;
+  border-bottom: 1px solid #d1d5db;
+  padding-bottom: 0.5rem;
 }
 
 /* Footnotes */
@@ -257,30 +248,116 @@ body {
   margin: 0.5rem 0;
 }
 
-.markdown-content .info {
-  background-color: #8793b54d; /* blue-900 */
-  border-left: 4px solid #3b82f6; /* blue-500 */
-  padding: 1rem;
-  border-radius: 0.5rem;
-  margin: 1rem 0;
+/* Standard alert/callout styling using blockquotes with emoji */
+.markdown-content blockquote p:first-child:before {
+  /* This will style blockquotes that start with emoji as callouts */
 }
 
-.markdown-content .warning {
-  background-color: #b398874d; /* amber-900 */
-  border-left: 4px solid #f59e0b; /* amber-500 */
-  padding: 1rem;
-  border-radius: 0.5rem;
-  margin: 1rem 0;
+/* You can use standard blockquotes for callouts:
+   > ℹ️ **Info**: This is an info callout
+   > ⚠️ **Warning**: This is a warning
+   > ❌ **Error**: This is an error
+*/
+
+/* WYSIWYG Editor Styling */
+.w-md-editor {
+  background-color: white;
+}
+
+.w-md-editor-text-textarea,
+.w-md-editor-text {
+  font-size: 14px !important;
+  font-family: ui-monospace, SFMono-Regular, 'Cascadia Code', 'Roboto Mono', Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace !important;
 }
 
-.markdown-content details.spoiler {
-  @apply bg-gray-100/60 border border-gray-200 rounded-lg p-3 my-4;
+.w-md-editor-preview {
+  background-color: white;
 }
 
-.markdown-content details.spoiler summary {
-  @apply cursor-pointer font-semibold text-indigo-700;
+/* Custom toolbar styling */
+.w-md-editor-toolbar {
+  border-bottom: 1px solid #e5e7eb;
+  background-color: #f9fafb;
 }
 
-.markdown-content details.spoiler[open] {
-  @apply bg-gray-200/80;
-}
+.w-md-editor-toolbar-child button {
+  color: #374151;
+}
+
+.w-md-editor-toolbar-child button:hover {
+  background-color: #e5e7eb;
+}
+
+/* Editor content area */
+.w-md-editor-text-container {
+  border: none !important;
+}
+
+/* Preview styling to match our markdown content */
+.w-md-editor-preview .wmde-markdown {
+  padding: 16px;
+  color: #374151;
+  line-height: 1.75;
+}
+
+.w-md-editor-preview .wmde-markdown h1,
+.w-md-editor-preview .wmde-markdown h2,
+.w-md-editor-preview .wmde-markdown h3,
+.w-md-editor-preview .wmde-markdown h4,
+.w-md-editor-preview .wmde-markdown h5,
+.w-md-editor-preview .wmde-markdown h6 {
+  color: #1f2937;
+  font-weight: 700;
+}
+
+.w-md-editor-preview .wmde-markdown code {
+  background-color: #f3f4f6;
+  padding: 2px 4px;
+  border-radius: 4px;
+  font-size: 0.875em;
+}
+
+.w-md-editor-preview .wmde-markdown pre {
+  background-color: #f3f4f6;
+  border-radius: 8px;
+  padding: 16px;
+}
+
+.w-md-editor-preview .wmde-markdown blockquote {
+  border-left: 4px solid #3b82f6;
+  padding-left: 16px;
+  margin: 16px 0;
+  font-style: italic;
+  color: #6b7280;
+}
+
+.w-md-editor-preview .wmde-markdown table {
+  border-collapse: collapse;
+  width: 100%;
+  margin: 16px 0;
+}
+
+.w-md-editor-preview .wmde-markdown table th,
+.w-md-editor-preview .wmde-markdown table td {
+  border: 1px solid #d1d5db;
+  padding: 8px 12px;
+  text-align: left;
+}
+
+.w-md-editor-preview .wmde-markdown table th {
+  background-color: #f9fafb;
+  font-weight: 600;
+}
+
+/* Tab styling */
+.w-md-editor-tab {
+  background-color: #f3f4f6 !important;
+  color: #6b7280 !important;
+  border: 1px solid #d1d5db !important;
+}
+
+.w-md-editor-tab.active {
+  background-color: white !important;
+  color: #1f2937 !important;
+  border-bottom-color: white !important;
+}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio