/* Per-page layout CSS that used to live in each template's own inline
   <style> block. Kept in one shared file instead of one per page — very
   few selectors actually collide between pages, since most rules only
   ever match markup that one specific page renders. The few that do
   collide (header, main, the editor's CodeMirror height) are scoped with
   a class on <body>/<html> instead of being split into more files.
   Every authenticated page's HTML response is marked Cache-Control:
   no-store (see main.go) and so is refetched on every navigation; this
   file is served from web/ instead, so the browser fetches it once and
   reuses it across every page view. */

/* ---- Shell chrome shared by layout.html ("app"), landing.html, and
   public_note.html ---- */
header { background: var(--header-bg); color: var(--header-fg); padding: 0.5em 1em; display: flex; gap: 1em; align-items: center; flex-wrap: wrap; }
header a { color: var(--header-fg); }
/* Lucide icons (see the "icon" template in layout.html) sized to sit inline
   with the text next to them. text-decoration: none stops header/footer's
   underline from painting through the icon glyph itself. */
.icon { width: 1em; height: 1em; display: inline-block; vertical-align: -0.15em; margin-right: 0.3em; flex-shrink: 0; text-decoration: none; }
.icon-filled { fill: currentColor; }

/* The 8 theme-aware note/folder icon color slots — each theme's own
   web/css/*.css defines what --icon-1..8 actually are (see light.css's
   comment); this just wires the class names used on a badge/swatch to
   those variables. */
.icon-1 { color: var(--icon-1); }
.icon-2 { color: var(--icon-2); }
.icon-3 { color: var(--icon-3); }
.icon-4 { color: var(--icon-4); }
.icon-5 { color: var(--icon-5); }
.icon-6 { color: var(--icon-6); }
.icon-7 { color: var(--icon-7); }
.icon-8 { color: var(--icon-8); }

/* Note/folder custom icon + color picker (see the "iconBadge" template) —
   a <details>/<summary> disclosure, same zero-JS technique list.html's
   folder tree uses. */
.icon-picker { position: relative; display: inline-block; }
/* .icon-badge alone is also used as a plain, non-interactive read-only
   badge (a collaborator viewing someone else's note, or a row in
   list.html's tree) — cursor/hover/marker-hiding only apply when it's
   actually the <summary> of a picker. */
.icon-badge { display: inline-flex; padding: 0.2em; border-radius: 4px; }
.icon-badge .icon { width: 1.3em; height: 1.3em; margin-right: 0; }
.icon-picker .icon-badge { cursor: pointer; list-style: none; }
.icon-picker .icon-badge::-webkit-details-marker { display: none; }
.icon-picker .icon-badge:hover { background: var(--bg-secondary); }
.icon-picker-panel { position: absolute; top: 100%; left: 0; z-index: 60; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 0.6em; margin-top: 0.3em; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); width: 18em; }
.icon-picker-search { width: 100%; box-sizing: border-box; margin-bottom: 0.5em; padding: 0.3em 0.5em; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; }
/* max-height/overflow-y: a search match can return up to MAX_RESULTS (60,
   see icon-picker.js) icons — without a cap here the panel would grow to
   however tall that makes it, potentially off the bottom of the viewport. */
.icon-picker-icons { display: flex; flex-wrap: wrap; gap: 0.15em; margin-bottom: 0.5em; max-height: 12em; overflow-y: auto; }
.icon-picker-icon { background: none; border: 1px solid transparent; border-radius: 4px; padding: 0.3em; cursor: pointer; color: var(--fg); }
.icon-picker-icon .icon { margin-right: 0; }
.icon-picker-icon:hover { background: var(--bg-secondary); }
.icon-picker-icon.selected { border-color: var(--accent); }
.icon-picker-colors { display: flex; gap: 0.4em; align-items: center; }
.icon-picker-color { width: 1.4em; height: 1.4em; border-radius: 50%; border: 2px solid transparent; cursor: pointer; padding: 0; background: currentColor; }
.icon-picker-color.selected { border-color: var(--fg); }
.icon-picker-color-none { background: var(--bg-secondary); color: var(--muted); display: flex; align-items: center; justify-content: center; }
.icon-picker-color-none .icon { width: 0.9em; height: 0.9em; margin: 0; }
main a { color: var(--accent); }
.meta { color: var(--muted); }
/* Hides keyboard-only affordances on a touchscreen: (hover: none) and
   (pointer: coarse) together mean "no precise pointer is attached," which
   is what actually correlates with "no physical keyboard either" — a
   viewport-width breakpoint would misfire on a small desktop window or a
   tablet in portrait mode. A hybrid device with a mouse/trackpad attached
   still reports hover:hover and keeps seeing both. */
@media (hover: none) and (pointer: coarse) {
	#quick-switcher-trigger .kbd-hint { display: none; }
	body.app footer .vim-toggle { display: none; }
}

/* ---- layout.html ("app": every page behind login) ---- */
/* padding-bottom leaves room for the footer below, which is pinned to the
   viewport (position: fixed) rather than sitting in normal document flow —
   without this, a short page's last bit of content would end up hidden
   behind it. */
body.app main { padding: 1em 2em 4.5em; box-sizing: border-box; }
/* Same reasoning as body.app main's own padding-bottom above, for the same
   fixed footer: CodeMirror's fullscreen addon (see note-editor.js) covers
   the full viewport with position: fixed, so without this the last line
   being typed would end up hidden behind the footer's autosave-status/
   doc-stats. The footer's own z-index: 50 (below) already beats the
   fullscreen editor's default z-index: 9 with no extra rule needed, so it
   keeps rendering on top rather than getting covered itself. */
body.app .CodeMirror-fullscreen { padding-bottom: 4.5em; box-sizing: border-box; }
/* Shared by every small inline-flex form container on an app page —
   header, footer, and list.html's tree-header alike. */
body.app header form, body.app footer form, .tree-header form { margin: 0; display: inline-flex; gap: 0.3em; }
/* Every action in the header/footer that isn't plain GET navigation
   (Search, Export, Log out, theme/editor settings, Jump to note) has to be
   a real <button> — either because it POSTs, or because it needs
   confirm.js's data-confirm dialog, which only ever fires on a form's
   submit event, never on a plain <a> click. Left unstyled, those buttons
   would keep the browser's native chrome (border, background, UA font)
   while sitting next to header/footer's plain-text <a> links, which is
   the inconsistency this undoes: strip the native button look so every
   action reads as the same plain, colored, underlined text regardless of
   whether it happens to be a link or a button underneath. .btn-accent (New
   Note) is the one deliberate exception — see below, it needs to win back
   against this. */
body.app header button, body.app footer button { background: none; border: none; padding: 0; margin: 0; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; }
/* The one call-to-action button in the app — solid --accent fill, used
   sparingly so it still reads as "the" primary action rather than blending
   in with the plain-text buttons/links everywhere else (see the comment
   above). Shared with landing.html's OAuth login links, which is the same
   kind of single-primary-action moment. The header/footer-scoped rule
   below exists only to beat body.app header button's own text-decoration:
   underline/background: none above — .btn-accent itself doesn't need
   body.app-scoping anywhere else it's used. */
.btn-accent { background: var(--accent); color: #fff; padding: 0.4em 1em; border-radius: 4px; text-decoration: none; font-weight: bold; border: none; font: inherit; cursor: pointer; }
body.app header button.btn-accent, body.app footer button.btn-accent { background: var(--accent); color: #fff; padding: 0.4em 1em; text-decoration: none; }
body.app header input[type=search] { min-width: 10em; }
body.app header label.checkbox-label { display: inline-flex; align-items: center; gap: 0.3em; font-size: 0.9em; white-space: nowrap; }
body.app header .header-desktop-nav { display: flex; align-items: center; gap: 1em; }
/* Jump to note and the "Menu" disclosure sit together at the far right of
   the header, grouped in one .header-actions flex container (see
   layout.html) rather than each having its own margin-left: auto — with
   flex-wrap on the outer header, two SEPARATE auto-margin items can end up
   wrapping to a new line independently of each other (one squeezing onto
   the end of line 1 alone, the other landing at the start of line 2 with
   no margin to push it right), which looked broken in practice. Grouping
   them means the pair wraps to a new line together, staying adjacent and
   right-aligned as a unit. */
body.app header .header-actions { margin-left: auto; display: flex; align-items: center; gap: 1em; }
/* .header-more (the mobile-only "Menu" stand-in for .header-desktop-nav
   above) is hidden by default — this rule IS the desktop behavior: the
   830px breakpoint below is what turns it back on and hides
   .header-desktop-nav instead, so nothing here needs its own media query. */
body.app header .header-more { display: none; }
body.app header .header-more summary { cursor: pointer; list-style: none; display: inline-flex; align-items: center; }
body.app header .header-more summary::-webkit-details-marker { display: none; }
/* Opens downward (top: 100%, not bottom) since the header sits at the top
   of the page rather than being pinned like the footer, and right-anchored
   (right: 0) for the same reason the footer's own panel is: "Menu" is the
   header's rightmost item, so anchoring the panel's left edge to it would
   push its nowrap content off the right edge of the viewport on a narrow
   phone screen. */
body.app header .header-more { position: relative; }
body.app header .header-more-panel { position: absolute; top: 100%; right: 0; margin-top: 0.5em; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; padding: 0.6em; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); display: flex; flex-direction: column; align-items: flex-start; gap: 0.5em; white-space: nowrap; z-index: 60; }
body.app header .header-more-panel a { color: var(--fg); }
/* Below the same 820px breakpoint editor.css already uses for the note
   editor's split-pane collapse (kept consistent rather than picking a new
   number): swap .header-desktop-nav for the collapsed "Menu" version, and
   drop Jump to note's text down to icon-only — the header can't spare
   either at that width without wrapping to extra lines (see
   .header-actions above, and the 4-line report that started this). */
@media (max-width: 820px) {
	body.app header .header-desktop-nav { display: none; }
	body.app header .header-more { display: block; }
	body.app header #quick-switcher-trigger .qs-label,
	body.app header #quick-switcher-trigger .kbd-hint { display: none; }
	body.app header .my-notes-label { display: none; }
	/* Tighter padding/gap/button padding buys back just enough width for
	   Cedar Note/My Notes(icon)/New Note/Jump to note/Menu to fit on one
	   line down to a 360px-wide phone — a pure density tweak (nothing here
	   removes anything), scoped to the header alone so the footer and
	   .btn-accent's other use (landing.html's OAuth login buttons) keep
	   their own spacing. */
	body.app header { padding: 0.5em 0.6em; gap: 0.6em; }
	body.app header button.btn-accent { padding: 0.4em 0.6em; }
}
/* Occasional maintenance/account actions (Admin, Favorites, Shares,
   Export, Trash, theme/editor settings, Log out) — visually secondary to
   the header, not something reached for on every page view. Pinned to the
   viewport (not just the end of the document) so it's reachable without
   scrolling, the same way the header always is. */
body.app footer { position: fixed; bottom: 0; left: 0; right: 0; background: var(--footer-bg); border-top: 1px solid var(--border); padding: 0.6em 1em; display: flex; gap: 1em; align-items: center; flex-wrap: wrap; font-size: 0.9em; color: var(--footer-fg); z-index: 50; }
body.app footer a { color: var(--footer-fg); }
/* Pushed to the far right of the footer's flex row, same technique as the
   header's #quick-switcher-trigger — everything else in the footer stays
   left-aligned as a group. #offline-indicator carries the margin since it
   comes first in the footer's markup; #autosave-status/#doc-stats's own
   margin-left: auto (unchanged below) is redundant once it does but
   harmless — there's simply no space left for it to consume. */
body.app footer #offline-indicator { margin-left: auto; white-space: nowrap; color: var(--danger); font-weight: bold; }
body.app footer #autosave-status { margin-left: auto; white-space: nowrap; }
body.app footer #doc-stats { margin-left: auto; white-space: nowrap; }
/* Set via note-editor.js's setStatus() alongside #autosave-status's text —
   status-pending reuses the same muted-italic treatment .status-pending
   already gets for a pending share elsewhere, since both mean "not final
   yet"; status-error reuses --danger the same way #offline-indicator
   above does, so a failed/conflicting save reads as unmistakably as being
   offline does. status-offline splits the difference on purpose: nothing
   has failed, but an offline-queued edit can sit unsynced far longer than
   a routine save ever would, so it borrows --danger's color (matching
   #offline-indicator) without --danger's bold weight (which is reserved
   for an actual failure). */
body.app footer #autosave-status.status-pending { color: var(--muted); font-style: italic; }
body.app footer #autosave-status.status-offline { color: var(--danger); font-style: italic; }
/* white-space: normal overrides the base rule's nowrap — unlike every
   other status text here, a conflict message plus its "Reload" button
   (see showConflict in note-editor.js) can be long enough to need to wrap
   rather than force the footer wider than the viewport. */
body.app footer #autosave-status.status-error { color: var(--danger); font-weight: bold; white-space: normal; }
body.app footer #autosave-status.status-error button { margin-left: 0.5em; }
body.app footer label.checkbox-label { display: inline-flex; align-items: center; gap: 0.3em; white-space: nowrap; }
/* "More" overflow menu (see layout.html) for the footer's occasional
   items — Import, Trash, Privacy, Terms, Contact, editor settings, Log
   out, Export — same <details>/<summary> disclosure the icon picker uses
   (see .icon-picker above), so the frequently-used items ahead of it can
   fit on one line even on a phone. Opens upward (bottom: 100%, not top)
   since the footer itself is pinned to the bottom of the viewport, and
   right-anchored (right: 0, not left: 0) since "More" is the last/
   rightmost item in the footer — anchoring the panel's left edge to the
   summary's left edge instead would push its nowrap content off the right
   edge of the viewport on a narrow phone screen. */
body.app footer .footer-more { position: relative; }
body.app footer .footer-more summary { cursor: pointer; list-style: none; display: inline-flex; align-items: center; }
body.app footer .footer-more summary::-webkit-details-marker { display: none; }
body.app footer .footer-more-panel { position: absolute; bottom: 100%; right: 0; margin-bottom: 0.5em; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; padding: 0.6em; box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.15); display: flex; flex-direction: column; align-items: flex-start; gap: 0.5em; white-space: nowrap; z-index: 60; }
body.app footer .footer-more-panel a { color: var(--fg); }
body.app .shared-badge { color: var(--muted); font-size: 0.85em; white-space: nowrap; }
body.app .note-folder { color: var(--muted); }
/* Used inside note.html's/folder.html's shareBox and on shares.html's own
   lists alike — not scoped to .shares, since not every one of those is
   wrapped in that div. */
body.app .status-pending { color: var(--muted); font-style: italic; }
body.app .panel { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 6px; padding: 0.6em 1em; }
/* [hidden] needs the explicit override below since the overlay's own open
   state sets display: flex — a later, more specific display declaration
   wins over the UA stylesheet's default `[hidden] { display: none }`. */
body.app .quick-switcher-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); display: flex; align-items: flex-start; justify-content: center; padding-top: 10vh; z-index: 100; }
body.app .quick-switcher-overlay[hidden] { display: none; }
body.app .quick-switcher-box { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; width: 90%; max-width: 480px; padding: 0.6em; }
body.app .quick-switcher-box input { width: 100%; box-sizing: border-box; font-size: 1.1em; padding: 0.4em; margin-bottom: 0.4em; }
body.app .quick-switcher-results { list-style: none; padding-left: 0; margin: 0; max-height: 50vh; overflow-y: auto; }
body.app .quick-switcher-results li { padding: 0.4em 0.6em; border-radius: 4px; cursor: pointer; }
body.app .quick-switcher-results li.active { background: var(--border); }
@media print {
	body.app header, body.app footer { display: none; }
}

/* ---- list.html ---- */
/* Fills the available width the same way .editor-container does on
   note.html (flex-grow panes, no cap) rather than the fixed-max-width,
   centered pair this used to be — that design left unused space outside
   the pair on anything wider than ~930px, which also meant .top-panel had
   just 380px to fit the sort tabs in, wrapping once a fifth (Favorites)
   was added. 3:2 approximates the old 550:380 proportion. */
.notes-layout { display: flex; gap: 3em; align-items: flex-start; }
.tree-panel { flex: 3; min-width: 0; }
.top-panel { flex: 2; min-width: 0; border-left: 1px solid var(--border); padding-left: 1.5em; }
.tree-panel ul { list-style: none; padding-left: 1.2em; }
.tree-panel > ul { padding-left: 0; }
.sort-tabs { display: inline-flex; flex-wrap: wrap; gap: 0.2em; margin-bottom: 0.8em; background: var(--border); padding: 0.2em; border-radius: 6px; }
.sort-tabs a { padding: 0.3em 0.7em; text-decoration: none; color: var(--fg); border-radius: 4px; }
.sort-tabs a.active { background: var(--bg); font-weight: bold; }
.tree-header { display: flex; align-items: baseline; gap: 1em; flex-wrap: wrap; }
.tree-panel summary { cursor: pointer; }
.drop-target-active { outline: 2px dashed var(--accent); outline-offset: 2px; border-radius: 4px; }
@media (max-width: 820px) {
	.notes-layout { flex-direction: column; }
	.top-panel { border-left: none; padding-left: 0; border-top: 1px solid var(--border); padding-top: 1em; margin-top: 1em; }
}

/* ---- search.html ---- */
.search-results { list-style: none; padding-left: 0; }
.search-results li { padding: 0.6em 0; border-bottom: 1px solid var(--border); }
.search-snippet { color: var(--muted); margin: 0.3em 0 0; }

/* ---- shares.html / trash.html / history.html ---- */
/* All three wrap their list in this one class — same plain
   list-with-a-divider-per-row look, nothing page-specific about it. */
.plain-list-page ul { list-style: none; padding-left: 0; }
.plain-list-page li { display: flex; gap: 0.5em; align-items: center; padding: 0.3em 0; border-bottom: 1px solid var(--border); }

/* ---- history_version.html ---- */
.version-preview { border: 1px solid var(--border); border-radius: 6px; padding: 0 1em; background: var(--bg-secondary); }

/* ---- admin.html ---- */
.admin-stats { display: flex; gap: 1em; flex-wrap: wrap; margin: 1em 0 1.5em; }
.stat-card { border: 1px solid var(--border); border-radius: 6px; padding: 0.6em 1.2em; min-width: 100px; background: var(--bg-secondary); }
.stat-card .value { font-size: 1.8em; font-weight: bold; display: block; }
.stat-card .label { color: var(--muted); font-size: 0.9em; }
table.admin-users { border-collapse: collapse; width: 100%; max-width: 700px; }
table.admin-users th, table.admin-users td { text-align: left; padding: 0.4em 0.8em; border-bottom: 1px solid var(--border); }

/* ---- note.html ---- */
/* Holds the icon badge and the title input side by side — without this,
   the input's own width: 100% (below) leaves no room on the same line and
   the icon badge (an inline-block sibling) wraps above it instead of
   sitting to its left. */
.note-title-row { display: flex; align-items: center; gap: 0.4em; }
.note-title-row .icon-picker { flex-shrink: 0; }
.note-title-row input[name="title"] { width: auto; flex: 1; min-width: 0; }
input[name="title"] { font-size: 1.4em; font-weight: bold; width: 100%; box-sizing: border-box; background: var(--bg); color: var(--fg); border: 1px solid var(--border); }
.toolbar { margin: 0.5em 0; display: flex; gap: 0.5em; align-items: center; flex-wrap: wrap; }
.toolbar .button-link { background: var(--bg-secondary); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; padding: 0.3em 0.8em; text-decoration: none; font-size: 0.9em; }
.tags { margin: 0.5em 0; display: flex; gap: 0.4em; flex-wrap: wrap; align-items: center; }
.tag { background: var(--border); border-radius: 1em; padding: 0.1em 0.6em; display: inline-flex; align-items: center; gap: 0.3em; }
.tag a { color: inherit; }
.tag form { display: inline; margin: 0; }
.tag-remove { background: none; border: none; cursor: pointer; padding: 0; font-size: 1em; }
.shares { margin: 0.5em 0; padding: 0.5em; border: 1px solid var(--border); border-radius: 4px; background: var(--bg-secondary); }
.shares ul { list-style: none; padding-left: 0; margin: 0.3em 0; }
.shares li { display: flex; gap: 0.5em; align-items: center; padding: 0.2em 0; }
.pane-toggle.active { font-weight: bold; }
.editor-pane.hidden { display: none; }
.format-toolbar { margin-bottom: 0.4em; display: flex; gap: 0.3em; flex-wrap: wrap; }
.format-toolbar button { background: var(--bg-secondary); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; padding: 0.2em 0.6em; font-size: 0.9em; cursor: pointer; min-width: 2em; }
.format-toolbar button:hover { background: var(--border); }
/* These buttons are icon-only (no adjacent label) — .icon's margin-right
   exists for icon+text pairs elsewhere and would just off-center the icon
   here. */
.format-toolbar .icon { margin-right: 0; }
.wikilink-autocomplete { position: absolute; z-index: 60; background: var(--bg); border: 1px solid var(--border); border-radius: 4px; list-style: none; margin: 0; padding: 0.2em 0; max-height: 200px; overflow-y: auto; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); }
.wikilink-autocomplete li { padding: 0.3em 0.6em; cursor: pointer; white-space: nowrap; }
.wikilink-autocomplete li.active { background: var(--border); }
/* Scoped to #note-form (unique to note.html) rather than the bare
   .editor-pane .CodeMirror selector — landing.html's demo editors want a
   different height for that same selector, scoped to .demo-row instead;
   see landing.html's section below. */
#note-form .editor-pane .CodeMirror { height: 34em; }
/* Preview only gets a matching fixed height (with its own scrollbar) while
   .split is on the container — note-editor.js adds that class exactly when
   Edit and Preview are both toggled on, since a single visible pane should
   still grow to fit its content instead of clipping it behind a scrollbar. */
#note-form .editor-container.split .preview-pane { height: 34em; overflow-y: auto; box-sizing: border-box; }
/* The Outline pane (note-outline.js): a narrow column left of the editor
   rather than a third equal pane — it only ever holds short headings.
   Capped at the editor's height with its own scrollbar, so a long outline
   doesn't push the page taller than the editor beside it. */
.outline-pane { flex: 0 0 12em; min-width: 0; max-height: 34em; overflow-y: auto; border-right: 1px solid var(--border); padding-right: 0.6em; font-size: 0.9em; }
.outline-pane.hidden { display: none; }
.outline-pane ul { list-style: none; margin: 0; padding: 0; }
.outline-item { display: block; width: 100%; background: none; border: none; color: var(--fg); font: inherit; text-align: left; cursor: pointer; padding: 0.15em 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.outline-item:hover { color: var(--accent); }
.outline-depth-1 { padding-left: 0.9em; }
.outline-depth-2 { padding-left: 1.8em; }
.outline-depth-3 { padding-left: 2.7em; }
.outline-depth-4 { padding-left: 3.6em; }
.outline-depth-5 { padding-left: 4.5em; }
.outline-empty { color: var(--muted); margin: 0; }
/* Matches editor.css's breakpoint where the panes stack: no room for a
   column, so the outline becomes a short scrolling list above the editor. */
@media (max-width: 820px) {
	.outline-pane { flex: none; max-height: 12em; border-right: none; border-bottom: 1px solid var(--border); padding: 0 0 0.5em; }
}
@media print {
	input[name="title"] { border: none; }
	.toolbar, .tags, .shares, #edit-pane, #outline-pane { display: none !important; }
	/* height/overflow reset: printing happens from whatever toggle state the
	   page was left in, and the .split height above would otherwise clip
	   the printed note to one scrollable page's worth of content. */
	#preview-pane { border: none; padding: 0; width: 100% !important; height: auto !important; overflow: visible !important; }
}

/* ---- landing.html ---- */
body.landing header { justify-content: space-between; }
body.landing header .welcome { color: var(--header-fg); }
body.landing header .login-options { display: flex; gap: 0.5em; }
body.landing main { padding: 1em 2em; box-sizing: border-box; }
body.landing h1 { margin-top: 0; }
.tagline { color: var(--muted); }
.demo-row { margin: 2em 0; }
.demo-row h2 { margin-bottom: 0.2em; }
.demo-row p.demo-note { color: var(--muted); margin-top: 0; }
.try-list { color: var(--muted); font-size: 0.9em; margin: 0.4em 0 0.8em; padding-left: 1.3em; }
.try-list li { margin: 0.15em 0; }
.stacked-form label { display: block; margin: 0.6em 0; }
.stacked-form input[type="text"] { display: block; width: 100%; max-width: 28em; box-sizing: border-box; }
.stacked-form input[type="file"] { display: block; margin-top: 0.3em; }
.try-list code { background: var(--bg-secondary); padding: 0.1em 0.3em; border-radius: 3px; font-family: monospace; }
.feature-list { list-style: none; padding-left: 0; margin: 1em 0 2em; }
.feature-list li { margin: 0.6em 0; }
/* Scoped to .demo-row (unique to landing.html) — see the #note-form rule
   above; same selector, different height, on a different page. */
.demo-row .editor-pane .CodeMirror { border-radius: 4px; height: 22em; font-size: 0.95em; }
.demo-row .preview-pane { overflow-x: auto; height: 22em; overflow-y: auto; box-sizing: border-box; }
.landing-footer { padding: 1em 2em; color: var(--muted); display: flex; gap: 1em; flex-wrap: wrap; }
.landing-footer a { color: var(--muted); }

/* ---- public_note.html ---- */
/* Public share links are viewed by anonymous, logged-out visitors with no
   theme preference to read — these are the same values light.css defines,
   kept here as this page's fixed palette instead of pulling in every
   theme file just to always pick "light." Scoped to <html> (not :root) so
   they don't leak into layout.html/landing.html, which set these same
   variables from the signed-in user's chosen theme file. */
html.public-note { --bg: #ffffff; --fg: #1a1a1a; --header-bg: #2c2c2c; --header-fg: #ffffff; --border: #dddddd; --muted: #6b6b6b; --accent: #1a73e8; --bg-secondary: #f5f5f5; --danger: #c0392b; }
body.public-note main { padding: 1em; max-width: 700px; margin: 0 auto; box-sizing: border-box; }

/* ---- not_found.html, privacy.html, terms.html ---- */
/* Same fixed light palette as html.public-note above, for the same reason:
   these are plain unauthenticated pages with no per-user theme to read. */
html.plain-page { --bg: #ffffff; --fg: #1a1a1a; --header-bg: #2c2c2c; --header-fg: #ffffff; --border: #dddddd; --muted: #6b6b6b; --accent: #1a73e8; --bg-secondary: #f5f5f5; --danger: #c0392b; }
.legal-page { padding: 1em; max-width: 700px; margin: 0 auto; box-sizing: border-box; }
.legal-page h2 { margin-top: 1.5em; }

/* ---- contact.html ---- */
.contact-form { display: flex; flex-direction: column; gap: 1em; }
.contact-form label { display: flex; flex-direction: column; gap: 0.3em; font-weight: bold; }
.contact-form input, .contact-form textarea { font: inherit; padding: 0.4em; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; box-sizing: border-box; }
.contact-form button { align-self: start; }
/* Honeypot: invisible to a sighted visitor and pulled out of tab order, but
   still present in the DOM for a bot's naive "fill in every field" script
   to find — see ContactSubmitHandler. display:none is deliberately avoided
   since some bots skip fields a screen-reader-style DOM check would flag
   as hidden that way; an off-screen position survives that check. */
.hp-field { position: absolute; left: -9999px; }

/* ---- graph.html ---- */
.graph-container { overflow: auto; }
.graph-container svg { max-width: none; }

/* ---- import.html ---- */
.error { color: var(--danger); }

/* ---- offline.html ---- */
.offline-page { padding: 2em; max-width: 500px; margin: 0 auto; box-sizing: border-box; }
