/* ============================================
   Design tokens
   ============================================
   This stylesheet is the one every page loads, so it is where the shared
   tokens live: the colours, and the one layout value that is themeable.

   One vocabulary, in every theme (discussion #1460). A role has one name,
   --pz-something, and a theme only changes its value: the light value sits
   on :root, the dark one in html[data-theme='dark'], and a named theme
   overrides whichever it needs. The stylesheets read --pz-* and nothing
   else (tools/css-check.php holds that line), so a rule can be written once
   for every theme, and a custom stylesheet has a single list to fill in:

       --pz-color-*   the fifteen colours users pick from, and their -soft wash
       --pz-*         every structural and semantic role

   A custom stylesheet overrides only the values it wants to differ, on :root
   for a light theme and in html[data-theme='dark'] for a dark one. Whatever
   it leaves out keeps the value declared here.

   The --dm-* names further down are the older vocabulary of the dark layer.
   They are still where the dark VALUES are stored, which is what keeps the
   stylesheets already in the wild working: one that sets --dm-text still
   moves --pz-text, one that reads var(--dm-text) still gets a colour. Nothing
   in the app reads them any more, and a new theme does not need them.

   It used to be css/dark-mode/variables.css, which was wrong twice over: it
   sat inside the dark layer while holding the LIGHT palette on :root, and a
   second file was also called variables.css. Anyone going looking for the
   palette did not find it. A custom stylesheet (Settings > Custom CSS) can
   re-theme the app by overriding these on :root / html[data-theme='dark'].
   Keep the names stable: they are part of the custom-CSS contract. */

:root {
    /* Corner radius. Twenty-seven different values were in use, fourteen of them
       on buttons alone, so the same kind of control was rounded differently from
       one page to the next. Six steps, and every value snapped to its nearest
       one; nothing moved by more than 2px. */
    --pz-radius-sm: 4px;      /* inputs, small controls, buttons */
    --pz-radius: 6px;         /* default */
    --pz-radius-lg: 8px;      /* cards, panels */
    --pz-radius-xl: 12px;     /* dialogs */
    --pz-radius-2xl: 16px;    /* the largest surfaces */
    --pz-radius-pill: 999px;  /* chips and pills */
    --pz-radius-circle: 50%;

    /* Type weight. The stylesheets used eight spellings, 300 / 400 / 500 / 600 /
       700 / normal / bold / inherit, for what the shipped font renders as two:
       fonts.css declares Inter at 400 and 600 only, so 300 and 500 come out as
       Regular and 700 as SemiBold. Naming the four steps keeps every rendering
       exactly as it is while making the scale visible, and gives the day a
       Medium and a Bold face ship somewhere to change.

       Light is the exception: fonts.css now also declares Inter at 300, so this
       step really does render lighter, but only on pages that link fonts.css
       (the page stylesheets carrying their own @font-face copies still stop at
       Regular and SemiBold, where 300 falls back to Regular). */
    --pz-weight-light: 300;
    --pz-weight-normal: 400;
    --pz-weight-medium: 500;
    --pz-weight-semibold: 600;
    --pz-weight-bold: 700;

    /* Layout. The resizable sidebar: js/resize-column.js overwrites this on
       :root at runtime, this is the default it starts from. */
    --left-col-width: 370px;

    /* Brand blue: links, active states, primary buttons, focus rings. */
    --pz-accent: #007db8;
    --pz-accent-hover: #005a8a;
    /* Same colour as RGB channels, for tints: rgba(var(--pz-accent-rgb), 0.1) */
    --pz-accent-rgb: 0, 125, 184;
    /* Selected text, everywhere: the global ::selection rule
       (components/selection.css) and the rect the markdown editor draws for
       itself (markdown.css) both read this one value, so a selection looks the
       same in read and in edit mode. Translucent on purpose: it composites over
       whatever is underneath, so nothing it covers loses its contrast. */
    --pz-selection: rgba(var(--pz-accent-rgb), 0.22);
    /* Hyperlinks. Kept as its own name because it shipped: a custom stylesheet
       out there may already set --pz-link, and dropping the name would make
       that override silently do nothing. It defaults to the accent now; the
       value it used to carry, #2e8cfa, had contrast 3.36 on white and failed
       WCAG AA for body text. Override it to colour links alone, or --pz-accent
       to move both. It follows --pz-accent-text, the accent as text, so a link
       is the accent in a light theme and its readable version on a dark one. */
    --pz-link: var(--pz-accent-text);
    /* The two ends of the greyscale, used with an alpha to darken or lighten
       whatever is under them: shadows, scrims and pressed states take the
       shadow channel, raised surfaces and hairlines on a dark ground take the
       highlight channel. They are channels, not colours, so they compose:
       rgba(var(--pz-shadow-rgb), 0.15). A theme that is not built on pure
       black and white re-points these two and every elevation follows. */
    --pz-shadow-rgb: 0, 0, 0;
    --pz-highlight-rgb: 255, 255, 255;
    /* Neutral palette. These are the light values; the dark block gives the
       same names their dark ones. */
    /* Text scale, four steps. Contrast on white is 12.6 / 7.6 / 4.8 / 2.5, and
       the app used 62 different greys to express them. Pick by role, not by
       taste, so a theme only has to redefine four values. */
    --pz-text: #333333;            /* body text, headings */
    --pz-text-secondary: #4b5563;  /* supporting text that still reads as content */
    --pz-text-muted: #6b7280;      /* secondary text, icons */
    --pz-text-subtle: #9ca3af;     /* placeholders, hints */
    /* Border scale, three steps by lightness. 43 grey values were in use for
       these three jobs. Anything darker, or tinted, is a border matching a
       filled control and is not part of this scale. */
    --pz-border-light: #eeeeee;    /* separators inside a surface */
    --pz-border: #e0e0e0;          /* default borders */
    --pz-border-strong: #d1d5db;   /* inputs, menus, cards */
    /* Surface scale, four steps by lightness, from the page down to a well.
       A pale TINT is a status or decorative fill and is deliberately not part of
       this scale, so overriding these four repaints the chrome and leaves the
       success greens and alert pinks alone. */
    --pz-surface: #f8f9fa;         /* panels, cards, code backgrounds */
    --pz-surface-hover: #f3f4f6;   /* hover rows and items */
    --pz-surface-sunken: #e9ecef;  /* wells, inset areas, table headers */
    --pz-danger: #dc3545;          /* destructive actions, errors */
    --pz-accent-strong: #0b4da6;   /* selected note/folder title in the sidebar */
    --pz-accent-soft: #e3f2fd;     /* active item background */
    --pz-success: #28a745;         /* success alerts, enabled states */
    --pz-warning: #ffc107;         /* warning alerts, badges */
    /* The pale wash behind a status: an alert body, a badge, a flagged row.
       Each family mixed a Bootstrap-era pastel with a Tailwind-era one, in
       components that never appear side by side, so they are one intention. */
    /* Every semantic colour has the same three steps, so a palette only has to
       answer four questions per family: the fill, its hover, its pale wash, and
       the deep shade used for text on that wash. */
    --pz-danger-hover: #c82333;
    --pz-danger-strong: #721c24;
    --pz-danger-soft: #f8d7da;
    --pz-success-hover: #218838;
    --pz-success-strong: #155724;
    --pz-success-soft: #d4edda;
    --pz-warning-hover: #e0a800;
    --pz-warning-strong: #856404;
    --pz-warning-soft: #fff3cd;
    /* Lucide icons are CSS masks painted with currentColor, so an icon's colour
       is just `color`. This is the grey the old filter chain produced. */
    --pz-icon: #808080;
    /* Neutral controls. The secondary button's grey was written literally, even
       inside components/buttons.css, so a palette could not reach it. */
    --pz-neutral: #6c757d;         /* secondary button, neutral chip */
    --pz-neutral-hover: #5a6268;
    --pz-disabled: #cccccc;        /* the fill of a control that cannot be used */
    --pz-scrollbar: #c1c1c1;
    --pz-scrollbar-hover: #a8a8a8;
    /* White was written as #fff in 268 places, for two opposite jobs: the sheet
       a page is drawn on, and the label sitting on top of a filled control.
       They need separate names, because a theme that darkens the first must not
       darken the second. Both stay white here, so nothing changes until a custom
       stylesheet overrides them. */
    --pz-bg: #ffffff;              /* page, card, menu and modal background */
    --pz-text-inverse: #ffffff;    /* label on an accent, dark or coloured ground */
    /* Search matches: the highlighter yellow, and the orange of the current one.
       Their own names, because the warning family is a text colour in several
       themes and unreadable as a fill behind black text. */
    --pz-mark: #ffff00;
    --pz-mark-active: #ff9d00;
    --pz-mark-active-border: #d35400;

    /* The colour palette users pick from (issue #1408): text colour, highlight,
       slash menu, and the icons of folders, notes, the icon rail and the
       toolbar. Notes store var(--pz-color-red, #dc2626), so redefining one of
       these fifteen on :root (or in a dark block) recolours every note and icon
       painted with it. lib/color-palette.php and js/color-palette.js hold the
       same values as the fallbacks written into content; change all three.

       The -soft variants are highlights. They are derived, not listed: the
       colour mixed into the page background, so they stay pale on a light
       theme and dark on a dark one, and follow a theme that only sets the base
       colour. Tune the strength with --pz-color-soft-mix. Override these on
       :root, where the mix is computed, not on a descendant.

       Yellow has a mix of its own, --pz-color-yellow-soft-mix. It is the
       highlighter (== in markdown, /highlight, <mark>), and the lightest colour
       of the palette: at the strength of the others it is a cream that a white
       page swallows (discussion #1451). 65% is the old #ffe066 marker again,
       with the note text still at 8:1 on it. */
    --pz-color-red: #dc2626;
    --pz-color-orange: #ea580c;
    --pz-color-amber: #d97706;
    --pz-color-yellow: #eab308;
    --pz-color-lime: #84cc16;
    --pz-color-green: #16a34a;
    --pz-color-teal: #0d9488;
    --pz-color-cyan: #0891b2;
    --pz-color-blue: #2563eb;
    --pz-color-indigo: #4f46e5;
    --pz-color-purple: #9333ea;
    --pz-color-magenta: #c026d3;
    --pz-color-pink: #db2777;
    --pz-color-brown: #92400e;
    --pz-color-gray: #6b7280;
    --pz-color-soft-mix: 50%;
    --pz-color-yellow-soft-mix: 65%;
    --pz-color-red-soft: color-mix(in srgb, var(--pz-color-red) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-orange-soft: color-mix(in srgb, var(--pz-color-orange) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-amber-soft: color-mix(in srgb, var(--pz-color-amber) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-yellow-soft: color-mix(in srgb, var(--pz-color-yellow) var(--pz-color-yellow-soft-mix), var(--pz-bg));
    --pz-color-lime-soft: color-mix(in srgb, var(--pz-color-lime) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-green-soft: color-mix(in srgb, var(--pz-color-green) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-teal-soft: color-mix(in srgb, var(--pz-color-teal) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-cyan-soft: color-mix(in srgb, var(--pz-color-cyan) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-blue-soft: color-mix(in srgb, var(--pz-color-blue) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-indigo-soft: color-mix(in srgb, var(--pz-color-indigo) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-purple-soft: color-mix(in srgb, var(--pz-color-purple) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-magenta-soft: color-mix(in srgb, var(--pz-color-magenta) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-pink-soft: color-mix(in srgb, var(--pz-color-pink) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-brown-soft: color-mix(in srgb, var(--pz-color-brown) var(--pz-color-soft-mix), var(--pz-bg));
    --pz-color-gray-soft: color-mix(in srgb, var(--pz-color-gray) var(--pz-color-soft-mix), var(--pz-bg));

    /* The roles that only the dark layer used to name. The dark theme paints
       these with values of its own; the light theme never needed a separate
       one, so each points at the light token that already does the job, and
       follows it when a theme changes that one. A theme that wants them to
       differ sets them like any other token. */
    /* Text that has to stand out from the body copy: a heading, the label of a
       selected row, a value next to its muted caption. Light has no step
       darker than --pz-text; a dark theme brightens it. */
    --pz-text-strong: var(--pz-text);
    /* One step past the surface scale: the ground of a quiet control that
       carries ordinary text, a Cancel button, a scrollbar thumb, a media
       player. Not --pz-neutral, which is a fill under an INVERSE label: a
       theme whose inverse label is dark makes that one light. */
    --pz-surface-strong: var(--pz-surface-sunken);
    --pz-surface-strong-hover: var(--pz-border-strong);
    /* The ground of the application chrome, as opposed to --pz-bg, the sheet
       the content is written on: the side columns, the panels docked to the
       note, the pages that have no note. */
    --pz-chrome-bg: var(--pz-surface);
    --pz-sidebar-bg: var(--pz-surface);       /* the band holding the search bar */
    --pz-sidebar-surface: var(--pz-bg);       /* a field or a hovered row inside it */
    --pz-code-bg: var(--pz-surface);          /* code blocks in a note */
    --pz-active-bg: var(--pz-accent-soft);    /* the row or option that is current */
    --pz-tabbar-bg: var(--pz-bg);
    --pz-tab-bg: var(--pz-surface-hover);
    --pz-tab-hover-bg: var(--pz-surface-sunken);
    --pz-tab-active-bg: var(--pz-bg);
    --pz-icon-hover: var(--pz-accent);
    /* Each semantic colour again, for where it stands on the page by itself:
       a link, an icon, an outline, a dot. --pz-accent is a FILL, the ground of
       a button that carries a --pz-text-inverse label, and a fill that holds a
       white label is too dark to read as a line on a dark ground. So a colour
       has two names, and a dark theme gives the second one a brighter value.
       In a light theme both jobs take the same colour, hence the aliases.
       -text-hover is its hovered state. The wash that goes behind it is -soft,
       and -strong is the shade for text ON that wash; those two switch with
       the theme like the neutrals do. */
    --pz-accent-text: var(--pz-accent);
    --pz-accent-text-hover: var(--pz-accent-hover);
    --pz-accent-text-rgb: var(--pz-accent-rgb);
    --pz-danger-text: var(--pz-danger);
    --pz-danger-text-hover: var(--pz-danger-hover);
    --pz-success-text: var(--pz-success);
    --pz-success-text-hover: var(--pz-success-hover);
    --pz-warning-text: var(--pz-warning);
    --pz-warning-text-hover: var(--pz-warning-hover);

    /* Excalidraw previews. A diagram is stored with no ground of its own and
       with the colours Excalidraw authors in light mode, so the note shows
       through behind it. A dark mode inverts it, which is how a black stroke
       becomes a light one: the same filter Excalidraw puts on its own canvas.
       Setting it here is what makes a theme change reach the diagram with no
       re-save (issue #1445). */
    --pz-excalidraw-filter: none;
}

/* ============================================
   Dark Mode - CSS Custom Properties & Base
   ============================================
   Two halves. The --dm-* declarations hold the dark values (see the header
   for why they keep that name). The --pz-* declarations after them give each
   one its universal name, which is the only name the stylesheets read. A
   dark variant such as theme-black changes the --dm-* values and every
   --pz-* follows; a custom stylesheet can set either, and --pz-* wins. */

html[data-theme='dark'] {
    /* See --pz-excalidraw-filter on :root above. */
    --pz-excalidraw-filter: invert(93%) hue-rotate(180deg);

    /* Text scale. Contrast on --dm-content-bg is 11.6 / 8.2 / 5.9 / 4.3, the same
       shape the black theme below already had. --dm-text-muted used to be
       #c5c5c5, which is BRIGHTER than --dm-text: the muted level was louder than
       the main one, so the hierarchy read backwards wherever both were used. */
    --dm-text-bright: #e0e0e0;
    --dm-text: #bebebe;
    --dm-text-muted: #a0a0a0;
    --dm-text-subtle: #888888;
    --dm-bg: #252526;
    --dm-content-bg: #252526;
    --dm-sidebar-bg: #252526;
    --dm-sidebar-surface: #333333;
    --dm-surface: #333333;
    --dm-surface-hover: #3a3a3a;
    /* A fill that has to sit above a hovered one: a chip, a raised control,
       a nested panel. 15 rules were painting it by hand. */
    --dm-surface-raised: #4a4a4a;
    /* Lucide icons are CSS masks painted with currentColor, so their colour is
       just `color`. These two are the greys the old `filter: invert(80%)` /
       `invert(90%)` produced, kept exactly so nothing moves. */
    --dm-neutral: #5f6368;
    --dm-neutral-hover: #6f757a;
    --dm-disabled: #4a4a4a;
    --dm-scrollbar: #4a4a4a;
    --dm-scrollbar-hover: #5f6368;
    --dm-icon: #cccccc;
    --dm-icon-hover: #e6e6e6;
    /* The semantic families again, in the values a dark ground needs: a fill
       bright enough to read, and a wash dark enough to sit on the page. The
       black theme inherits these unless it overrides them. */
    --dm-accent-hover: #6ab3ff;
    --dm-accent-soft: #334155;
    --dm-danger: #ff6b6b;
    --dm-danger-hover: #ef4444;
    --dm-danger-soft: #3d1f1f;
    --dm-success: #4ade80;
    --dm-success-hover: #22c55e;
    --dm-success-soft: #1a4d2e;
    --dm-warning: #ffc107;
    --dm-warning-hover: #e0a800;
    --dm-warning-soft: #665500;
    --pz-mark: var(--dm-warning);
    --pz-mark-active: var(--dm-warning-hover);
    --pz-mark-active-border: var(--dm-warning-hover);

    /* The user palette, lighter so it reads as text and icons on a dark
       ground (contrast 5.1 to 10.2 on #252526). Highlights are mixed with
       less colour, so light text keeps a contrast of 4.4 or more on them. */
    --pz-color-red: #f87171;
    --pz-color-orange: #fb923c;
    --pz-color-amber: #fbbf24;
    --pz-color-yellow: #facc15;
    --pz-color-lime: #a3e635;
    --pz-color-green: #4ade80;
    --pz-color-teal: #2dd4bf;
    --pz-color-cyan: #22d3ee;
    --pz-color-blue: #60a5fa;
    --pz-color-indigo: #818cf8;
    --pz-color-purple: #c084fc;
    --pz-color-magenta: #e879f9;
    --pz-color-pink: #f472b6;
    --pz-color-brown: #c8a27a;
    --pz-color-gray: #9ca3af;
    --pz-color-soft-mix: 25%;
    --pz-color-yellow-soft-mix: var(--pz-color-soft-mix);

    /* The light tokens, switched for this theme.

       Until now a light rule that said color: var(--pz-text) rendered #333333 in
       dark mode too, and the only thing saving it was a rule in dark-mode/ saying
       the same thing again with --dm-text. That is why the dark layer holds 1,593
       rules, 1,149 of which do nothing but restate a light rule in other colours.

       With the token itself switching, a rule written once is correct in both
       themes, and a component whose dark override was simply forgotten stops
       rendering dark text on a dark ground.

       The neutrals switch, and so does everything that stands on the ground by
       itself. The accent and the status FILLS deliberately do not: the dark
       accent is bright because it has to read as text on a dark ground, and
       using it as a fill would put white on #4a9eff at a contrast of 2.2. A
       fill and a label cannot be the same token, which is why each family also
       has a -text name further down. */
    --pz-bg: var(--dm-content-bg);
    --pz-surface: var(--dm-surface);
    --pz-surface-hover: var(--dm-surface-hover);
    --pz-surface-sunken: var(--dm-surface-raised);
    --pz-text: var(--dm-text);
    --pz-text-secondary: var(--dm-text-muted);
    --pz-text-muted: var(--dm-text-muted);
    --pz-text-subtle: var(--dm-text-subtle);
    --pz-border: var(--dm-border);
    --pz-border-light: var(--dm-border);
    --pz-border-strong: var(--dm-border-light);
    --pz-icon: var(--dm-icon);
    /* Neutral controls follow too. Their dark values existed but nothing
       pointed at them, so a scrollbar or a disabled fill written once with
       var(--pz-scrollbar) kept rendering the light grey in dark mode. */
    --pz-disabled: var(--dm-disabled);
    --pz-scrollbar: var(--dm-scrollbar);
    --pz-scrollbar-hover: var(--dm-scrollbar-hover);
    /* The roles the dark layer named on its own, under their universal names
       (their light values are on :root). These are what dark rules read. */
    --pz-text-strong: var(--dm-text-bright);
    --pz-surface-strong: var(--dm-neutral);
    --pz-surface-strong-hover: var(--dm-neutral-hover);
    --pz-chrome-bg: var(--dm-bg);
    --pz-sidebar-bg: var(--dm-sidebar-bg);
    --pz-sidebar-surface: var(--dm-sidebar-surface);
    --pz-code-bg: var(--dm-code-bg);
    --pz-active-bg: var(--dm-active);
    --pz-tabbar-bg: var(--dm-tabbar-bg);
    --pz-tab-bg: var(--dm-tab-bg);
    --pz-tab-hover-bg: var(--dm-tab-hover-bg);
    --pz-tab-active-bg: var(--dm-tab-active-bg);
    --pz-icon-hover: var(--dm-icon-hover);
    --pz-accent-text: var(--dm-accent);
    --pz-accent-text-hover: var(--dm-accent-hover);
    --pz-accent-text-rgb: var(--dm-accent-rgb);
    --pz-danger-text: var(--dm-danger);
    --pz-danger-text-hover: var(--dm-danger-hover);
    --pz-success-text: var(--dm-success);
    --pz-success-text-hover: var(--dm-success-hover);
    --pz-warning-text: var(--dm-warning);
    --pz-warning-text-hover: var(--dm-warning-hover);
    /* The wash and the text that goes on it. They used to keep their light
       values here, so an alert no dark rule had reached stayed a pale box with
       dark text in the middle of a dark page. A wash has to switch together
       with its text, or one of the two becomes unreadable: a dark wash under
       the deep light shade, or a bright label on a pale box. */
    --pz-accent-soft: var(--dm-accent-soft);
    --pz-accent-strong: var(--dm-accent);
    --pz-danger-soft: var(--dm-danger-soft);
    --pz-danger-strong: var(--dm-danger);
    --pz-success-soft: var(--dm-success-soft);
    --pz-success-strong: var(--dm-success);
    --pz-warning-soft: var(--dm-warning-soft);
    --pz-warning-strong: var(--dm-warning);
    /* A tint of the dark accent, a little stronger than the light one because
       it has less ground to stand out from. */
    --pz-selection: rgba(var(--dm-accent-rgb), 0.28);
    --dm-border: #404040;
    --dm-border-light: #555555;
    --dm-accent: #4a9eff;
    --dm-accent-rgb: 74, 158, 255;   /* tints of the dark accent */
    --dm-active: #1e3a5f;
    --dm-code-bg: #262424;
    --dm-tabbar-bg: #1e1e1e;
    --dm-tab-bg: #252525;
    --dm-tab-hover-bg: #2e2e2e;
    --dm-tab-active-bg: #383838;
}

/* ============================================
   Named themes
   ============================================
   Each one is a variant of a mode, exactly like theme-black above: the mode
   stays in data-theme so every rule in the app keeps working unchanged, and
   the class carries the palette. A light variant overrides the --pz-* scales,
   a dark one the --dm-*. js/theme-manager.js and js/theme-init.js hold the
   same list; adding a theme means adding it in all three. */

/* --- Lavender: a light theme with a neon streak -------------------------- */
html.theme-lavender {
    --pz-bg: #f3e3ff;
    --pz-surface: #e7cdfb;
    --pz-surface-hover: #d9b3f5;
    --pz-surface-sunken: #d9b3f5;

    --pz-text: #1a0033;
    --pz-text-secondary: #43206b;
    --pz-text-muted: #5c3a85;
    --pz-text-subtle: #6b4d90;
    --pz-text-inverse: #ffffff;

    --pz-border-light: #d9b3f5;
    --pz-border: #c98ae8;
    --pz-border-strong: #b026ff;

    --pz-accent: #7a00d4;
    --pz-accent-hover: #c2007a;
    --pz-accent-strong: #4a0080;
    --pz-accent-soft: #f3d9ff;
    --pz-accent-rgb: 122, 0, 212;
    --pz-link: #7a00d4;

    --pz-danger: #c4002a;
    --pz-danger-hover: #8f001e;
    --pz-danger-strong: #6b0016;
    --pz-danger-soft: #ffd9e2;
    --pz-success: #1d9e00;
    --pz-success-hover: #157400;
    --pz-success-strong: #0d4a00;
    --pz-success-soft: #d8ffd0;
    --pz-warning: #a38f00;
    --pz-warning-hover: #7d6d00;
    --pz-warning-strong: #544a00;
    --pz-warning-soft: #fff8cc;

    --pz-icon: #c2007a;
    --pz-neutral: #6b3fa0;
    --pz-neutral-hover: #52307a;
    --pz-disabled: #d9b3f5;
    --pz-scrollbar: #c98ae8;
    --pz-scrollbar-hover: #b026ff;
    --pz-shadow-rgb: 122, 0, 212;
}

/* --- Sepia: warm paper, for reading -------------------------------------- */
html.theme-sepia {
    --pz-bg: #f6ecd8;
    --pz-surface: #efe0c4;
    --pz-surface-hover: #e6d2ad;
    --pz-surface-sunken: #e6d2ad;

    --pz-text: #3b2c1a;
    --pz-text-secondary: #56412a;
    --pz-text-muted: #6d573c;
    --pz-text-subtle: #7a6449;
    --pz-text-inverse: #f6ecd8;

    --pz-border-light: #e6d2ad;
    --pz-border: #d4bd94;
    --pz-border-strong: #b99e72;

    --pz-accent: #8a4b12;
    --pz-accent-hover: #6d3a0c;
    --pz-accent-strong: #4d2807;
    --pz-accent-soft: #f2dcc0;
    --pz-accent-rgb: 138, 75, 18;
    --pz-link: #8a4b12;

    --pz-danger: #96271b;
    --pz-danger-hover: #741c12;
    --pz-danger-strong: #52130c;
    --pz-danger-soft: #f6d9d2;
    --pz-success: #4a6a1f;
    --pz-success-hover: #384f17;
    --pz-success-strong: #26350f;
    --pz-success-soft: #e3edcd;
    --pz-warning: #8a6a12;
    --pz-warning-hover: #6d540c;
    --pz-warning-strong: #4d3a07;
    --pz-warning-soft: #f6e8c2;

    --pz-icon: #7a6449;
    --pz-neutral: #6d573c;
    --pz-neutral-hover: #56412a;
    --pz-disabled: #e6d2ad;
    --pz-scrollbar: #d4bd94;
    --pz-scrollbar-hover: #b99e72;
    --pz-shadow-rgb: 59, 44, 26;
}

/* --- Terminal: green phosphor on a dark tube ----------------------------- */
html.theme-terminal[data-theme='dark'] {
    --dm-bg: #000000;
    --dm-content-bg: #041008;
    --dm-sidebar-bg: #000000;
    --dm-sidebar-surface: #0a1f10;
    --dm-surface: #0a1f10;
    --dm-surface-hover: #10301a;
    --dm-surface-raised: #164226;
    --dm-code-bg: #000000;
    --dm-active: #10301a;

    --dm-text-bright: #b6ffc8;
    --dm-text: #4ee87a;
    --dm-text-muted: #37c561;
    --dm-text-subtle: #279449;

    --dm-border: #16512a;
    --dm-border-light: #1f7a3a;

    --dm-accent: #4ee87a;
    --dm-accent-rgb: 78, 232, 122;
    --dm-accent-hover: #b6ffc8;
    --dm-accent-soft: #0a2a14;

    --dm-danger: #ff5f56;
    --dm-danger-hover: #ff8a84;
    --dm-danger-soft: #2e0a08;
    --dm-success: #4ee87a;
    --dm-success-hover: #b6ffc8;
    --dm-success-soft: #0a2a14;
    --dm-warning: #ffbd2e;
    --dm-warning-hover: #ffd473;
    --dm-warning-soft: #2e2205;

    --dm-icon: #2fae54;
    --dm-icon-hover: #4ee87a;
    --dm-neutral: #16512a;
    --dm-neutral-hover: #1f7a3a;
    --dm-disabled: #10301a;
    --dm-scrollbar: #16512a;
    --dm-scrollbar-hover: #1f7a3a;

    --dm-tabbar-bg: #000000;
    --dm-tab-bg: #041008;
    --dm-tab-hover-bg: #0a1f10;
    --dm-tab-active-bg: #10301a;

    /* Fills keep their own label colour: the phosphor green is a text colour,
       so anything filled with it takes the tube's black back. The washes are
       left to the bridge (they are this theme's --dm-*-soft); -strong is
       stated because this theme wants the brightest green on a wash. */
    --pz-accent: #2fae54;
    --pz-accent-hover: #4ee87a;
    --pz-accent-strong: #b6ffc8;
    --pz-accent-rgb: 47, 174, 84;
    --pz-text-inverse: #041008;
    --pz-danger: #e04c3f;
    --pz-danger-hover: #ff5f56;
    --pz-danger-strong: #ff8a84;
    --pz-success: #2fae54;
    --pz-success-hover: #4ee87a;
    --pz-success-strong: #b6ffc8;
    --pz-warning: #a37516;
    --pz-warning-hover: #ffbd2e;
    --pz-warning-strong: #ffd473;
    --pz-neutral: #16512a;
    --pz-neutral-hover: #1f7a3a;
    --pz-shadow-rgb: 0, 0, 0;
    --pz-highlight-rgb: 78, 232, 122;
}

html.theme-black[data-theme='dark'] {
    /* Same four steps, in the blue-grey the black theme uses. These two values
       were already in the right order; bright and subtle extend them.
       --dm-text was #c0c8d4, 10.5:1 on the note ground where the dark theme
       reads at 8.2:1; once the tree stopped being dimmed below it (#1457) the
       whole theme read too bright. #aab3c0 is 8.4:1, the dark theme's level. */
    --dm-text-bright: #e9ecf0;
    --dm-text: #aab3c0;
    --dm-text-muted: #9ba6b5;
    --dm-text-subtle: #818a96;
    /* The neutral controls in this theme's own blue-grey. They were inherited
       from the dark theme, whose greys are neutral, so a secondary button or a
       scrollbar sat as a flat grey inside a blue-grey interface. Same lightness,
       so nothing about the contrast changes. The status colours are NOT
       overridden: a red is a red in both dark themes. */
    --dm-neutral: #5f636a;
    --dm-neutral-hover: #71747b;
    --dm-disabled: #474a52;
    --dm-scrollbar: #474a52;
    --dm-scrollbar-hover: #5f636a;
    --dm-bg: #0f1117;
    --dm-content-bg: #141821;
    --dm-sidebar-bg: #0b0d12;
    --dm-sidebar-surface: #12151c;
    --dm-surface: #171a21;
    --dm-surface-hover: #202532;
    --dm-surface-raised: #2d303d;
    --dm-icon: #b9c2cf;
    --dm-icon-hover: #dde3ec;
    --dm-border: #252b35;
    --dm-border-light: #394150;
    --dm-accent: #5f94f7;
    --dm-active: #15243a;
    --dm-code-bg: #090b10;
    --dm-tabbar-bg: var(--dm-sidebar-bg);
    --dm-tab-bg: var(--dm-sidebar-surface);
    --dm-tab-hover-bg: var(--dm-surface);
    --dm-tab-active-bg: var(--dm-content-bg);
}

/* The page canvas. The dark rule below existed on its own for a long time,
   which left the light theme's outermost ground on the browser's default
   white: no token reached it, so a custom stylesheet could repaint every
   panel and still show white behind them. --pz-bg is #ffffff by default, so
   this renders exactly as the UA default did and only adds the hook. */
html {
    background-color: var(--pz-bg);
}

/* Apply dark background as early as possible */
html[data-theme='dark'] {
    background-color: var(--dm-content-bg);
    color: var(--dm-text);
}

/* Prevent transition flash on initial load */
html[data-theme='dark'] * {
    transition: background-color 0.0s, color 0.0s, border-color 0.0s !important;
}

/* The one rule that consumes --pz-excalidraw-filter, and it lives here
   because this is the only stylesheet every page that can render a note body
   loads: the note editor, the journal, a share page, the notes manager. A
   diagram whose preview carries no theme would otherwise be drawn in dark
   strokes on a dark ground on whichever of them lacked the rule. */
.excalidraw-image-neutral {
    filter: var(--pz-excalidraw-filter, none);
}
