    /* PDF.js text layer: invisible selectable text over the canvas */
    .pdf-page { position: relative; margin: 0 auto 16px; box-shadow: 0 1px 4px var(--mr-shadow-c1); }
    .pdf-textLayer {
      position: absolute; inset: 0; overflow: hidden; line-height: 1;
      opacity: 1; mix-blend-mode: multiply;
    }
    .pdf-textLayer span {
      position: absolute; white-space: pre; cursor: text;
      color: transparent; transform-origin: 0 0;
    }
    .pdf-textLayer ::selection { background: rgba(var(--mr-hl-yellow-rgb), .5); }
    .pdf-hl-layer { position: absolute; inset: 0; pointer-events: none; }
    .pdf-hl { position: absolute; border-radius: 2px; pointer-events: auto; cursor: pointer; }
    /* Free-text annotation label (see renderTextAnnotation in viewer-render.js) — a placed
       point, not a rect region, so it's sized to its own text instead of a fixed box. */
    .pdf-text-annot {
      position: absolute; pointer-events: auto; cursor: pointer; font-weight: 600;
      white-space: pre-wrap; max-width: 60%; padding: 1px 3px; border-radius: 3px;
    }
    .pdf-text-annot:hover { outline: 1px dashed currentColor; outline-offset: 2px; }
    #viewer-content-area.freehand-mode .pdf-text-annot { pointer-events: none; }
    #viewer-content-area.erasing .pdf-text-annot:hover { outline: 2px solid var(--mr-danger); outline-offset: 1px; }
    /* HTML-document highlights (background set inline per color) */
    .hl-mark { border-radius: 2px; cursor: pointer; }
    /* Note ("blocnote") editor body — a contenteditable div fed straight from/to
       server-sanitized HTML (see sanitize_note_html in ingest.py), so these rules
       only need to cover the small tag set the toolbar in viewer-render.js's
       renderNote() can actually produce. */
    .note-editor-body { min-height: 50vh; }
    .note-editor-body:focus { outline: none; }
    .note-editor-body img { max-width: 100%; height: auto; border-radius: 6px; margin: 8px 0; }
    .note-editor-body ul { list-style: disc; padding-left: 1.5em; margin: 8px 0; }
    .note-editor-body ol { list-style: decimal; padding-left: 1.5em; margin: 8px 0; }
    .note-editor-body h1 { font-size: 1.5em; font-weight: 700; margin: 16px 0 8px; }
    .note-editor-body h2 { font-size: 1.25em; font-weight: 700; margin: 14px 0 8px; }
    .note-editor-body h3 { font-size: 1.1em; font-weight: 600; margin: 12px 0 6px; }
    .note-editor-body blockquote { border-left: 3px solid var(--mr-paper-line); padding-left: 12px; color: var(--mr-paper-ink-2); margin: 8px 0; }
    .note-editor-body p { margin: 0 0 8px; }
    .note-editor-body a { color: var(--mr-paper-link); text-decoration: underline; }
    /* Let the browser handle one/two-finger scroll natively, but not pinch-to-zoom — that's
       intercepted in JS (onViewerTouchMove) and mapped onto the document's own zoom instead
       of the browser's page/viewport zoom. Omitting "pinch-zoom" from the allowed list is what
       disables the native gesture; pan-x/pan-y keep normal scrolling working. */
    #viewer-content-area { touch-action: pan-x pan-y; }
    /* Eraser mode */
    #viewer-content-area.erasing .pdf-textLayer { cursor: crosshair; }
    #viewer-content-area.erasing .pdf-hl:hover,
    #viewer-content-area.erasing .hl-mark:hover { outline: 2px solid var(--mr-danger); outline-offset: 1px; }
    /* Freehand mode: drag to draw a hand-drawn highlight/line over any part of the page/image
       (like iPad Markup) */
    #viewer-content-area.freehand-mode .pdf-textLayer { pointer-events: none; user-select: none; }
    #viewer-content-area.freehand-mode .pdf-hl { pointer-events: none; }
    #viewer-content-area.freehand-mode .pdf-page { cursor: crosshair; }
    /* Text tool: click anywhere on a page to place a free-text annotation there — disable the
       underlying text layer's native selection so clicking never leaves a stray highlighted
       selection behind, only the placed annotation. */
    #viewer-content-area.text-mode .pdf-page { cursor: text; }
    #viewer-content-area.text-mode .pdf-textLayer { pointer-events: none; user-select: none; }
    #viewer-content-area.text-mode .pdf-hl { pointer-events: none; }
    /* While freehand mode is active on a touchscreen, a single-finger drag draws a stroke
       (handled entirely in JS below) rather than scrolling the page — `pan-x pan-y` from the
       base rule above would otherwise let the browser claim that drag for native scrolling
       before our touchmove handler ever sees it. */
    #viewer-content-area.freehand-mode { touch-action: none; }
    .freehand-draft { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 5; }
    /* Viewer header auto-hide: collapse height/padding/opacity rather than translate, so the
       flex-col layout reflows and #viewer-content-area smoothly grows to fill the freed space
       (no gap left behind, unlike a transform-only hide). */
    /* Draws the eye to the account-settings Country dropdown when the phone-field flag button
       (a shortcut, not a separate picker) is clicked — see focusSettingsCountry(). */
    @keyframes settingsCountryPulse { 0%, 100% { box-shadow: 0 0 0 3px var(--wc-moss-wash); } 50% { box-shadow: 0 0 0 3px var(--wc-moss); } }
    .settings-country-highlight { animation: settingsCountryPulse .4s ease-in-out 3; }
    #viewer-header { max-height: 200px; overflow: hidden;
      transition: max-height .25s ease, padding-top .25s ease, padding-bottom .25s ease, opacity .2s ease, border-color .25s ease; }
    #viewer-header.viewer-header-hidden { max-height: 0; padding-top: 0; padding-bottom: 0;
      opacity: 0; border-bottom-color: transparent; pointer-events: none; }
    /* Loading-state skeletons — replaces plain "Loading…" text in the handful of
       full-panel async loads (dashboard, planner, admin console, quiz review, viewer).
       .wc-skel is for light canvas/card surfaces (uses the theme's hairline token);
       .wc-skel-inv is for the always-dark viewer/toolbar bar (--wc-bar), which stays
       dark in both light and dark mode, so it needs a fixed light-on-dark fill instead. */
    @keyframes wcSkelShine { to { transform: translateX(100%); } }
    .wc-skel, .wc-skel-inv { position: relative; overflow: hidden; border-radius: 8px; }
    .wc-skel { background: var(--wc-hair); }
    .wc-skel-inv { background: rgba(255,255,255,.08); }
    .wc-skel::after, .wc-skel-inv::after {
      content: ''; position: absolute; inset: 0; transform: translateX(-100%);
      animation: wcSkelShine 1.6s ease-in-out infinite;
    }
    .wc-skel::after { background: linear-gradient(90deg, transparent, rgba(255,255,255,.5), transparent); }
    html.dark .wc-skel::after { background: linear-gradient(90deg, transparent, rgba(255,255,255,.1), transparent); }
    .wc-skel-inv::after { background: linear-gradient(90deg, transparent, rgba(255,255,255,.16), transparent); }
    @media (prefers-reduced-motion: reduce) {
      .wc-skel::after, .wc-skel-inv::after { animation: none; }
    }

    /* Every dialog uses the .mr-modal shell from components.css (scrim, surface, open
       motion); see index.html. */

    /* BRIDGE — the legacy --wc-* names used across app.css and inline styles now point at
       the shared design tokens (static/css/tokens.css), so every screen wears the new
       system even before its own markup is migrated. Removed in the final cleanup. */
    :root {
      --wc-canvas: var(--mr-bg); --wc-canvas-2: var(--mr-bg-2); --wc-card: var(--mr-surface); --wc-hair: var(--mr-line-2);
      --wc-track: var(--mr-bg-2); --wc-ink: var(--mr-bone); --wc-ink-2: var(--mr-bone-2); --wc-ink-3: var(--mr-bone-3);
      --wc-moss: var(--mr-moss); --wc-moss-2: var(--mr-moss-2); --wc-moss-text: var(--mr-moss-lit); --wc-moss-wash: var(--mr-moss-wash);
      --wc-ochre: var(--mr-warn); --wc-ochre-text: var(--mr-warn); --wc-ochre-wash: var(--mr-warn-wash);
      --wc-bar: var(--mr-bar); --wc-shadow: var(--mr-shadow-c1); --wc-shadow-2: var(--mr-shadow-c2);
    }
    svg[width="1em"] { display: inline-block; vertical-align: -0.125em; flex-shrink: 0; }
    body { font-family: var(--mr-sans); background: var(--mr-bg) !important; color: var(--mr-bone); }
    /* index.html's <body> is `h-screen` (100vh) so the header stays put and #main-content's
       own overflow-y-auto does the scrolling. On mobile browsers 100vh is the viewport with
       the address bar hidden — while it's shown, 100vh is taller than what's actually
       visible, so the bottom slice of the page (and of any anchored popup, e.g. #more-menu)
       renders below the visible fold with no way to reach it: body itself doesn't scroll
       (overflow-hidden), so it isn't a scroll-position problem, it's a page-taller-than-
       viewport problem. dvh tracks the *actual* visible viewport and updates live as the
       address bar shows/hides, so override with it where supported (everything but very old
       Safari/Chrome) instead of dropping h-screen outright and losing the older fallback. */
    @supports (height: 100dvh) {
      body.h-screen { height: 100dvh; }
    }
    /* Editorial serif for display headings & big numbers */
    h1, h2, .text-3xl, .text-4xl, .text-2xl.font-bold { font-family: var(--mr-serif); font-weight: var(--mr-heading-weight) !important; letter-spacing: -.012em; }

    /* surfaces */
    .bg-white       { background:var(--wc-card) !important; }
    .bg-slate-50    { background:var(--wc-canvas) !important; }
    .bg-slate-100, .bg-slate-200 { background:var(--wc-track) !important; }
    .bg-slate-800, .bg-slate-900, .bg-slate-700 { background:var(--wc-bar) !important; }  /* viewer/toolbar */
    /* text */
    .text-slate-900,.text-slate-800 { color:var(--wc-ink) !important; }
    .text-slate-700,.text-slate-600 { color:var(--wc-ink-2) !important; }
    .text-slate-500,.text-slate-400,.text-slate-300,.text-slate-200 { color:var(--wc-ink-3) !important; }
    .text-slate-200, .bg-slate-800 .text-slate-200 { color:var(--mr-on-bar) !important; }
    /* borders / dividers */
    .border-slate-100,.border-slate-200,.border-slate-300,.border-slate-700,.border-slate-600 { border-color:var(--wc-hair) !important; }
    .divide-slate-50 > * + *, .divide-slate-100 > * + * { border-color:var(--wc-hair) !important; }
    /* primary accent: blue → moss */
    .bg-blue-600,.bg-blue-500 { background:var(--wc-moss) !important; }
    .bg-blue-700,.hover\:bg-blue-700:hover,.hover\:bg-blue-600:hover { background:var(--wc-moss-2) !important; }
    .text-blue-700,.text-blue-600,.text-blue-500 { color:var(--wc-moss-text) !important; }
    .bg-blue-50,.bg-blue-100 { background:var(--wc-moss-wash) !important; }
    .border-blue-600,.border-blue-500,.border-blue-400,.border-blue-300,.border-blue-200 { border-color:var(--wc-moss) !important; }
    .hover\:border-blue-300:hover { border-color:var(--wc-moss) !important; }
    .hover\:text-blue-600:hover { color:var(--wc-moss-text) !important; }
    .focus\:border-blue-500:focus { border-color:var(--wc-moss) !important; }
    /* success / completed: green → moss */
    .bg-green-600 { background:var(--wc-moss) !important; }
    .hover\:bg-green-700:hover { background:var(--wc-moss-2) !important; }
    .text-green-700,.text-green-600 { color:var(--wc-moss-text) !important; }
    .bg-green-50,.bg-green-100 { background:var(--wc-moss-wash) !important; }
    .border-green-300,.border-green-200 { border-color:var(--wc-moss) !important; }
    .hover\:border-green-300:hover { border-color:var(--wc-moss) !important; }
    .hover\:text-green-600:hover { color:var(--wc-moss-text) !important; }
    /* review / attention: orange & amber → ochre */
    .text-orange-500,.text-orange-600,.text-amber-600,.text-amber-700,.text-amber-800 { color:var(--wc-ochre-text) !important; }
    .bg-orange-50,.bg-amber-50,.bg-amber-100 { background:var(--wc-ochre-wash) !important; }
    .border-orange-300,.border-amber-300,.border-amber-200 { border-color:var(--wc-ochre) !important; }
    .hover\:border-orange-300:hover { border-color:var(--wc-ochre) !important; }
    .hover\:text-orange-600:hover { color:var(--wc-ochre-text) !important; }
    /* violet (spaced-review accents) → ochre-ish for warmth */
    .text-violet-700,.text-violet-800 { color:var(--wc-ochre-text) !important; }
    .bg-violet-50 { background:var(--wc-ochre-wash) !important; }
    /* hovers / tracks */
    .hover\:bg-slate-50:hover { background:var(--wc-canvas-2) !important; }
    /* form controls */
    input,textarea,select { background:var(--wc-card) !important; color:var(--wc-ink) !important; border-color:var(--wc-hair) !important; }
    input::placeholder,textarea::placeholder { color:var(--wc-ink-3) !important; }
    input:focus,textarea:focus,select:focus { outline:none; border-color:var(--wc-moss) !important; box-shadow:0 0 0 3px var(--wc-moss-wash); }

    /* motion & polish */
    button,a,[onclick],.cursor-pointer,.rounded-lg,.rounded-xl,.rounded-2xl {
      transition: background-color .16s ease, border-color .16s ease, color .16s ease, box-shadow .2s ease, transform .12s ease;
    }
    .rounded-xl.border.cursor-pointer:hover, .hover\:shadow-md:hover { box-shadow:0 6px 20px var(--wc-shadow) !important; }
    button:not(:disabled):active { transform:translateY(1px); }
    * { scrollbar-width:thin; scrollbar-color:var(--wc-hair) transparent; }
    *::-webkit-scrollbar { width:10px; height:10px; }
    *::-webkit-scrollbar-thumb { background:var(--wc-hair); border-radius:8px; border:2px solid transparent; background-clip:padding-box; }
    *::-webkit-scrollbar-thumb:hover { background:var(--wc-ink-3); background-clip:padding-box; }
    /* Touch/coarse-pointer devices have no hover state, so any element gated behind
       opacity-0 + group-hover:opacity-100 (bulk-select checkboxes, document card action
       buttons, folder-tree rename/delete, highlight-delete ×, friend Remove) is permanently
       invisible and untappable there. Force it visible whenever the primary input has no
       hover capability. Scoped to elements carrying BOTH classes together — the only
       combination this codebase uses them in, confirmed by grep — so this can't affect
       anything else. */
    @media (hover: none), (any-pointer: coarse) {
      .opacity-0.group-hover\:opacity-100 { opacity: 1 !important; }
    }

    /* header icon buttons */
    .mr-hbtn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; width: 40px; height: 40px; border-radius: var(--mr-r-md); color: var(--mr-bone-2); background: transparent; border: 1px solid transparent; font-size: 17px; cursor: pointer; transition: color var(--mr-dur-micro) var(--mr-ease), background-color var(--mr-dur-micro) var(--mr-ease), border-color var(--mr-dur-micro) var(--mr-ease); }
    .mr-hbtn:hover { color: var(--mr-bone); background: var(--mr-glow-soft); }
    .mr-hbtn[aria-expanded="true"] { color: var(--mr-glow); border-color: rgba(var(--mr-glow-rgb), .4); }
    /* popovers anchored to the header (positionPanel()) */
    #more-menu.flex { display: flex; }
    .mr-menu .mr-select--sm { min-height: 36px; font-size: var(--mr-fs-3); margin-bottom: 4px; }
    .mr-menu__item svg { font-size: 16px; flex: none; }
    .mr-panel { background: var(--mr-surface-2); border: 1px solid var(--mr-line); border-radius: var(--mr-r-lg); box-shadow: var(--mr-shadow-2); }
    .mr-panel.hidden { display: none; }
    .mr-panel__head { padding: 12px 16px; border-bottom: 1px solid var(--mr-line); }
    .mr-panel__title { font: var(--mr-heading-weight) var(--mr-fs-6)/1.2 var(--mr-serif); color: var(--mr-bone); }
    .mr-tree-empty { padding: 24px 12px; text-align: center; font-size: var(--mr-fs-2); color: var(--mr-bone-3); }
    .mr-main { background: var(--mr-bg); }

    @media (max-width: 1279px) {
      /* Chat list column: give the active thread a usable minimum width on phones. */
      #chat-list-col { width: 40vw !important; min-width: 0; }
    }
    /* Popups positioned near a click point could otherwise sit past the right/bottom edge
       of a narrow viewport — clamp so they always stay fully on-screen. */
    #highlight-popup, #hl-comment-box { max-width: calc(100vw - 16px); }
    /* Admin console hides all library/social chrome */
    body.admin-mode .user-only { display: none !important; }
    body:not(.admin-mode) .admin-only { display: none !important; }
    /* Presence dots */
    .presence-dot { width: 9px; height: 9px; border-radius: 9999px; display: inline-block; flex-shrink: 0; }
    .presence-online  { background: var(--mr-online); }
    .presence-absent  { background: var(--mr-absent); }
    .presence-busy    { background: var(--mr-busy); }
    .presence-offline { background: var(--mr-offline); }

    /* Chat — theme-aware (the /50 opacity utilities aren't remapped by the theme) */
    #chat-messages { background: var(--wc-canvas); }
    #chat-list-col, #chat-thread-header, #chat-composer { background: var(--wc-card); }
    .chat-bubble-mine { background: var(--mr-moss); color: var(--mr-on-moss); }
    .chat-bubble-mine .chat-time { color: var(--mr-on-moss); opacity: .75; }
    .chat-bubble-them { background: var(--wc-card); color: var(--wc-ink-2); border: 1px solid var(--wc-hair); }
    .chat-bubble-them .chat-time { color: var(--wc-ink-3); }
    /* In dark mode the moss is light, so flip the sent-bubble text to dark for contrast */
    /* Optimistic send: dim until the server confirms, red outline + retry hint on failure. */
    .chat-bubble-pending { opacity: .55; }
    .chat-bubble-failed  { outline: 1.5px solid var(--mr-danger); cursor: pointer; }
    /* The group's pinned/announcement message — a subtle sticky-note highlight
       so it stands out while scrolling, without competing with .chat-bubble-failed. */
    .chat-bubble-pinned  { outline: 1.5px solid var(--wc-ochre); outline-offset: 1px; }
    /* A message's dropped-in file — an inline preview for an image, a named chip
       (with a download affordance) for anything else. */
    .chat-attachment-image { display: block; }
    .chat-attachment-file {
      border-radius: 10px; padding: 6px 8px; min-width: 160px; max-width: 220px;
      text-decoration: none;
    }
    .chat-bubble-mine .chat-attachment-file { background: rgba(var(--mr-bg-rgb), .16); color: inherit; }
    .chat-bubble-them .chat-attachment-file { background: var(--wc-canvas); color: inherit; }
    /* The whole #chat-messages pane highlights while a file is dragged over it,
       same affordance as the document-upload dropzone elsewhere in the app. */
    #chat-messages.chat-drop-active { outline: 2px dashed var(--wc-moss); outline-offset: -2px; }
    /* Small round initials badge used in the conversation list and thread header. */
    .chat-avatar {
      border-radius: 9999px; color: #FFFFFF; display: flex; align-items: center;
      justify-content: center; font-size: 12px; font-weight: 600; flex-shrink: 0;
      text-transform: uppercase;
    }
    /* "Today" / "Yesterday" / date pill separating message groups by calendar day. */
    .chat-date-divider { text-align: center; margin: 10px 0; }
    .chat-date-divider span {
      display: inline-block; padding: 2px 10px; border-radius: 9999px; font-size: 10px;
      background: var(--wc-card); color: var(--wc-ink-3); border: 1px solid var(--wc-hair);
    }
    .chat-seen { text-align: right; font-size: 10px; color: var(--wc-ink-3); margin-top: 2px; }
    /* Presence dot pinned to the bottom-right corner of an avatar (parent needs position:relative). */
    .chat-presence-badge {
      position: absolute; bottom: -1px; right: -1px; border: 2px solid var(--wc-card);
    }

    /* Dashboard Library Map (library-map.js): radial mycelium on a canvas + side panel. */
    .lm { display: grid; gap: 12px; }
    .lm-list summary { list-style: none; }
    .lm-list summary::-webkit-details-marker { display: none; }
    .lm-list summary > span:first-child::before { content: ""; display: inline-block; width: 6px; height: 6px; margin: 0 10px 2px 2px; border-right: 1.5px solid var(--mr-bone-3); border-bottom: 1.5px solid var(--mr-bone-3); transform: rotate(-45deg); transition: transform var(--mr-dur-micro) var(--mr-ease); }
    .lm-list details[open] > summary > span:first-child::before { transform: rotate(45deg); }
    .lm-body { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 320px; min-height: 560px; border: 1px solid var(--mr-line); border-radius: var(--mr-r-lg); background: var(--mr-surface); overflow: hidden; }
    .lm-stage { position: relative; min-height: 560px; height: min(68vh, 680px); background: var(--mr-bg); outline: none; touch-action: none; }
    .lm-stage:focus-visible { box-shadow: inset 0 0 0 2px rgba(var(--mr-glow-rgb), .8); }
    .lm-stage[hidden], .lm-list[hidden] { display: none; }
    .lm-stage canvas { position: absolute; inset: 0; display: block; }
    .lm-tip { position: absolute; left: 0; top: 0; z-index: 2; max-width: 280px; padding: 6px 10px; border-radius: var(--mr-r-md); background: var(--mr-surface-2); color: var(--mr-bone); border: 1px solid var(--mr-line-2); box-shadow: var(--mr-shadow-2); font-size: var(--mr-fs-2); pointer-events: none; }
    .lm-tip[hidden] { display: none; }
    .lm-count { position: absolute; left: 14px; bottom: 12px; margin: 0; font-size: var(--mr-fs-2); color: var(--mr-bone-3); pointer-events: none; }
    .lm-hint { position: absolute; left: 50%; top: 12px; transform: translateX(-50%); margin: 0; padding: 6px 12px; border-radius: var(--mr-r-pill); background: var(--mr-surface-2); border: 1px solid var(--mr-line-2); font-size: var(--mr-fs-2); color: var(--mr-bone-2); opacity: 0; transition: opacity var(--mr-dur-1) var(--mr-ease); pointer-events: none; }
    .lm-hint.is-on { opacity: 1; }
    .lm-zoom { position: absolute; right: 12px; bottom: 12px; display: grid; gap: 4px; }
    .lm-list { min-height: 560px; max-height: min(68vh, 680px); overflow: auto; padding: 8px 16px 16px; }
    .lm-list ul { list-style: none; margin: 0; padding: 0; }
    .lm-list summary { display: flex; justify-content: space-between; gap: 12px; padding: 10px 4px; cursor: pointer; border-bottom: 1px solid var(--mr-line); }
    .lm-list summary:hover { color: var(--mr-bone); background: var(--mr-glow-soft); }
    .lm-list__field { font-weight: 600; }
    .lm-list__folders { padding-left: 16px !important; }
    .lm-list .lm-docs { padding-left: 16px; }
    .lm-panel { position: relative; border-left: 1px solid var(--mr-line); background: var(--mr-surface); max-height: min(68vh, 680px); min-height: 560px; overflow: auto; }
    .lm-panel__body { padding: 20px; }
    .lm-grab { display: none; }
    .lm-kicker { margin: 0; font-size: var(--mr-fs-2); font-weight: 600; color: var(--mr-moss-lit); }
    .lm-title { margin: 4px 0 2px; font: var(--mr-heading-weight) 22px/1.2 var(--mr-serif); letter-spacing: var(--mr-heading-tracking); color: var(--mr-bone); overflow-wrap: anywhere; }
    .lm-title--doc { font-size: 19px; }
    .lm-meta { margin: 0; font-size: var(--mr-fs-2); color: var(--mr-bone-3); }
    .lm-help { margin: 12px 0 0; font-size: var(--mr-fs-2); color: var(--mr-bone-2); }
    .lm-path { margin: 10px 0 0; font: 400 12px/1.5 var(--mr-mono); color: var(--mr-bone-2); overflow-wrap: anywhere; }
    .lm-path b { font-weight: 400; color: var(--mr-glow); }
    .lm-h { margin: 18px 0 4px; font-size: var(--mr-fs-1); font-weight: 600; color: var(--mr-bone-3); }
    .lm-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
    .lm-rows, .lm-docs { list-style: none; margin: 0; padding: 0; }
    .lm-row { display: flex; width: 100%; justify-content: space-between; gap: 12px; padding: 9px 6px; border-bottom: 1px solid var(--mr-line); text-align: left; color: var(--mr-bone); font-size: var(--mr-fs-3); border-radius: 0; }
    .lm-row:hover { background: var(--mr-glow-soft); }
    .lm-n { color: var(--mr-bone-3); font-variant-numeric: tabular-nums; }
    .lm-doc { display: grid; gap: 2px; width: 100%; padding: 9px 6px; border-bottom: 1px solid var(--mr-line); text-align: left; }
    .lm-doc:hover { background: var(--mr-glow-soft); }
    .lm-doc__name { font: 400 13px/1.35 var(--mr-mono); color: var(--mr-bone); overflow-wrap: anywhere; }
    .lm-doc__meta { font-size: 12px; color: var(--mr-bone-3); }
    .lm-due { color: var(--mr-warn); font-weight: 600; }
    .lm-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
    .lm-tags .mr-chip[aria-pressed="true"] { border-color: rgba(var(--mr-glow-rgb), .6); background: var(--mr-glow-soft); color: var(--mr-bone); }
    .lm-more, .lm-empty { margin: 10px 0 0; font-size: var(--mr-fs-2); color: var(--mr-bone-3); }
    /* phones and narrow cards: the panel becomes a bottom sheet over the map */
    @media (max-width: 759px) {
            .lm-body { grid-template-columns: minmax(0, 1fr); min-height: 0; }
      .lm-stage { height: 64vh; min-height: 420px; }
      .lm-list { min-height: 0; max-height: none; }
      .lm-panel { position: absolute; left: 0; right: 0; bottom: 0; z-index: 3; min-height: 0; max-height: 70%; border-left: 0; border-top: 1px solid var(--mr-line-2); border-radius: 16px 16px 0 0; box-shadow: var(--mr-shadow-2); transform: translateY(calc(100% - 64px)); transition: transform var(--mr-dur-2) var(--mr-ease); overflow: hidden; }
      .lm.is-sheet-open .lm-panel { transform: none; overflow: auto; }
      .lm.is-list .lm-panel { display: none; }
      .lm-grab { display: flex; justify-content: center; width: 100%; padding: 10px 0 2px; position: sticky; top: 0; background: var(--mr-surface); }
      .lm-grab span { width: 40px; height: 4px; border-radius: 2px; background: var(--mr-line-2); }
      .lm-panel__body { padding: 4px 18px 18px; }
      .lm-count { bottom: 76px; }
      .lm-zoom { bottom: 76px; }
    }

    /* ══ AUTH GATE — the welcome page's world: the same living mycelial network
       (the shared ambient.js canvas, raised under the gate), the same reading-room surface and type, one moss
       primary action. Scoped to .auth-* / #auth-gate. */
    #auth-gate { background: var(--mr-bg); color: var(--mr-bone); }
    .auth-stage { position: relative; min-height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 96px 16px 48px; overflow: hidden; }
    /* with the ambient background on, it sits just under the gate (or the reader) and paints the desk */
    html.ambient-elevated #auth-gate, html.ambient-elevated .rd-viewer, html.ambient-elevated .rd-desk { background: transparent; }
    .auth-shade { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(520px 480px at 50% 48%, var(--mr-bg) 30%, color-mix(in srgb, var(--mr-bg) 55%, transparent) 70%, transparent); }
    .auth-bar { position: fixed; inset: 0 0 auto 0; z-index: 20; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px clamp(16px, 4vw, 40px); background: color-mix(in srgb, var(--mr-bg) 80%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--mr-line); }
    .auth-brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--mr-bone); }
    .auth-brand img { border-radius: 8px; }
    .auth-brand-name { font: var(--mr-heading-weight) 19px/1 var(--mr-serif); letter-spacing: -.01em; white-space: nowrap; }
    .auth-bar-actions { display: flex; align-items: center; gap: 4px; }
    .auth-lang-btn { font: 700 12px/1 var(--mr-sans); }
    .auth-wrap { position: relative; z-index: 2; }
    .auth-card-head { text-align: center; margin-bottom: 20px; }
    .auth-card-head h1 { font: var(--mr-heading-weight) clamp(30px, 4vw, 38px)/1.1 var(--mr-serif) !important; letter-spacing: -.015em; color: var(--mr-bone); margin: 0 0 6px; }
    .auth-card-head p { font-size: var(--mr-fs-4); color: var(--mr-bone-2); margin: 0; }
    .auth-card-panel { background: color-mix(in srgb, var(--mr-surface) 92%, transparent); border: 1px solid var(--mr-line-2); border-radius: var(--mr-r-lg); box-shadow: var(--mr-shadow-2); overflow: hidden; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
    .auth-tabs { padding: 0 12px; }
    .auth-tabs .mr-tab { padding: 14px 10px; font-size: var(--mr-fs-4); }
    .auth-panel { display: grid; gap: 12px; padding: 22px; }
    .auth-panel > .hidden { display: none; }
    .auth-small { font-size: var(--mr-fs-2); }
    .auth-center { text-align: center; color: var(--mr-bone-3); }
    .auth-info { font-size: var(--mr-fs-2); color: var(--mr-moss-lit); }
    .mr-input--pw { padding-right: 40px; }
    .mr-pw-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 32px; height: 32px; display: grid; place-items: center; border-radius: var(--mr-r-sm); color: var(--mr-bone-3); font-size: 16px; }
    .mr-pw-toggle:hover { color: var(--mr-bone); background: var(--mr-glow-soft); }
    .mr-choice--top { align-items: flex-start; line-height: 1.45; }
    .mr-choice--top .mr-check { margin-top: 1px; }
    .mr-checklist { list-style: none; margin: 0; padding: 0 2px; display: grid; gap: 3px; font-size: var(--mr-fs-2); color: var(--mr-bone-3); }
    [data-check].is-ok { color: var(--mr-moss-lit); }
    [data-check] svg { display: inline-block; vertical-align: -2px; margin-right: 2px; }
    .auth-fine { text-align: center; font-size: var(--mr-fs-3); color: var(--mr-bone-2); margin-top: 18px; }
    .auth-fine-cta { color: var(--mr-moss-lit); font-weight: 600; background: none; border: none; padding: 0; font: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
    .auth-fine-cta:hover { color: var(--mr-glow); }
    @media (max-width: 480px) {
      .auth-brand-name { font-size: 16px; }
      .auth-back-text { display: none; }
      .auth-panel { padding: 18px; }
    }

    /* ══ LIBRARY — dense but breathable. Page heads in the serif, filenames in mono,
       classification paths as chips (.mr-path) with a soft scan sweep on hover, folder
       cards carrying their sub-folders as a little network of branches. */
    .lib-icon { display: inline-grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: var(--mr-r-md); background: var(--mr-moss-wash); color: var(--mr-moss-lit); font-size: 19px; }
    .lib-icon--doc { width: 36px; height: 36px; font-size: 17px; background: var(--mr-bg-2); color: var(--mr-bone-2); border: 1px solid var(--mr-line); }
    .lib-icon--lg { width: 52px; height: 52px; font-size: 24px; }
    .lib-chips { display: flex; flex-wrap: wrap; gap: 4px; }
    /* room for the absolutely-positioned "⋯ More" button in the card's corner */
    @media (hover: none) { .lib-open { display: none; } }
    /* folder card */
    /* document card */
    /* document detail + search */
    .lib-detail__title { font: var(--mr-heading-weight) clamp(24px, 2.6vw, 32px)/1.15 var(--mr-serif) !important; letter-spacing: -.012em; color: var(--mr-bone); overflow-wrap: anywhere; margin: 0 0 4px; }
    .mr-mark { background: rgba(var(--mr-glow-rgb), .18); color: var(--mr-bone); border-radius: 3px; padding: 0 2px; box-shadow: inset 0 -1px 0 rgba(var(--mr-glow-rgb), .6); }
    html:not(.dark) .mr-mark { background: rgba(var(--mr-hl-yellow-rgb), .55); box-shadow: none; }
    /* folder pickers (Move / new note / photo upload) */
    .mr-treebox { padding: 6px; border-radius: var(--mr-r-md); border: 1px solid var(--mr-line); background: var(--mr-bg-2); }
    .mr-treenode { display: flex; align-items: center; gap: 7px; min-height: 32px; padding-right: 8px; border-radius: var(--mr-r-sm); font-size: var(--mr-fs-3); color: var(--mr-bone-2); cursor: pointer; transition: background-color var(--mr-dur-micro) var(--mr-ease), color var(--mr-dur-micro) var(--mr-ease); }
    .mr-treenode:hover { background: var(--mr-glow-soft); color: var(--mr-bone); }
    .mr-treenode.is-selected { background: var(--mr-surface-2); color: var(--mr-bone); font-weight: 600; box-shadow: inset 2px 0 0 var(--mr-glow); }
    .mr-treenode.is-current { opacity: .4; cursor: not-allowed; }
    .mr-treenode__icon { display: inline-grid; color: var(--mr-moss-lit); font-size: 14px; }
    .mr-divider-top { border-top: 1px solid var(--mr-line); }
    .mr-input--readonly { background: var(--mr-bg-2); color: var(--mr-bone-3); }
    .mr-modal__close { font-size: 20px; line-height: 1; }
    /* ══ UPLOAD & CLASSIFICATION — the signature moment: the file is "read" by a light
       bar while it uploads, then each result reveals what it is and where it was filed. */
    .up-tabs { padding: 0 12px; }
    .up-urls { min-height: 110px; font-family: var(--mr-mono); font-size: var(--mr-fs-2); line-height: 1.7; resize: none; }
    .up-drop { display: grid; justify-items: center; gap: 4px; padding: 30px 16px; border: 1.5px dashed var(--mr-line-2); border-radius: var(--mr-r-lg); text-align: center; cursor: pointer; transition: border-color var(--mr-dur-micro) var(--mr-ease), background-color var(--mr-dur-micro) var(--mr-ease); }
    .up-drop--sm { padding: 22px 16px; }
    .up-drop:hover, .up-drop:focus-visible, .up-drop.is-dragover { border-color: rgba(var(--mr-glow-rgb), .6); background: var(--mr-glow-soft); }
    .up-drop__icon { font-size: 28px; color: var(--mr-moss-lit); margin-bottom: 4px; }
    .up-drop__title { font-size: var(--mr-fs-4); font-weight: 600; color: var(--mr-bone); }
    .up-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--mr-r-md); background: var(--mr-bg-2); border: 1px solid var(--mr-line); }
    .up-thumb { width: 100%; height: 64px; object-fit: cover; border-radius: var(--mr-r-sm); border: 1px solid var(--mr-line); }
    .up-thumb__x { position: absolute; top: -6px; right: -6px; width: 22px; height: 22px; display: grid; place-items: center; border-radius: 50%; background: var(--mr-surface-2); border: 1px solid var(--mr-line-2); color: var(--mr-bone-2); font-size: 13px; line-height: 1; }
    .up-thumb__x:hover { color: var(--mr-danger); }
    /* loading: a file card crossed by the scanning light */
    .up-loading { display: grid; justify-items: center; text-align: center; padding-top: 34px; padding-bottom: 34px; }
    .up-scan { position: relative; width: 210px; margin-bottom: 22px; }
    .up-file { position: relative; display: grid; gap: 10px; padding: 18px 16px 16px; border-radius: var(--mr-r-md); background: var(--mr-bg-2); border: 1px solid var(--mr-line-2); overflow: hidden; text-align: left; }
    .up-file__glyph { width: 22px; height: 28px; border-radius: 2px 7px 2px 2px; border: 1.5px solid var(--mr-line-2); }
    .up-file__name { min-height: 1.3em; font: 400 var(--mr-fs-2)/1.3 var(--mr-mono); color: var(--mr-bone); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .up-file__lines { display: grid; gap: 6px; }
    .up-file__lines i { height: 5px; border-radius: 3px; background: var(--mr-line-2); }
    .up-file__lines i:nth-child(2) { width: 80%; } .up-file__lines i:nth-child(3) { width: 90%; } .up-file__lines i:nth-child(4) { width: 55%; }
    .up-bar { position: absolute; top: -8px; bottom: -8px; left: 0; width: 2px; background: var(--mr-glow); box-shadow: 0 0 16px 3px rgba(var(--mr-glow-rgb), .45), -28px 0 40px -8px rgba(var(--mr-glow-rgb), .2); animation: upScan 1.8s cubic-bezier(.45, 0, .55, 1) infinite alternate; }
    @keyframes upScan { from { left: 0; } to { left: calc(100% - 2px); } }
    .up-progress { font-size: var(--mr-fs-4); font-weight: 600; color: var(--mr-bone); max-width: 36ch; overflow-wrap: anywhere; }
    /* summary */
    .up-summary-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
    .up-summary-head__icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: var(--mr-moss-wash); color: var(--mr-moss-lit); font-size: 18px; }
    .up-summary-head__icon.is-warn { background: var(--mr-warn-wash); color: var(--mr-warn); }
    .up-list { list-style: none; margin: 0; padding: 0; max-height: 18rem; overflow-y: auto; border: 1px solid var(--mr-line); border-radius: var(--mr-r-md); }
    .up-row { display: flex; align-items: flex-start; gap: 10px; padding: 12px; border-bottom: 1px solid var(--mr-line); animation: mrRise var(--mr-dur-1) var(--mr-ease) both; animation-delay: calc(var(--i) * 90ms); }
    .up-row:last-child { border-bottom: 0; }
    .up-row__icon { flex: none; margin-top: 1px; color: var(--mr-bone-3); }
    .up-row--done .up-row__icon { color: var(--mr-moss-lit); }
    .up-row--failed .up-row__icon, .up-row--failed .up-row__sub { color: var(--mr-danger); }
    .up-row--queued .up-row__icon { color: var(--mr-glow); }
    .up-row__sub { margin-top: 3px; font-size: var(--mr-fs-2); color: var(--mr-bone-3); }
    /* the classification path is revealed left-to-right behind a light bar */
    .up-reveal { position: relative; margin-top: 4px; clip-path: inset(0 100% 0 0); animation: upReveal var(--mr-dur-3) var(--mr-ease) forwards; animation-delay: calc(var(--i) * 90ms + 250ms); }
    @keyframes upReveal { to { clip-path: inset(0 0 0 0); } }
    @media (prefers-reduced-motion: reduce) { .up-reveal { clip-path: none; } .up-bar { left: 50%; } }

    /* ══ READER — the content is the hero: documents sit as light paper sheets on the
       dark reading desk (so highlight colours and colours saved inside notes stay legible
       in both themes), excellent reading type, minimal chrome, near-invisible motion. */
    .rd-viewer { background: var(--mr-bg); color: var(--mr-bone); }
    .rd-bar { background: color-mix(in srgb, var(--mr-bg) 90%, transparent); border-bottom: 1px solid var(--mr-line); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
    .rd-title { font: var(--mr-heading-weight) var(--mr-fs-6)/1.25 var(--mr-serif); letter-spacing: -.005em; color: var(--mr-bone); }
    .rd-meta { font: 400 var(--mr-fs-2)/1 var(--mr-mono); color: var(--mr-bone-3); }
    .rd-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 34px; padding: 0 10px; border-radius: var(--mr-r-sm); border: 1px solid transparent; background: transparent; color: var(--mr-bone-2); font: 500 var(--mr-fs-2)/1 var(--mr-sans); white-space: nowrap; cursor: pointer; transition: color var(--mr-dur-micro) var(--mr-ease), background-color var(--mr-dur-micro) var(--mr-ease), border-color var(--mr-dur-micro) var(--mr-ease); }
    .rd-btn:hover { color: var(--mr-bone); background: var(--mr-glow-soft); }
    .rd-btn--icon { width: 34px; padding: 0; font-size: 16px; }
    .rd-btn.is-active, .rd-btn[aria-pressed="true"] { color: var(--mr-glow); border-color: rgba(var(--mr-glow-rgb), .5); background: var(--mr-glow-soft); }
    .rd-btn.is-danger { color: var(--mr-danger); border-color: color-mix(in srgb, var(--mr-danger) 50%, transparent); background: var(--mr-danger-wash); }
    .rd-btn--close { color: var(--mr-bone); font-size: var(--mr-fs-3); }
    #viewer-page-nav:not(.hidden) { display: flex; }
    .rd-group { display: flex; align-items: center; gap: 8px; padding: 4px 6px; border-radius: var(--mr-r-md); background: var(--mr-surface); border: 1px solid var(--mr-line); }
    .rd-group.hidden { display: none; }
    .rd-seg { display: inline-flex; align-items: center; gap: 4px; padding: 5px 8px; border-radius: var(--mr-r-sm); font: 600 11px/1 var(--mr-sans); color: var(--mr-bone-3); background: none; border: 0; cursor: pointer; }
    .rd-seg:hover { color: var(--mr-bone); }
    .rd-seg.is-active, .rd-seg[aria-pressed="true"] { color: var(--mr-bone); background: var(--mr-bg); box-shadow: inset 0 0 0 1px var(--mr-line-2); }
    .rd-sep { width: 1px; height: 16px; background: var(--mr-line-2); flex: none; }
    .rd-pen { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; color: var(--mr-bone-2); }
    .rd-pen > span { display: block; border-radius: 50%; background: currentColor; }
    .rd-pen:hover { background: var(--mr-glow-soft); }
    .tbcolor, .ttcolor, .cdot { box-shadow: inset 0 0 0 1px rgba(var(--mr-paper-ink-rgb),.18); }
    /* the desk + the page */
    .rd-desk { background: var(--mr-bg); background-image: radial-gradient(1000px 420px at 50% -200px, rgba(var(--mr-moss-rgb), .12), transparent 70%); }
    .rd-page { max-width: 72ch; margin: 28px auto 64px; padding: clamp(28px, 5vw, 64px) clamp(20px, 5vw, 72px); background: var(--mr-paper); color: var(--mr-paper-ink); border-radius: 6px; box-shadow: 0 30px 60px -30px var(--mr-shadow-c2), 0 0 0 1px rgba(var(--mr-paper-ink-rgb),.08); }
    html:not(.dark) .rd-page { box-shadow: 0 20px 50px -28px rgba(var(--mr-paper-ink-rgb),.35), 0 0 0 1px rgba(var(--mr-paper-ink-rgb),.08); }
    .rd-page__title { font: var(--mr-heading-weight) clamp(26px, 3vw, 34px)/1.15 var(--mr-serif); letter-spacing: var(--mr-heading-tracking); color: var(--mr-paper-ink); margin: 0 0 24px; }
    .rd-page__text { font: 400 19px/1.75 var(--mr-serif); color: var(--mr-paper-ink); font-feature-settings: "kern", "liga", "onum"; hyphens: auto; }
    .rd-page__text--mono { font: 400 14px/1.7 var(--mr-mono); }
    .rd-page--note .rd-page__text { font-size: 18px; }
    .rd-page ::selection { background: rgba(var(--mr-hl-yellow-rgb), .55); color: inherit; }
    .pdf-page { box-shadow: 0 30px 60px -30px var(--mr-shadow-c2), 0 0 0 1px rgba(var(--mr-paper-ink-rgb),.08); border-radius: 2px; }
    .rd-status { padding: 80px 16px; text-align: center; font-size: var(--mr-fs-3); color: var(--mr-bone-3); }
    .rd-status--error { color: var(--mr-danger); }
    .rd-link { display: grid; justify-items: center; gap: 12px; max-width: 520px; margin: 0 auto; padding: 80px 24px; text-align: center; }
    .rd-link .mr-fname { overflow-wrap: anywhere; }
    /* note toolbar (on the paper) */
    .rd-notebar { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; margin: -8px 0 20px; padding-bottom: 12px; border-bottom: 1px solid var(--mr-paper-line); font-family: var(--mr-sans); }
    .rd-notebar .rd-sep { background: var(--mr-paper-line); margin: 0 4px; }
    .rd-notebar .mr-hint { color: var(--mr-paper-ink-2); }
    .rd-notebtn { display: inline-grid; place-items: center; min-width: 32px; height: 32px; padding: 0 8px; border-radius: var(--mr-r-sm); font-size: 14px; color: var(--mr-paper-ink-2); }
    .rd-notebtn:hover { background: rgba(var(--mr-paper-ink-rgb),.07); color: var(--mr-paper-ink); }
    .rd-swatch { width: 18px; height: 18px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(var(--mr-paper-ink-rgb),.18); }
    .rd-swatch--clear { display: inline-grid; place-items: center; background: var(--mr-paper); color: var(--mr-paper-danger); font-size: 10px; line-height: 1; }
    /* annotation popups */
    .rd-pop { background: var(--mr-surface-2); color: var(--mr-bone); border: 1px solid var(--mr-line-2); border-radius: var(--mr-r-lg); box-shadow: var(--mr-shadow-2); }
    .rd-pop__author { font-size: 11px; font-weight: 600; color: var(--mr-bone-3); margin-bottom: 6px; }
    .rd-pop__author.hidden { display: none; }
    .rd-pop__input { min-height: 72px; font-size: var(--mr-fs-2); resize: none; }
    .rd-quick { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: var(--mr-r-pill); background: var(--mr-surface-2); color: var(--mr-bone); border: 1px solid rgba(var(--mr-glow-rgb), .45); box-shadow: var(--mr-shadow-2); font: 600 var(--mr-fs-2)/1 var(--mr-sans); }
    .rd-quick.hidden { display: none; }
    .rd-quick:hover { border-color: rgba(var(--mr-glow-rgb), .8); }
    .rd-tip { max-width: 260px; padding: 7px 10px; border-radius: var(--mr-r-md); background: var(--mr-surface-2); color: var(--mr-bone); border: 1px solid var(--mr-line-2); box-shadow: var(--mr-shadow-2); font-size: var(--mr-fs-2); line-height: 1.5; }
    /* reading mode */
    .rd-exit { display: none; }
    #viewer-modal.is-reading #viewer-header { display: none; }
    #viewer-modal.is-reading .rd-exit { display: inline-flex; position: fixed; top: 14px; right: 16px; z-index: 5; align-items: center; height: 32px; padding: 0 12px; border-radius: var(--mr-r-pill); background: color-mix(in srgb, var(--mr-surface-2) 85%, transparent); border: 1px solid var(--mr-line-2); color: var(--mr-bone-2); font: 600 var(--mr-fs-2)/1 var(--mr-sans); opacity: .55; transition: opacity var(--mr-dur-1) var(--mr-ease); backdrop-filter: blur(8px); }
    #viewer-modal.is-reading .rd-exit:hover, #viewer-modal.is-reading .rd-exit:focus-visible { opacity: 1; }
    @media (max-width: 640px) { .rd-page { margin: 12px 8px 40px; } .rd-page__text { font-size: 17px; } }


    /* bulk selection bar */

    /* Group/member list rows — same lift idea as .lib-card above, scaled down since
       these sit inside a dense modal rather than a full page. */
    .group-row, .group-member-row { transition: transform 150ms ease, box-shadow 150ms ease; }
    .group-row:hover { transform: translateY(-1px); box-shadow: 0 4px 12px var(--wc-shadow); }
    /* Inline edit box for a sent group-channel message, sized to sit inside the bubble. */

    /* ══ APP ATMOSPHERE — the reading room: one soft moss light falling from the top of
       the workspace onto a near-black blue-green desk. Deliberately quiet (no grain, no
       watermark) so documents and cards are the brightest things on screen. */
    #main-content {
      background-color: var(--mr-bg);
      background-image: radial-gradient(1200px 520px at 30% -260px, rgba(var(--mr-moss-rgb), .16), transparent 70%);
      background-repeat: no-repeat;
    }
    /* with the ambient background on, the desk colour comes from the page itself */
    html.ambient-on #main-content { background-color: transparent; }
    html:not(.dark) #main-content { background-image: radial-gradient(1200px 520px at 30% -260px, rgba(var(--mr-moss-rgb), .1), transparent 70%); }

    /* ══ PLANNER CALENDAR CELLS — dedicated classes instead of Tailwind's opacity-
       suffixed utilities (e.g. bg-slate-50/60). Those generate their own literal-rgb
       class (background-color: rgb(248 250 252 / .6)) that the theme remap above has
       no hook into, since it only targets the plain .bg-slate-50 class — that mismatch
       is why past/out-of-month cells used to stay flat light-gray even in dark mode.
       See viewPlanner() in planner.js. */
    .planner-cell { background: var(--wc-card); transition: background .12s ease; }
    .planner-cell:hover { background: var(--wc-moss-wash); }
    .planner-cell-past { background: var(--wc-canvas-2); }
    .planner-cell-past:hover { background: var(--wc-track); }
    .planner-cell-out { background: var(--wc-canvas); }

    /* ══ FIRST-LOGIN TOUR — see #tour-overlay in index.html and tour.js. #tour-spotlight
       is positioned/sized in JS (fixed top/left/width/height, computed from the current
       step's target getBoundingClientRect()) — its own huge box-shadow spread is both the
       dimmed backdrop AND the cutout around the target, so there's nothing else to dim.
       transition here is what makes the spotlight glide from one nav button to the next
       instead of jump-cutting; #tour-card gets the same treatment so the two move as one. */
    #tour-spotlight {
      position: fixed; top: 0; left: 0; width: 0; height: 0;
      border-radius: 12px;
      /* Flat black, not the theme's --wc-shadow-2 (too faint in light mode to read as a
         dimmed backdrop) — same fixed bg-black/40-ish strength every other modal's
         backdrop uses, just a bit darker since it also has to read as a "hole" cutout. */
      box-shadow: 0 0 0 9999px var(--mr-scrim);
      transition: top .3s cubic-bezier(.22,1,.36,1), left .3s cubic-bezier(.22,1,.36,1),
                  width .3s cubic-bezier(.22,1,.36,1), height .3s cubic-bezier(.22,1,.36,1);
      pointer-events: none;
    }
    #tour-card {
      transition: top .3s cubic-bezier(.22,1,.36,1), left .3s cubic-bezier(.22,1,.36,1);
    }
