mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-14 17:52:32 -06:00
18ca19044c
Follow-up to #27495, reopened as a high contrast mode change. Builds on the `high-contrast` class landed in #27555. Muted UI text is written as text-gray-400 dark:text-gray-600. The grey scale in src/tailwind.css is achromatic oklch(L 0 0), so relative luminance is exactly L³: text-gray-400 is 2.07:1 on white and dark:text-gray-600 is 3.12:1 on #171717. The pair is effectively inverted, and both halves fail the 4.5:1 required by WCAG 1.4.3, with the light value also failing the 3:1 required of icons under 1.4.11. This is the text used for settings and admin section headings, field descriptions, sidebar labels, timestamps and counters, all at 10px to 12px, so the large-text exemption does not apply. Rather than rewriting the class literal at 251 sites, the remap is two CSS rules that only apply when the existing High Contrast Mode setting is on, so the default theme is untouched: - text-gray-400 resolves to gray-600 (5.75:1) in light mode - dark:text-gray-600 resolves to gray-400 (8.65:1) in dark mode dark:text-gray-500 already passes at 6.46:1 and is left alone. The rules live in `@layer utilities` and use `:where()` to stay at low specificity: they outrank the base utility but lose to `hover:` and `dark:hover:` variants, so hover feedback keeps working. Verified in a browser against Tailwind's emitted rules and layer order: with the setting on, resting text resolves to gray-600 in light and gray-400 in dark, hover still resolves to its own value, and with the setting off nothing changes in either theme. One component change is required alongside it. In admin/Settings/Audio.svelte the help text puts links inside the muted block via `[&_a]:text-gray-600`; once the surrounding prose resolves to gray-600 the link becomes the same colour as the text it sits in, and it has no resting underline, which would be a new WCAG 1.4.1 failure. The link moves to gray-900. This is the only place in the codebase where a link colour is nested inside muted text. Letting the variants win has one edge: a few elements hover to a grey lighter than their new resting colour, so hovering would have lowered contrast instead of raising it. A light-mode hover landing on gray-500 now resolves to gray-800, which keeps the hover darker than the gray-600 resting state. Sidebar/Section.svelte is the site this branch would otherwise break. Not covered here: text-gray-500 dark:text-gray-400 (2.77:1 in light), which is a separate branch.
887 lines
19 KiB
CSS
887 lines
19 KiB
CSS
@reference "./tailwind.css";
|
|
|
|
@font-face {
|
|
font-family: 'Inter';
|
|
src: url('/assets/fonts/Inter-Variable.ttf');
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Vazirmatn';
|
|
src: url('/assets/fonts/Vazirmatn-Variable.ttf');
|
|
font-display: swap;
|
|
}
|
|
|
|
/* --app-text-scale is updated via the UI Scale slider (Interface.svelte) */
|
|
:root {
|
|
--app-text-scale: 1;
|
|
}
|
|
|
|
html {
|
|
word-break: break-word;
|
|
/* font-size scales the entire document via the same UI control */
|
|
font-size: calc(1rem * var(--app-text-scale, 1));
|
|
}
|
|
|
|
#sidebar-chat-item {
|
|
/* sidebar item sizing scales for the chat list entries */
|
|
min-height: calc(32px * var(--app-text-scale, 1));
|
|
padding-inline: calc(11px * var(--app-text-scale, 1));
|
|
padding-block: calc(6px * var(--app-text-scale, 1));
|
|
}
|
|
|
|
#sidebar-chat-item div[dir='auto'] {
|
|
/* chat title line height follows the text scale */
|
|
height: calc(20px * var(--app-text-scale, 1));
|
|
line-height: calc(20px * var(--app-text-scale, 1));
|
|
}
|
|
|
|
#sidebar-chat-item input {
|
|
/* editing state input height is kept in sync */
|
|
min-height: calc(20px * var(--app-text-scale, 1));
|
|
}
|
|
|
|
code {
|
|
/* white-space-collapse: preserve !important; */
|
|
overflow-x: auto;
|
|
width: auto;
|
|
}
|
|
|
|
.editor-selection {
|
|
background: rgba(180, 213, 255, 0.5);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.app-muted {
|
|
@apply text-gray-500 dark:text-gray-400;
|
|
}
|
|
|
|
.app-icon-muted {
|
|
@apply text-gray-500 dark:text-gray-400;
|
|
}
|
|
|
|
.app-interactive-active {
|
|
@apply bg-gray-50/40 dark:bg-gray-800/40;
|
|
}
|
|
|
|
.marked a {
|
|
@apply underline;
|
|
}
|
|
|
|
math {
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.hljs {
|
|
@apply rounded-lg;
|
|
}
|
|
|
|
input::placeholder {
|
|
direction: auto;
|
|
}
|
|
|
|
textarea::placeholder {
|
|
direction: auto;
|
|
}
|
|
|
|
textarea {
|
|
color-scheme: light;
|
|
}
|
|
|
|
.dark textarea {
|
|
color-scheme: dark;
|
|
}
|
|
|
|
textarea::-webkit-resizer,
|
|
textarea::-webkit-scrollbar-corner {
|
|
background: transparent;
|
|
}
|
|
|
|
.input-prose {
|
|
@apply prose dark:prose-invert !text-[0.9375rem] prose-headings:font-normal prose-hr:my-4 prose-hr:border-gray-50 prose-hr:dark:border-gray-850 prose-p:my-1 prose-img:my-1 prose-headings:my-2 prose-pre:my-0 prose-table:my-1 prose-blockquote:my-0 prose-ul:my-1 prose-ol:my-1 prose-li:my-0.5 whitespace-pre-line;
|
|
}
|
|
|
|
.input-prose-sm {
|
|
@apply prose dark:prose-invert prose-headings:font-normal prose-h1:text-2xl prose-h2:text-xl prose-h3:text-lg prose-hr:my-4 prose-hr:border-gray-50 prose-hr:dark:border-gray-850 prose-p:my-1 prose-img:my-1 prose-headings:my-2 prose-pre:my-0 prose-table:my-1 prose-blockquote:my-0 prose-ul:my-1 prose-ol:my-1 prose-li:my-1 whitespace-pre-line text-sm;
|
|
}
|
|
|
|
.markdown-prose {
|
|
@apply prose prose-sm dark:prose-invert max-w-none break-words !text-[0.9375rem] font-normal leading-relaxed prose-p:mt-0 prose-p:mb-2 prose-p:font-normal prose-p:leading-relaxed prose-headings:mt-2 prose-headings:mb-1 prose-headings:font-normal prose-headings:leading-snug prose-h1:text-xl prose-h2:text-lg prose-h3:text-base prose-strong:font-medium prose-code:before:content-none prose-code:after:content-none prose-ul:my-2 prose-ol:my-2 prose-li:my-0.5 prose-li:font-normal prose-pre:my-3 prose-table:my-0 prose-blockquote:my-3 prose-blockquote:font-normal prose-hr:my-4 prose-hr:border-gray-50 prose-hr:dark:border-gray-850/30 prose-img:my-2 [&>:first-child]:mt-0 [&>:last-child]:mb-0 [&_p:first-child]:mt-0 [&_h1:first-child]:mt-0 [&_h2:first-child]:mt-0 [&_h3:first-child]:mt-0 [&_h4:first-child]:mt-0 [&_h5:first-child]:mt-0 [&_h6:first-child]:mt-0;
|
|
}
|
|
|
|
.markdown-prose-sm {
|
|
@apply text-sm prose dark:prose-invert prose-blockquote:border-s-gray-100 prose-blockquote:dark:border-gray-800 prose-blockquote:border-s-2 prose-blockquote:not-italic prose-blockquote:font-normal prose-headings:font-normal prose-hr:my-2 prose-hr:border-gray-50 prose-hr:dark:border-gray-850 prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-0 prose-ol:-my-0 prose-li:-my-0 whitespace-pre-line;
|
|
}
|
|
|
|
.markdown-prose-xs {
|
|
@apply text-xs prose dark:prose-invert prose-blockquote:border-s-gray-100 prose-blockquote:dark:border-gray-800 prose-blockquote:border-s-2 prose-blockquote:not-italic prose-blockquote:font-normal prose-headings:font-normal prose-hr:my-0.5 prose-hr:border-gray-50 prose-hr:dark:border-gray-850 prose-p:my-0 prose-img:my-1 prose-headings:my-1 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-ul:-my-0 prose-ol:-my-0 prose-li:-my-0 whitespace-pre-line;
|
|
}
|
|
|
|
.markdown a {
|
|
@apply underline;
|
|
}
|
|
|
|
.drag-region {
|
|
-webkit-app-region: drag;
|
|
}
|
|
|
|
.drag-region a,
|
|
.drag-region button {
|
|
-webkit-app-region: no-drag;
|
|
}
|
|
|
|
.no-drag-region {
|
|
-webkit-app-region: no-drag;
|
|
}
|
|
|
|
li p {
|
|
display: inline;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
--tw-border-opacity: 1;
|
|
background-color: rgba(215, 215, 215, 0.6);
|
|
border-color: rgba(255, 255, 255, var(--tw-border-opacity));
|
|
border-radius: 9999px;
|
|
border-width: 1px;
|
|
}
|
|
|
|
/* Dark theme scrollbar styles */
|
|
.dark ::-webkit-scrollbar-thumb {
|
|
background-color: rgba(67, 67, 67, 0.6); /* Darker color for dark theme */
|
|
border-color: rgba(0, 0, 0, var(--tw-border-opacity));
|
|
}
|
|
|
|
::-webkit-scrollbar {
|
|
height: 0.45rem;
|
|
width: 0.45rem;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background-color: transparent;
|
|
border-radius: 9999px;
|
|
}
|
|
|
|
select {
|
|
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");
|
|
background-position: right 0rem center;
|
|
background-repeat: no-repeat;
|
|
background-size: 1.5em 1.5em;
|
|
-webkit-print-color-adjust: exact;
|
|
print-color-adjust: exact;
|
|
/* padding-right: 2.5rem; */
|
|
/* for Firefox */
|
|
-moz-appearance: none;
|
|
/* for Chrome */
|
|
-webkit-appearance: none;
|
|
}
|
|
|
|
.dark select:not([class*='bg-transparent']) {
|
|
@apply bg-gray-900 text-gray-300;
|
|
}
|
|
|
|
.dark select option {
|
|
@apply bg-gray-850 text-white;
|
|
}
|
|
|
|
@keyframes shimmer {
|
|
0% {
|
|
background-position: 100% 0;
|
|
}
|
|
100% {
|
|
background-position: -100% 0;
|
|
}
|
|
}
|
|
|
|
.shimmer {
|
|
background: linear-gradient(
|
|
110deg,
|
|
#b4b4b4 0%,
|
|
#b4b4b4 43%,
|
|
#e8e8e8 50%,
|
|
#b4b4b4 57%,
|
|
#b4b4b4 100%
|
|
);
|
|
background-size: 200% 100%;
|
|
background-clip: text;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
animation: shimmer 1.5s cubic-bezier(0.7, 0, 1, 0.4) infinite;
|
|
color: #b4b4b4;
|
|
}
|
|
|
|
:global(.dark) .shimmer {
|
|
background: linear-gradient(
|
|
110deg,
|
|
#9a9a9a 0%,
|
|
#9a9a9a 43%,
|
|
#5e5e5e 50%,
|
|
#9a9a9a 57%,
|
|
#9a9a9a 100%
|
|
);
|
|
background-size: 200% 100%;
|
|
background-clip: text;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
animation: shimmer 1.5s cubic-bezier(0.7, 0, 1, 0.4) infinite;
|
|
color: #9a9a9a;
|
|
}
|
|
|
|
@keyframes smoothFadeIn {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(-10px);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.status-description {
|
|
animation: smoothFadeIn 0.2s forwards;
|
|
}
|
|
|
|
@keyframes fade-in-token {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.fade-in-token {
|
|
animation: fade-in-token 100ms ease-out;
|
|
}
|
|
|
|
.katex-mathml {
|
|
display: none;
|
|
}
|
|
|
|
/* Hide leaked Mermaid temp containers if render cleanup misses.
|
|
Use visibility:hidden (not display:none) so mermaid can still
|
|
measure the SVG layout before extracting its HTML. */
|
|
body > div[id^='dmermaid-'],
|
|
body > iframe[id^='imermaid-'] {
|
|
position: fixed !important;
|
|
visibility: hidden !important;
|
|
height: 0 !important;
|
|
overflow: hidden !important;
|
|
}
|
|
|
|
.scrollbar-hidden:active::-webkit-scrollbar-thumb,
|
|
.scrollbar-hidden:focus::-webkit-scrollbar-thumb,
|
|
.scrollbar-hidden:hover::-webkit-scrollbar-thumb {
|
|
visibility: visible;
|
|
}
|
|
.scrollbar-hidden::-webkit-scrollbar-thumb {
|
|
visibility: hidden;
|
|
}
|
|
|
|
.scrollbar-hidden::-webkit-scrollbar-corner {
|
|
display: none;
|
|
}
|
|
|
|
.scrollbar-none::-webkit-scrollbar {
|
|
display: none; /* for Chrome, Safari and Opera */
|
|
}
|
|
|
|
.scrollbar-none::-webkit-scrollbar-corner {
|
|
display: none;
|
|
}
|
|
|
|
.scrollbar-none {
|
|
-ms-overflow-style: none; /* IE and Edge */
|
|
scrollbar-width: none; /* Firefox */
|
|
}
|
|
|
|
input::-webkit-outer-spin-button,
|
|
input::-webkit-inner-spin-button {
|
|
/* display: none; <- Crashes Chrome on hover */
|
|
-webkit-appearance: none;
|
|
margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
|
|
}
|
|
|
|
input[type='number'] {
|
|
-moz-appearance: textfield; /* Firefox */
|
|
}
|
|
|
|
.katex-display {
|
|
@apply overflow-y-hidden overflow-x-auto max-w-full;
|
|
}
|
|
|
|
.katex-display::-webkit-scrollbar {
|
|
height: 0.4rem;
|
|
width: 0.4rem;
|
|
}
|
|
|
|
.katex-display:active::-webkit-scrollbar-thumb,
|
|
.katex-display:focus::-webkit-scrollbar-thumb,
|
|
.katex-display:hover::-webkit-scrollbar-thumb {
|
|
visibility: visible;
|
|
}
|
|
.katex-display::-webkit-scrollbar-thumb {
|
|
visibility: hidden;
|
|
}
|
|
|
|
.katex-display::-webkit-scrollbar-corner {
|
|
display: none;
|
|
}
|
|
|
|
.cm-editor {
|
|
height: 100%;
|
|
width: 100%;
|
|
}
|
|
|
|
.cm-scroller:active::-webkit-scrollbar-thumb,
|
|
.cm-scroller:focus::-webkit-scrollbar-thumb,
|
|
.cm-scroller:hover::-webkit-scrollbar-thumb {
|
|
visibility: visible;
|
|
}
|
|
|
|
.cm-scroller::-webkit-scrollbar-thumb {
|
|
visibility: hidden;
|
|
}
|
|
|
|
.cm-scroller::-webkit-scrollbar-corner {
|
|
display: none;
|
|
}
|
|
|
|
.cm-editor.cm-focused {
|
|
outline: none;
|
|
}
|
|
|
|
.cm-gutters {
|
|
@apply !bg-white dark:!bg-black !border-none;
|
|
}
|
|
|
|
.cm-editor {
|
|
@apply bg-white dark:bg-black;
|
|
}
|
|
|
|
.tippy-box[data-theme~='dark'] {
|
|
@apply rounded-lg bg-gray-950 text-xs border border-gray-900 shadow-xl;
|
|
}
|
|
|
|
.password {
|
|
-webkit-text-security: disc;
|
|
}
|
|
|
|
.codespan {
|
|
padding: 0.15rem 0.3rem;
|
|
font-size: 0.85em;
|
|
@apply font-mono rounded-md text-gray-800 bg-gray-100 dark:text-gray-200 dark:bg-gray-800 mx-0.5;
|
|
}
|
|
|
|
.svelte-flow {
|
|
background-color: transparent !important;
|
|
}
|
|
|
|
.svelte-flow__edge > path {
|
|
stroke-width: 0.5;
|
|
}
|
|
|
|
.svelte-flow__edge.animated > path {
|
|
stroke-width: 2;
|
|
@apply stroke-gray-600 dark:stroke-gray-500;
|
|
}
|
|
|
|
.bg-gray-950-90 {
|
|
background-color: rgba(var(--color-gray-950, #0d0d0d), 0.9);
|
|
}
|
|
|
|
.ProseMirror {
|
|
@apply h-full min-h-fit max-h-full whitespace-pre-wrap;
|
|
}
|
|
|
|
.ProseMirror:focus {
|
|
outline: none;
|
|
}
|
|
|
|
.ProseMirror p.is-editor-empty:first-child::before {
|
|
content: attr(data-placeholder);
|
|
float: left;
|
|
/* Below color is from tailwind, and has the proper contrast
|
|
text-gray-600 from: https://tailwindcss.com/docs/color */
|
|
color: #676767;
|
|
pointer-events: none;
|
|
|
|
@apply line-clamp-1 absolute;
|
|
}
|
|
|
|
/* #676767 is 3.17:1 on the dark canvas; the light value already passes. */
|
|
html.high-contrast.dark .ProseMirror p.is-editor-empty:first-child::before {
|
|
color: var(--color-gray-500);
|
|
}
|
|
|
|
.tiptap ul[data-type='taskList'] {
|
|
list-style: none;
|
|
margin-left: 0;
|
|
padding: 0;
|
|
|
|
li {
|
|
align-items: start;
|
|
display: flex;
|
|
|
|
> label {
|
|
flex: 0 0 auto;
|
|
margin-right: 0.5rem;
|
|
margin-top: 0.2rem;
|
|
user-select: none;
|
|
display: flex;
|
|
}
|
|
|
|
> div {
|
|
flex: 1 1 auto;
|
|
|
|
align-items: center;
|
|
}
|
|
}
|
|
|
|
/* checked data-checked="true" */
|
|
|
|
li[data-checked='true'] {
|
|
> div {
|
|
opacity: 0.5;
|
|
text-decoration: line-through;
|
|
}
|
|
}
|
|
|
|
input[type='checkbox'] {
|
|
cursor: pointer;
|
|
}
|
|
|
|
ul[data-type='taskList'] {
|
|
margin: 0;
|
|
}
|
|
|
|
/* Reset nested regular ul elements to default styling */
|
|
ul:not([data-type='taskList']) {
|
|
list-style: disc;
|
|
padding-left: 1rem;
|
|
|
|
li {
|
|
align-items: initial;
|
|
display: list-item;
|
|
|
|
label {
|
|
flex: initial;
|
|
margin-right: initial;
|
|
margin-top: initial;
|
|
user-select: initial;
|
|
display: initial;
|
|
}
|
|
|
|
div {
|
|
flex: initial;
|
|
align-items: initial;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.mention {
|
|
border-radius: 0.4rem;
|
|
box-decoration-break: clone;
|
|
padding: 0.1rem 0.3rem;
|
|
@apply text-sky-800 dark:text-sky-200 bg-sky-300/15 dark:bg-sky-500/15;
|
|
}
|
|
|
|
.mention::after {
|
|
content: '\200B';
|
|
}
|
|
|
|
.tiptap .suggestion {
|
|
border-radius: 0.4rem;
|
|
box-decoration-break: clone;
|
|
padding: 0.1rem 0.3rem;
|
|
@apply text-sky-800 dark:text-sky-200 bg-sky-300/15 dark:bg-sky-500/15;
|
|
}
|
|
|
|
.tiptap .suggestion::after {
|
|
content: '\200B';
|
|
}
|
|
|
|
.tiptap .suggestion.is-empty::after {
|
|
content: '\00A0';
|
|
border-bottom: 1px dotted rgba(31, 41, 55, 0.12);
|
|
}
|
|
|
|
.input-prose .tiptap ul[data-type='taskList'] {
|
|
list-style: none;
|
|
margin-left: 0;
|
|
padding: 0;
|
|
|
|
li {
|
|
align-items: start;
|
|
display: flex;
|
|
|
|
> label {
|
|
flex: 0 0 auto;
|
|
margin-right: 0.5rem;
|
|
margin-top: 0.4rem;
|
|
user-select: none;
|
|
display: flex;
|
|
}
|
|
|
|
> div {
|
|
flex: 1 1 auto;
|
|
|
|
align-items: center;
|
|
}
|
|
}
|
|
|
|
/* checked data-checked="true" */
|
|
|
|
li[data-checked='true'] {
|
|
> div {
|
|
opacity: 0.5;
|
|
text-decoration: line-through;
|
|
}
|
|
}
|
|
|
|
input[type='checkbox'] {
|
|
cursor: pointer;
|
|
}
|
|
|
|
ul[data-type='taskList'] {
|
|
margin: 0;
|
|
}
|
|
|
|
/* Reset nested regular ul elements to default styling */
|
|
ul:not([data-type='taskList']) {
|
|
list-style: disc;
|
|
padding-left: 1rem;
|
|
|
|
li {
|
|
align-items: initial;
|
|
display: list-item;
|
|
|
|
label {
|
|
flex: initial;
|
|
margin-right: initial;
|
|
margin-top: initial;
|
|
user-select: initial;
|
|
display: initial;
|
|
}
|
|
|
|
div {
|
|
flex: initial;
|
|
align-items: initial;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
.ProseMirror p.is-editor-empty:first-child::before {
|
|
color: #757575;
|
|
}
|
|
}
|
|
|
|
.ai-autocompletion::after {
|
|
color: #a0a0a0;
|
|
|
|
content: attr(data-suggestion);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.tiptap pre > code {
|
|
border-radius: 0.4rem;
|
|
font-size: 0.85rem;
|
|
padding: 0.25em 0.3em;
|
|
|
|
@apply dark:bg-gray-800 bg-gray-50;
|
|
}
|
|
|
|
.tiptap pre {
|
|
border-radius: 0.5rem;
|
|
font-family: 'JetBrainsMono', monospace;
|
|
margin: 1.5rem 0;
|
|
padding: 0.75rem 1rem;
|
|
|
|
@apply dark:bg-gray-800 bg-gray-50;
|
|
}
|
|
|
|
.tiptap p code {
|
|
padding: 0.15rem 0.3rem;
|
|
font-size: 0.85em;
|
|
@apply font-mono rounded-md text-gray-800 bg-gray-50 dark:text-gray-200 dark:bg-gray-800 mx-0.5;
|
|
}
|
|
|
|
/* Code styling */
|
|
.hljs-comment,
|
|
.hljs-quote {
|
|
color: #616161;
|
|
}
|
|
|
|
.hljs-variable,
|
|
.hljs-template-variable,
|
|
.hljs-attribute,
|
|
.hljs-tag,
|
|
.hljs-regexp,
|
|
.hljs-link,
|
|
.hljs-name,
|
|
.hljs-selector-id,
|
|
.hljs-selector-class {
|
|
color: #f98181;
|
|
}
|
|
|
|
.hljs-number,
|
|
.hljs-meta,
|
|
.hljs-built_in,
|
|
.hljs-builtin-name,
|
|
.hljs-literal,
|
|
.hljs-type,
|
|
.hljs-params {
|
|
color: #fbbc88;
|
|
}
|
|
|
|
.hljs-string,
|
|
.hljs-symbol,
|
|
.hljs-bullet {
|
|
color: #b9f18d;
|
|
}
|
|
|
|
.hljs-title,
|
|
.hljs-section {
|
|
color: #faf594;
|
|
}
|
|
|
|
.hljs-keyword,
|
|
.hljs-selector-tag {
|
|
color: #70cff8;
|
|
}
|
|
|
|
.hljs-emphasis {
|
|
font-style: italic;
|
|
}
|
|
|
|
.hljs-strong {
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* Table styling for tiptap editors */
|
|
.tiptap table {
|
|
@apply w-full text-sm text-start text-gray-500 dark:text-gray-400 max-w-full;
|
|
}
|
|
|
|
.tiptap thead {
|
|
@apply text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-850 dark:text-gray-400 border-none;
|
|
}
|
|
|
|
.tiptap th,
|
|
.tiptap td {
|
|
@apply px-3 py-1.5 border border-gray-100/30 dark:border-gray-850/30;
|
|
}
|
|
|
|
.tiptap th {
|
|
@apply cursor-pointer text-start text-xs text-gray-700 dark:text-gray-400 font-normal uppercase bg-gray-50 dark:bg-gray-850;
|
|
}
|
|
|
|
.tiptap td {
|
|
@apply text-gray-900 dark:text-white w-max;
|
|
}
|
|
|
|
.tiptap tr {
|
|
@apply bg-white dark:bg-gray-900 dark:border-gray-850 text-xs;
|
|
}
|
|
|
|
.tippy-box[data-theme~='transparent'] {
|
|
@apply bg-transparent p-0 m-0;
|
|
}
|
|
|
|
/* this is a rough fix for the first cursor position when the first paragraph is empty */
|
|
.ProseMirror > .ProseMirror-yjs-cursor:first-child {
|
|
margin-top: 16px;
|
|
}
|
|
/* This gives the remote user caret. The colors are automatically overwritten*/
|
|
.ProseMirror-yjs-cursor {
|
|
position: relative;
|
|
margin-left: -1px;
|
|
margin-right: -1px;
|
|
border-left: 1px solid black;
|
|
border-right: 1px solid black;
|
|
border-color: orange;
|
|
word-break: normal;
|
|
pointer-events: none;
|
|
}
|
|
/* This renders the username above the caret */
|
|
.ProseMirror-yjs-cursor > div {
|
|
position: absolute;
|
|
top: -1.05em;
|
|
left: -1px;
|
|
font-size: 13px;
|
|
background-color: rgb(250, 129, 0);
|
|
user-select: none;
|
|
color: white;
|
|
padding-left: 2px;
|
|
padding-right: 2px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
body {
|
|
background: #fff;
|
|
color: #000;
|
|
}
|
|
|
|
.dark body {
|
|
background: #171717;
|
|
color: #eee;
|
|
}
|
|
|
|
/* Position the handle relative to each LI */
|
|
.pm-li--with-handle {
|
|
position: relative;
|
|
margin-left: 12px; /* make space for the handle */
|
|
}
|
|
|
|
.tiptap ul[data-type='taskList'] .pm-list-drag-handle {
|
|
margin-left: 0px;
|
|
}
|
|
|
|
/* The drag handle itself */
|
|
.pm-list-drag-handle {
|
|
position: absolute;
|
|
left: -36px; /* pull into the left gutter */
|
|
top: 1px;
|
|
width: 18px;
|
|
height: 18px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 12px;
|
|
line-height: 1;
|
|
border-radius: 4px;
|
|
cursor: grab;
|
|
user-select: none;
|
|
opacity: 0.35;
|
|
transition:
|
|
opacity 120ms ease,
|
|
background 120ms ease;
|
|
}
|
|
|
|
.tiptap ul[data-type='taskList'] .pm-list-drag-handle {
|
|
left: -16px; /* pull into the left gutter more to avoid the checkbox */
|
|
}
|
|
|
|
.pm-list-drag-handle:active {
|
|
cursor: grabbing;
|
|
}
|
|
.pm-li--with-handle:hover > .pm-list-drag-handle {
|
|
opacity: 1;
|
|
}
|
|
.pm-list-drag-handle:hover {
|
|
background: rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
:root {
|
|
--pm-accent: color-mix(in oklab, Highlight 70%, transparent);
|
|
--pm-fill-target: color-mix(in oklab, Highlight 26%, transparent);
|
|
--pm-fill-ancestor: color-mix(in oklab, Highlight 16%, transparent);
|
|
}
|
|
|
|
.pm-li-drop-before,
|
|
.pm-li-drop-after,
|
|
.pm-li-drop-into,
|
|
.pm-li-drop-outdent {
|
|
position: relative;
|
|
}
|
|
|
|
/* BEFORE/AFTER lines */
|
|
.pm-li-drop-before::before,
|
|
.pm-li-drop-after::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
height: 3px;
|
|
background: var(--pm-accent);
|
|
pointer-events: none;
|
|
}
|
|
.pm-li-drop-before::before {
|
|
top: -2px;
|
|
}
|
|
.pm-li-drop-after::after {
|
|
bottom: -2px;
|
|
}
|
|
|
|
.pm-li-drop-before,
|
|
.pm-li-drop-after,
|
|
.pm-li-drop-into,
|
|
.pm-li-drop-outdent {
|
|
background: var(--pm-fill-target);
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.pm-li-drop-outdent::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset-block: 0;
|
|
inset-inline-start: 0;
|
|
width: 3px;
|
|
background: color-mix(in oklab, Highlight 35%, transparent);
|
|
}
|
|
|
|
.pm-li--with-handle:has(.pm-li-drop-before),
|
|
.pm-li--with-handle:has(.pm-li-drop-after),
|
|
.pm-li--with-handle:has(.pm-li-drop-into),
|
|
.pm-li--with-handle:has(.pm-li-drop-outdent) {
|
|
background: var(--pm-fill-ancestor);
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.pm-li-drop-before,
|
|
.pm-li-drop-after,
|
|
.pm-li-drop-into,
|
|
.pm-li-drop-outdent {
|
|
position: relative;
|
|
z-index: 0;
|
|
}
|
|
|
|
#note-content-container .ProseMirror {
|
|
padding-bottom: 2rem; /* space for the bottom toolbar */
|
|
}
|
|
|
|
/* High Contrast Mode: placeholders bottom out at 1.58:1 (WCAG 1.4.3 wants 4.5:1). */
|
|
@layer utilities {
|
|
html.high-contrast:not(.dark) :is(input, textarea)::placeholder {
|
|
color: var(--color-gray-600);
|
|
}
|
|
|
|
html.high-contrast.dark :is(input, textarea)::placeholder {
|
|
color: var(--color-gray-500);
|
|
}
|
|
}
|
|
|
|
/* High Contrast Mode: muted text fails WCAG 1.4.3 (2.07:1 light, 3.12:1 dark).
|
|
:where() keeps these at low specificity so hover variants still win. */
|
|
@layer utilities {
|
|
html:where(.high-contrast):not(:where(.dark)) .text-gray-400 {
|
|
color: var(--color-gray-600);
|
|
}
|
|
|
|
html:where(.high-contrast).dark .dark\:text-gray-600 {
|
|
color: var(--color-gray-400);
|
|
}
|
|
|
|
/* Elements that hover to a lighter grey than the new resting colour. */
|
|
html:where(.high-contrast):not(:where(.dark)) .hover\:text-gray-500:hover {
|
|
color: var(--color-gray-800);
|
|
}
|
|
}
|
|
|
|
/* High Contrast Mode: gray-500 muted text is 2.77:1 in light (WCAG 1.4.3 wants 4.5:1).
|
|
The utility stays in the layer so hover variants still outrank it; the classes below
|
|
are unlayered, so their override has to be too. */
|
|
@layer utilities {
|
|
html:where(.high-contrast):not(:where(.dark)) .text-gray-500 {
|
|
color: var(--color-gray-600);
|
|
}
|
|
}
|
|
|
|
html.high-contrast:not(.dark) :is(.app-muted, .app-icon-muted, .tiptap table) {
|
|
color: var(--color-gray-600);
|
|
}
|