diff --git a/.github/workflows/docs_test.yml b/.github/workflows/docs_test.yml index ad7671a446..e7f851801c 100644 --- a/.github/workflows/docs_test.yml +++ b/.github/workflows/docs_test.yml @@ -36,3 +36,48 @@ jobs: - name: Build docs run: cd docs && npm run build + + test-docs-accessibility: + name: Docs Accessibility (IBM Equal Access) + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + ref: ${{ inputs.branch || github.ref }} + + - name: Allow Chrome sandbox (Ubuntu 24.04 AppArmor restriction) + # Ubuntu 24.04 runners restrict unprivileged user namespaces, which + # breaks Chrome's sandbox (used by the IBM checker via puppeteer). + # This re-enables them — the documented GitHub Actions workaround. + run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + cache-dependency-path: ./docs/package-lock.json + + - name: Install dependencies + run: cd docs && npm install + + - name: Build docs (light theme) + run: cd docs && npm run build + + - name: Scan light theme + run: cd docs && ./scripts/a11y-ci.sh + + - name: Rebuild with dark theme as default + # The IBM CLI scans the page in its default color mode, so the dark + # scan flips the Docusaurus default and rebuilds (build-only change, + # nothing is committed). + run: | + cd docs + sed -i 's/defaultMode: "light"/defaultMode: "dark"/; s/respectPrefersColorScheme: true/respectPrefersColorScheme: false/' docusaurus.config.js + rm -rf build .docusaurus + npm run build + + - name: Scan dark theme + run: cd docs && ./scripts/a11y-ci.sh diff --git a/.gitignore b/.gitignore index 2d237df1ab..c619923a01 100644 --- a/.gitignore +++ b/.gitignore @@ -195,6 +195,9 @@ instance/ # Sphinx documentation docs/_build/ +# IBM Equal Access accessibility scan results +docs/a11y-results/ + # PyBuilder target/ diff --git a/docs/README.md b/docs/README.md index 19e3cb1173..da1597334b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,23 +24,17 @@ $ npm run build This command generates static content into the `build` directory and can be served using any static contents hosting service, including `npm run serve`. -### Import code snippets from the repo with a line range +### Import code snippets from the repo -To pull a slice of a file into the docs, source the content with `raw-loader` and present the code with the `CodeSnippet` component. -For a working example, see the [Components overview](/concepts-components#component-code). +To embed source files directly in the docs, use `raw-loader` to import the file as a string and pass it to the native `CodeBlock` component. ```mdx -import CodeSnippet from "@site/src/components/CodeSnippet"; +import CodeBlock from "@theme/CodeBlock"; import customComponent from "!!raw-loader!@langflow/src/lfx/src/lfx/custom/custom_component/custom_component.py"; - + + {customComponent} + ``` ## Docusaurus Versioning diff --git a/docs/aceconfig.js b/docs/aceconfig.js new file mode 100644 index 0000000000..0871beb3f8 --- /dev/null +++ b/docs/aceconfig.js @@ -0,0 +1,23 @@ +// IBM Equal Access accessibility-checker configuration +// https://github.com/IBMa/equal-access/tree/master/accessibility-checker +module.exports = { + // Pinned rule archive — keeps CI deterministic (IBM updates "latest" + // independently of this repo). Bump deliberately, like any dependency. + ruleArchive: "19May2026", + // IBM_Accessibility maps to WCAG 2.1 AA + IBM requirements + policies: ["IBM_Accessibility"], + // Fail levels: what makes the scan exit non-zero (kept to real violations) + failLevels: ["violation"], + // Report levels: what gets written to the reports + reportLevels: [ + "violation", + "potentialviolation", + "recommendation", + "potentialrecommendation", + "manual", + ], + outputFormat: ["json"], + outputFolder: "a11y-results", + // Don't fail the run when a newer rule archive exists + ignoreArchiveVersionCheck: true, +}; diff --git a/docs/css/code.css b/docs/css/code.css index 57791dc4cb..99c23257aa 100644 --- a/docs/css/code.css +++ b/docs/css/code.css @@ -1,7 +1,78 @@ -/* Geist Mono (and other ligature-enabled fonts) merge ~= into one glyph in inline code */ -code, -pre code { - font-variant-ligatures: none; +.theme-code-block { + box-shadow: none !important; + border: 1px solid #1e2128; + border-radius: var(--ifm-global-radius); + overflow: hidden; + margin-bottom: 1.5rem; +} + +/* Keep inline code vertically aligned with surrounding text */ +:not(pre) > code { + vertical-align: baseline; +} + +html[data-theme="light"] :not(pre) > code { + border: none; +} + +/* ===================================================================== + Langflow custom code theme — CSS variables (dark/light switching). + ===================================================================== */ +:root, +html[data-theme="dark"] { + --lf-ch-bg: #18181a; + --lf-ch-fg: #c8ccd4; + --lf-ch-line-num: #798197; + --lf-ch-selection: #264f78; + --lf-ch-border: #1e2128; + --lf-ch-title-bg: #0b0d10; + --lf-ch-comment: #798197; + --lf-ch-string: #51d0a5; + --lf-ch-number: #ff9b7d; + --lf-ch-boolean: #f7c93e; + --lf-ch-import: #c791f1; + --lf-ch-keyword: #ffffff; + --lf-ch-function: #ed86bf; + --lf-ch-decorator: #e45287; + --lf-ch-variable: #c8ccd4; +} + +html[data-theme="light"] { + --lf-ch-bg: #f9f9fd; + --lf-ch-fg: #64748b; + --lf-ch-line-num: #607491; + --lf-ch-selection: #e2e8f0; + --lf-ch-border: #e2e4f0; + --lf-ch-title-bg: #f0f0f8; + --lf-ch-comment: #607491; + --lf-ch-string: #04835c; + --lf-ch-number: #c74b0a; + --lf-ch-boolean: #ae5f05; + --lf-ch-import: #7c3aed; + --lf-ch-keyword: #077d9a; + --lf-ch-function: #d82474; + --lf-ch-decorator: #be185d; + --lf-ch-variable: #64748b; +} + + +/* Light mode: Prism / theme-code-block overrides */ +html[data-theme="light"] .theme-code-block { + border-color: #e2e4f0; +} + +html[data-theme="light"] .theme-code-block pre { + background-color: #f9f9fd !important; +} + +html[data-theme="light"] .theme-code-block code { + color: #64748b !important; +} + +html[data-theme="light"] .theme-code-block div[class*="codeBlockTitle"] { + background: #f0f0f8; + border-bottom-color: #e2e4f0; + color: #64748b; } .docusaurus-highlight-code-line { @@ -11,20 +82,6 @@ pre code { padding: 0 var(--ifm-pre-padding); } -.ch-scrollycoding-content { - max-width: 55% !important; - min-width: 40% !important; -} - -.ch-scrollycoding-sticker { - max-width: 60% !important; - min-width: 45% !important; -} - -.ch-scrollycoding-step-content { - min-height: 70px; -} - /* ======================================== Code Blocks - Enhanced (Langfuse style) ======================================== */ @@ -44,16 +101,14 @@ pre code { border-bottom-color: #303038; } -/* Code block container */ -.theme-code-block { - border: 1px solid var(--ifm-color-emphasis-200); - border-radius: var(--ifm-global-radius); - overflow: hidden; - margin-bottom: 1.5rem; + +.theme-code-block pre, +.theme-code-block code { + line-height: 1.7; } [data-theme="dark"] .theme-code-block { - border-color: #303038; + border-color: #1e2128; } /* Line highlighting in code blocks */ @@ -64,34 +119,3 @@ pre code { padding: 0 var(--ifm-pre-padding); border-left: 3px solid var(--ifm-color-primary); } - -/* Code Hike + CodeSnippet: Code Hike uses height:100% on .ch-codeblock > * and omits overflow on the - wrapper when measured; we shrink-wrap the block (fixes
/Collapsible height) and put - overflow on only so the copy button stays in the corner while scrolling long lines. */ -.markdown .ch-codeblock { - min-width: 0; - max-width: 100%; - height: fit-content; - align-self: flex-start; -} - -.markdown .ch-codeblock .ch-code-wrapper { - min-width: 0; - box-sizing: border-box; - height: fit-content !important; - max-height: none !important; - min-height: 0; -} - -.markdown .ch-codeblock .ch-code-wrapper > .ch-code-scroll-parent { - display: block; - overflow-x: auto; - overflow-y: auto; - max-width: 100%; - min-width: 0; -} - -.markdown .ch-codeblock .ch-code-button { - right: calc(10px + 0.75rem); - z-index: 2; -} diff --git a/docs/css/custom.css b/docs/css/custom.css index acb5916fec..d6c86d30b4 100644 --- a/docs/css/custom.css +++ b/docs/css/custom.css @@ -1,3 +1,4 @@ +@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;1,400&display=swap"); @import "./tokens.css"; @import "./layout.css"; @import "./navbar.css"; diff --git a/docs/css/redocusaurus.css b/docs/css/redocusaurus.css index 3fce69055c..897a58324d 100644 --- a/docs/css/redocusaurus.css +++ b/docs/css/redocusaurus.css @@ -1,55 +1,520 @@ /* ======================================== Redocusaurus / API Reference Pages + + NOTE: This file uses `!important` throughout because Redoc injects styles + via CSS-in-JS (Styled Components) with high specificity at runtime. + Plain selectors cannot override them — `!important` is intentional here. + + NOTE: Structural selectors (nth-child, first-child, etc.) target Redoc's + internal DOM layout. Tested against redocusaurus@2.5.0 / Redoc v2.x. + If Redoc is upgraded, verify these selectors still apply correctly. ======================================== */ -/* Remove Redoc's built-in left gutter so it aligns with the rest of the layout */ -.redocusaurus .menu-content { - padding-left: 0 !important; +/* ── Prevent horizontal scroll ───────────────────────────── */ +/* clip (not hidden) so position:sticky on sidebar/right panel still works */ + +html.plugin-redoc .main-wrapper { + overflow-x: clip; + width: 100%; } -/* Match sidebar font to site font */ -.redocusaurus .menu-content, -.redocusaurus [class*="SidebarDivider"], -.redocusaurus [class*="ApiItemName"] { +/* ── CSS custom properties ────────────────────────────────── */ +/* Centralizes all theme colors — change here, applies everywhere. */ + +html[data-theme='dark'] .redocusaurus { + --redoc-bg-primary: #111; + --redoc-bg-secondary: #18181b; + --redoc-bg-code: #161618; + --redoc-border-color: #303038; + --redoc-text-primary: #e3e3e3; + --redoc-text-muted: #cdcdd4; + --redoc-text-label: #ffffff; +} + +html[data-theme='light'] .redocusaurus { + --redoc-bg-primary: #f5f5f5; + --redoc-bg-secondary: #ffffff; + --redoc-bg-code: #f5f5f5; + --redoc-border-color: #e4e4e7; + --redoc-text-primary: #111827; + --redoc-text-muted: hsl(240, 4%, 46%); + --redoc-text-label: #111827; + /* Darkened brand pink — #f471b5 fails WCAG AA on light surfaces; + #cd1072 passes 4.5:1 on #fff, #f5f5f5, #ebebec and #f5f3f4 */ + --redoc-pink-a11y: #cd1072; +} + +/* ── Sidebar layout ───────────────────────────────────────── */ + +/* Redoc sets top:0 which overlaps the navbar */ +.redocusaurus .menu-content { + top: 60px !important; + padding-left: 0 !important; + border-right: none !important; font-family: var(--ifm-font-family-base) !important; } -/* Light theme Redoc sidebar */ -[data-theme="light"] .redocusaurus .menu-content { +/* ── Sidebar background ───────────────────────────────────── */ + +html[data-theme='dark'] .redocusaurus .menu-content { + background: var(--redoc-bg-secondary) !important; + border-right: 1px solid var(--redoc-border-color) !important; +} + +/* "API docs by Redocly" badge — position:fixed, background transparent from Redoc. + Give it a solid background so it renders above the sidebar. */ +html[data-theme='dark'] .redocusaurus a[href*="redocly"] { + background: var(--redoc-bg-secondary) !important; + display: block !important; + padding: 8px !important; + border-right: 1px solid var(--redoc-border-color) !important; +} + +html[data-theme='light'] .redocusaurus a[href*="redocly"] { background: var(--ifm-background-color) !important; - border-right: none !important; + display: block !important; + padding: 8px !important; + border-right: 1px solid var(--redoc-border-color) !important; } -/* Dark theme Redoc sidebar */ -[data-theme="dark"] .redocusaurus .menu-content { - background: #111 !important; - border-right: none !important; + +html[data-theme='light'] .redocusaurus .menu-content { + background: var(--ifm-background-color) !important; + border-right: 1px solid var(--redoc-border-color) !important; } -[data-theme="dark"] .redocusaurus { - background: #111 !important; +/* ── Sidebar active item ──────────────────────────────────── */ + +html[data-theme='dark'] .redocusaurus .menu-content label.active { + background-color: var(--redoc-bg-primary) !important; } -/* Redoc operation panels */ -[data-theme="dark"] .redocusaurus [class*="OperationTitle"], -[data-theme="dark"] .redocusaurus [class*="operation-type"] { - color: #cdcdd4; +html[data-theme='light'] .redocusaurus .menu-content label.active { + background-color: var(--redoc-bg-primary) !important; } -/* Redoc search input */ -.redocusaurus input[type="search"] { - border-radius: 8px; - font-family: var(--ifm-font-family-base); +/* ── Sidebar hover ────────────────────────────────────────── */ + +html[data-theme='light'] .redocusaurus .menu-content label:hover, +html[data-theme='light'] .redocusaurus .menu-content label:hover span:not([class*="operation-type"]), +html[data-theme='light'] .redocusaurus .menu-content li:hover > label { + color: var(--redoc-text-primary) !important; } -[data-theme="dark"] .redocusaurus input[type="search"] { - background: rgba(255, 255, 255, 0.04); - border-color: #303038; - color: #c6c6d1; +/* ── Central content background ───────────────────────────── */ + +html[data-theme='dark'] .redocusaurus { + background: var(--redoc-bg-primary) !important; } -/* Redoc code samples */ -[data-theme="dark"] .redocusaurus [class*="CodeSample"] pre { - background: #161618 !important; - border: 1px solid #303038; +html[data-theme='light'] .redocusaurus { + background: var(--redoc-bg-primary) !important; +} + +/* ── Dark theme headings ──────────────────────────────────── */ + +html[data-theme='dark'] .redocusaurus h1, +html[data-theme='dark'] .redocusaurus h2, +html[data-theme='dark'] .redocusaurus h3, +html[data-theme='dark'] .redocusaurus h4, +html[data-theme='dark'] .redocusaurus h5, +html[data-theme='dark'] .redocusaurus h6 { + color: var(--redoc-text-primary) !important; +} + +/* ── Expanded response/schema content background ──────────── */ +/* redocusaurus@2.5.0: button+div is the expanded schema panel */ + +html[data-theme='dark'] .redocusaurus div[id^='tag'] button + div, +html[data-theme='dark'] .redocusaurus div[id^='operation'] button + div { + background-color: var(--redoc-bg-secondary) !important; +} + +html[data-theme='light'] .redocusaurus div[id^='tag'] button + div, +html[data-theme='light'] .redocusaurus div[id^='operation'] button + div { + background-color: var(--redoc-bg-secondary) !important; +} + +/* ── Right panel background ───────────────────────────────── */ +/* redocusaurus@2.5.0: nth-child(2) of tag/operation is the right panel */ + +html[data-theme='dark'] .redocusaurus .api-content > div > div:nth-child(2), +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2), +html[data-theme='dark'] .redocusaurus div[id^='tag'] > div > div:nth-child(2) { + background: var(--redoc-bg-primary) !important; +} + +html[data-theme='light'] .redocusaurus .api-content > div > div:nth-child(2), +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2), +html[data-theme='light'] .redocusaurus div[id^='tag'] > div > div:nth-child(2), +html[data-theme='light'] .redocusaurus [class*="RightPanel"] { + background: var(--redoc-bg-primary) !important; +} + +/* ── HTTP method button wrapper ───────────────────────────── */ +/* redocusaurus@2.5.0: nth-child(1) of the right panel */ + +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(1) { + background: var(--redoc-bg-secondary) !important; + border: 1px solid var(--redoc-border-color) !important; + border-radius: 8px !important; +} + +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(1) { + background: var(--redoc-bg-secondary) !important; + border: 1px solid var(--redoc-border-color) !important; + border-radius: 8px !important; +} + +/* ── HTTP method button ───────────────────────────────────── */ +/* redocusaurus@2.5.0: button inside div:first-child of the right panel */ + +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:first-child > button { + background: var(--redoc-bg-secondary) !important; + border: none !important; + border-radius: 8px !important; + box-shadow: none !important; +} + +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:first-child > button { + background: var(--redoc-bg-secondary) !important; + border: none !important; + border-radius: 8px !important; + box-shadow: none !important; + color: var(--redoc-text-muted) !important; +} + +/* ── HTTP method dropdown ──────────────────────────────────── */ +/* redocusaurus@2.5.0: div>div inside the button wrapper */ + +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(1) > div > div { + background: var(--redoc-bg-secondary) !important; + border: 1px solid var(--redoc-border-color) !important; + border-bottom-left-radius: 8px !important; + border-bottom-right-radius: 8px !important; + box-shadow: none !important; + border-top: none !important; +} + +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(1) > div > div { + border-bottom-left-radius: 8px !important; + border-bottom-right-radius: 8px !important; + box-shadow: none !important; + border-top: none !important; +} + +/* ── Request + Response cards ─────────────────────────────── */ +/* redocusaurus@2.5.0: nth-child(2) and nth-child(3) of the right panel */ + +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(2), +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(3) { + background: var(--redoc-bg-secondary) !important; + border: 1px solid var(--redoc-border-color) !important; + border-radius: 12px !important; + overflow: hidden !important; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5) !important; + margin-top: 12px !important; +} + +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(2), +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(3) { + background: var(--redoc-bg-secondary) !important; + border: 1px solid var(--redoc-border-color) !important; + border-radius: 12px !important; + overflow: hidden !important; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08) !important; + margin-top: 12px !important; +} + +/* ── Status code tabs ─────────────────────────────────────── */ + +.redocusaurus .react-tabs__tab-list { + padding: 0 20px !important; + margin-top: 4px; +} + +html[data-theme='dark'] .redocusaurus .tab-success, +html[data-theme='dark'] .redocusaurus .tab-error, +html[data-theme='dark'] .redocusaurus .react-tabs__tab--selected { + background: var(--redoc-bg-secondary) !important; + border-color: var(--redoc-border-color) !important; +} + +html[data-theme='light'] .redocusaurus .tab-success, +html[data-theme='light'] .redocusaurus .tab-error, +html[data-theme='light'] .redocusaurus .react-tabs__tab--selected { + background: var(--redoc-bg-secondary) !important; + border-color: var(--redoc-border-color) !important; +} + +/* ── Card title (h3) ──────────────────────────────────────── */ +/* redocusaurus@2.5.0: h3 direct child of nth-child(2/3) of right panel */ + +.redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(2) > h3 ~ div, +.redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(3) > h3 ~ div { + padding-top: 8px !important; + padding-bottom: 8px !important; +} + +.redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(2) > h3, +.redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(3) > h3 { + padding-top: 12px !important; + padding-left: 16px !important; + padding-bottom: 12px !important; + margin: 0 !important; +} + +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(2) > h3, +html[data-theme='dark'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(3) > h3 { + border-bottom: 1px solid var(--redoc-border-color) !important; +} + +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(2) > h3, +html[data-theme='light'] .redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(3) > h3 { + border-bottom: 1px solid var(--redoc-border-color) !important; + color: var(--redoc-text-primary) !important; +} + +/* ── Tab panel content ────────────────────────────────────── */ +/* redocusaurus@2.5.0: structural selectors for content type / example area */ + +.redocusaurus .react-tabs__tab-panel--selected > div { + padding-top: 8px !important; + padding-bottom: 8px !important; +} + +.redocusaurus .react-tabs__tab-panel--selected > div > div, +.redocusaurus .react-tabs__tab-panel--selected > div > div > div:not(:last-child) { + display: flex !important; + flex-direction: column !important; + gap: 0.5rem !important; +} + +.redocusaurus .react-tabs__tab-panel--selected > div > div:nth-child(2) { + margin-top: 8px !important; +} + +/* Content type / Example labels */ +html[data-theme='dark'] .redocusaurus .react-tabs__tab-panel--selected > div > div > span, +html[data-theme='dark'] .redocusaurus .react-tabs__tab-panel--selected > div > div:nth-child(2) > div > span { + position: static !important; + font-size: 0.875rem !important; + color: var(--redoc-text-label) !important; +} + +html[data-theme='light'] .redocusaurus .react-tabs__tab-panel--selected > div > div > span, +html[data-theme='light'] .redocusaurus .react-tabs__tab-panel--selected > div > div:nth-child(2) > div > span { + position: static !important; + font-size: 0.875rem !important; + color: var(--redoc-text-primary) !important; +} + +/* Content type / Example value borders + text color */ +html[data-theme='dark'] .redocusaurus .react-tabs__tab-panel--selected > div > div:first-of-type > div:first-of-type, +html[data-theme='dark'] .redocusaurus .react-tabs__tab-panel--selected > div > div:nth-child(2) > div:last-child, +html[data-theme='dark'] .redocusaurus .react-tabs__tab-panel--selected > div > div:nth-child(2) > div:not(:last-child) > div { + border: 1px solid var(--redoc-border-color) !important; + border-radius: 6px !important; + background: transparent !important; + min-height: 20px !important; + padding: 8px !important; + color: var(--redoc-text-muted) !important; +} + +html[data-theme='light'] .redocusaurus .react-tabs__tab-panel--selected > div > div:first-of-type > div:first-of-type, +html[data-theme='light'] .redocusaurus .react-tabs__tab-panel--selected > div > div:nth-child(2) > div:last-child, +html[data-theme='light'] .redocusaurus .react-tabs__tab-panel--selected > div > div:nth-child(2) > div:not(:last-child) > div { + border: 1px solid var(--redoc-border-color) !important; + border-radius: 6px !important; + background: transparent !important; + min-height: 20px !important; + padding: 8px !important; + color: var(--redoc-text-muted) !important; +} + +/* Tab panel transparent so card bg shows through */ +.redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(2) .react-tabs__tab-panel--selected, +.redocusaurus div[id^='operation'] > div:nth-child(2) > div:nth-child(3) .react-tabs__tab-panel--selected { + background: transparent !important; +} + +/* ── Light theme syntax highlighting ──────────────────────── */ +/* All colors pass WCAG AA (4.5:1) on white sample backgrounds */ + +html[data-theme='light'] .redocusaurus .token.keyword { + color: #b75868 !important; +} + +html[data-theme='light'] .redocusaurus .token.punctuation { + color: rgb(113, 113, 122) !important; +} + +html[data-theme='light'] .redocusaurus .token.boolean, +html[data-theme='light'] .redocusaurus .token.null { + color: #e32c29 !important; +} + +html[data-theme='light'] .redocusaurus .token.number, +html[data-theme='light'] .redocusaurus .token.constant { + color: #427ca0 !important; +} + +html[data-theme='light'] .redocusaurus .token.literal-property.property, +html[data-theme='light'] .redocusaurus .token.string-property.property { + color: #427ca0 !important; +} + +html[data-theme='light'] .redocusaurus .token.string { + color: rgb(22, 130, 50) !important; +} + +html[data-theme='light'] .redocusaurus .token.operator { + color: #9f6d08 !important; +} + +html[data-theme='light'] .redocusaurus .token.property { + color: var(--redoc-text-muted) !important; +} + +/* ── Operation divider ────────────────────────────────────── */ + +.redocusaurus .api-content > div:not(:last-of-type)::after { + display: none !important; +} + +/* ── Light theme WCAG contrast overrides ──────────────────── */ +/* Redoc renders these with #f471b5 / #9c9ca2, which fail 4.5:1 on + light surfaces. Dark theme is unaffected (colors pass there). */ + +/* Inline code in descriptions (typography.code.color from config) */ +html[data-theme='light'] .redocusaurus *:not(pre) > code { + color: var(--redoc-pink-a11y) !important; +} + +/* "required" labels in schema tables (schema.requireLabelColor) */ +html[data-theme='light'] .redocusaurus td[kind='field'] > div { + color: var(--redoc-pink-a11y) !important; +} + +/* Classless utility buttons (Expand all / Collapse all, etc.). + Redoc dims their wrapper div to 0.7, lightening the effective color — + restore full opacity on the wrapper, not the button */ +html[data-theme='light'] .redocusaurus button:not([class]) { + color: #6c6c74 !important; +} + +html[data-theme='light'] .redocusaurus div:has(> button:not([class])) { + opacity: 1 !important; +} + +/* Links (Download button, server URLs) — primaryColor fails on light */ +html[data-theme='light'] .redocusaurus .api-content a { + color: var(--redoc-pink-a11y) !important; +} + +/* Schema tree lines (schema.linesColor #F471B5) — align with the + accessible pink on light so all pinks on the page match */ +html[data-theme='light'] .redocusaurus td[kind='field'] { + border-left-color: var(--redoc-pink-a11y) !important; +} + +html[data-theme='light'] .redocusaurus td[kind='field'] > span:not(.property-name)::before, +html[data-theme='light'] .redocusaurus td[kind='field'] > span:not(.property-name)::after { + background-color: var(--redoc-pink-a11y) !important; +} + +/* Expandable property names render inside a classless