/* Layout, typography, and chrome.
 *
 * Theme colors come from themes.css as --me-* custom properties, generated
 * from the macOS app's EditorColorTheme. Nothing here hard-codes a palette
 * color, so all sixteen themes work by flipping two attributes on <html>.
 *
 * The point sizes and spacing are the ones in PRD section 13, treated as CSS
 * pixels. The rendered and source panes deliberately share them so the two
 * halves of Split keep the same vertical proportions and scroll together
 * meaningfully (E-19).
 */

:root {
  --me-body-size: 15px;
  --me-code-size: 13px;
  --me-h1-size: 30px;
  --me-h2-size: 25px;
  --me-h3-size: 21px;
  --me-h4-size: 18px;
  --me-h5-size: 16px;
  --me-h6-size: 15px;

  --me-line-height: 1.45;
  --me-paragraph-gap: 7px;
  --me-heading-gap-large: 14px;
  --me-heading-gap-small: 9px;
  --me-heading-gap-below: 8px;
  --me-list-indent: 24px;
  --me-quote-inset: 20px;

  --me-sidebar-width: 240px;
  /* The measure the document is set at. Named "preview" from when there were
     two panes and this was the width of one of them; kept because it is
     written into every reader's localStorage and into the image-bleed
     arithmetic that the stylesheet tests check. */
  --me-preview-width: 700px;
  /* The page is wider than the column the text is set in. This is how much
     wider it may be, on each side, and a picture is the only thing allowed to
     use it — text stays at the column, because a longer line is a worse line
     to read. Matches EditorPaneGeometry.maximumImageBleed on the Mac. */
  --me-image-bleed-max: 100px;
  /* Off unless something turns it on. Only the Rich Text pane on its own has
     margins to reach into: in Split the pane is exactly the column wide, and
     an overhang there would hang over the divider. */
  --me-image-bleed: 0px;
  --me-surface-padding: 24px;
  /* The column itself: the surface's width less the padding either side. */
  --me-measure: calc(var(--me-preview-width) - 2 * var(--me-surface-padding));

  --me-ui-font: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --me-text-font: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --me-mono-font: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* The face the document is set in, and what to multiply its sizes by so it
     reads at the size the numbers above promise (T-16). theme.js sets both
     from Customize Theme; code keeps --me-mono-font whatever the face. */
  --me-page-font: var(--me-text-font);
  --me-page-scale: 1;

  /* How large the document is drawn, from Customize Theme ▸ Size (T-23):
     0.75 to 1.5, set by theme.js. It multiplies everything the text is set
     with — type, the gaps between paragraphs, the indents of lists, quotes
     and code — so 150% is the same page drawn larger. The column and the
     pictures in it keep their size. */
  --me-text-scale: 1;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  font-family: var(--me-ui-font);
  font-size: 13px;
  color: var(--me-primary-text);
  background: var(--me-canvas-background);
  -webkit-font-smoothing: antialiased;
}

/* A tint and no text colour, so selected words keep their own. */
::selection {
  background: var(--me-text-selection-background);
}

/* T-24: in the document the editor draws the selection itself — rounded, and
   fading where it runs on across lines — so the browser's square one is
   switched off there, but only while selection-highlight.js is drawing. */
.me-surface[data-draws-selection]::selection,
.me-surface[data-draws-selection] ::selection {
  background: transparent;
}

/* ---------------------------------------------------------------- app shell */

.me-app {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.me-app[hidden] { display: none; }

.me-body {
  display: flex;
  flex: 1;
  min-height: 0;
  /* The explorer is positioned against this on both layouts. */
  position: relative;
}

/* WT-13: on desktop the explorer floats over the document instead of displacing
   it. Two things follow. The document keeps one position on screen whatever
   the nav is doing — no reflow, no sideways jump, and its centre is the centre
   of the page rather than the centre of what the nav left over. And a closed
   nav is the resting state, so the calm case costs nothing to reach. */
.me-app:not([data-layout="mobile"]) .me-sidebar {
  position: absolute;
  inset-block: 0;
  left: 0;
  z-index: 40;
  flex: 0 0 auto;
  border-right: 1px solid var(--me-separator);
  box-shadow: 0 0 24px rgb(0 0 0 / 12%);
}

/* The width gripper follows the floating panel, so the explorer can still be
   resized even though it is no longer part of the row. */
.me-app:not([data-layout="mobile"]) .me-divider--sidebar {
  position: absolute;
  inset-block: 0;
  left: var(--me-sidebar-width);
  z-index: 41;
}

/* ------------------------------------------------------------------ menu bar */

/* WT-14: the chrome shares the page's own background. Tinted bands with hard
   rules under them read as three stacked panels; one continuous field reads as
   a page with some tools resting on it, which is the calmer of the two. */
.me-menubar {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 0 10px;
  height: 30px;
  flex: 0 0 auto;
  background: var(--me-page-background);
  user-select: none;
}

.me-menubar__title {
  font-weight: 700;
  padding-right: 10px;
  opacity: 0.85;
}

.me-menu {
  position: relative;
}

.me-menu__button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 4px 9px;
  border-radius: 5px;
  cursor: default;
}

.me-menu__button:hover,
.me-menu__button[aria-expanded="true"] {
  background: var(--me-selection-background);
  color: var(--me-selection-text);
}

.me-menu__list {
  position: absolute;
  top: calc(100% + 3px);
  left: 0;
  min-width: 232px;
  padding: 5px;
  margin: 0;
  list-style: none;
  z-index: 40;
  background: var(--me-page-background);
  border: 1px solid var(--me-separator);
  border-radius: 8px;
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.22);
}

.me-menu__list[hidden] { display: none; }

/* Anchored to a point rather than to a button, so the menu-bar offsets have to
   go; the exact position is set inline once the size is known. */
.me-menu__list--context {
  top: 0;
  left: 0;
  min-width: 188px;
}

.me-menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 5px 9px;
  border-radius: 5px;
  cursor: default;
  text-align: left;
  white-space: nowrap;
}

.me-menu__item:disabled {
  opacity: 0.4;
}

.me-menu__item:not(:disabled):hover {
  background: var(--me-selection-background);
  color: var(--me-selection-text);
}

.me-menu__shortcut {
  margin-left: auto;
  padding-left: 22px;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

.me-menu__item:hover .me-menu__shortcut { opacity: 0.85; }

.me-menu__check {
  width: 12px;
  flex: 0 0 12px;
  text-align: center;
}

.me-menu__separator {
  height: 1px;
  margin: 5px 8px;
  background: var(--me-separator);
}

/* ------------------------------------------------------------------- toolbar */

.me-toolbar {
  display: flex;
  align-items: center;
  gap: 11px;
  flex: 0 0 auto;
  padding: 6px 10px;
  min-height: 42px;
  flex-wrap: wrap;
  background: var(--me-page-background);
  /* Kept, and only just visible: text scrolling up under the tools needs
     somewhere to stop, but a full-strength rule draws the eye to the chrome. */
  border-bottom: 1px solid color-mix(in srgb, var(--me-separator) 45%, transparent);
  user-select: none;
}

.me-toolbar__group {
  display: flex;
  align-items: center;
  gap: 2px;
}

/* The gap between groups already separates them. A drawn line for every one of
   them is six more marks on screen saying what the spacing has said already. */
.me-toolbar__separator { display: none; }

.me-toolbar__spacer { flex: 1; }

.me-tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 28px;
  padding: 0;
  font: inherit;
  /* Secondary until wanted. The document is the thing with something to say;
     the tools only need to be findable. */
  color: var(--me-secondary-text);
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: default;
}

.me-tool:hover:not(:disabled) {
  background: color-mix(in srgb, var(--me-primary-text) 8%, transparent);
  color: var(--me-primary-text);
}

.me-tool:disabled { opacity: 0.35; }

/* A tint and the accent, not a filled block. An active Bold button is a state
   worth reading, not an alarm. */
.me-tool[aria-pressed="true"] {
  background: color-mix(in srgb, var(--me-accent) 14%, transparent);
  color: var(--me-accent);
}

.me-tool svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.me-tool svg .me-fill { fill: currentColor; stroke: none; }
.me-tool--wide { width: auto; padding: 0 9px; gap: 5px; }

/* ------------------------------------------------------------------- sidebar */

.me-sidebar {
  display: flex;
  flex-direction: column;
  flex: 0 0 var(--me-sidebar-width);
  width: var(--me-sidebar-width);
  min-width: 0;
  background: var(--me-sidebar-background);
  overflow: hidden;
}

.me-sidebar[hidden] { display: none; }

.me-sidebar__header {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 6px 6px 6px 10px;
  border-bottom: 1px solid var(--me-separator);
}

.me-sidebar__path {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: 1;
  min-width: 0;
  font: inherit;
  font-weight: 600;
  color: inherit;
  background: none;
  border: 0;
  padding: 3px 5px;
  border-radius: 5px;
  cursor: default;
  text-align: left;
}

.me-sidebar__path:hover { background: color-mix(in srgb, var(--me-accent) 16%, transparent); }
.me-sidebar__path span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.me-chevron { width: 9px; height: 6px; flex: 0 0 9px; }

.me-icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 5px;
  cursor: default;
  opacity: 0.75;
}

.me-icon-button:hover { background: color-mix(in srgb, var(--me-accent) 16%, transparent); opacity: 1; }
.me-icon-button svg { width: 15px; height: 15px; }

.me-sidebar__tree {
  flex: 1;
  overflow: auto;
  padding: 5px 6px 14px;
}

.me-tree__row {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 3px 6px;
  border-radius: 6px;
  cursor: default;
  white-space: nowrap;
  user-select: none;
}

.me-tree__row:hover { background: color-mix(in srgb, var(--me-accent) 15%, transparent); }

/* WF-10: the drag itself fades, and the folder that would receive it is
   outlined, so a drop always says where it is going before it happens. */
.me-tree__row--dragging { opacity: 0.4; }

.me-tree__row--drop,
.me-sidebar__tree--drop {
  background: color-mix(in srgb, var(--me-accent) 22%, transparent);
  outline: 1.5px solid var(--me-accent);
  outline-offset: -1.5px;
  border-radius: 6px;
}

/* X-15: selected rows use the theme accent with an automatically contrasting
   label, which is what keeps text readable across all sixteen themes. */
.me-tree__row[aria-selected="true"] {
  background: var(--me-selection-background);
  color: var(--me-selection-text);
}

.me-tree__row--other { color: var(--me-secondary-text); }
.me-tree__row[aria-selected="true"].me-tree__row--other { color: var(--me-selection-text); }

.me-tree__twisty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  flex: 0 0 13px;
  opacity: 0.7;
}

.me-tree__twisty svg {
  width: 8px;
  height: 8px;
  transition: transform 120ms ease;
}

.me-tree__row[aria-expanded="true"] .me-tree__twisty svg { transform: rotate(90deg); }

.me-tree__icon { flex: 0 0 15px; width: 15px; height: 15px; opacity: 0.85; }
.me-tree__label { overflow: hidden; text-overflow: ellipsis; }
.me-tree__children { padding-left: 14px; }
.me-tree__empty { padding: 8px 10px; color: var(--me-secondary-text); }

/* ------------------------------------------------------------------ dividers */

.me-divider {
  flex: 0 0 6px;
  cursor: col-resize;
  background: transparent;
  position: relative;
}

.me-divider::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 50%;
  width: 1px;
  transform: translateX(-50%);
  background: var(--me-separator);
}

.me-divider:hover::after,
.me-divider:focus-visible::after {
  background: var(--me-accent);
  width: 2px;
}

.me-divider:focus-visible { outline: none; }
.me-divider[hidden] { display: none; }

/* -------------------------------------------------------------------- panes */

.me-editor {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  min-height: 0;
  background: var(--me-page-background);
}

/* The panes are a row inside the editor's column so that a notice can sit
   above both of them and push them down rather than cover them. */
.me-editor__panes {
  display: flex;
  flex: 1;
  min-width: 0;
  min-height: 0;
}

/* WC-10. Says the document was changed by something else. A bar rather than a
   dialog: it is very often not urgent, and a dialog would have to be dismissed
   before the document it is talking about could be looked at. */
.me-notice {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  padding: 9px 14px;
  border-bottom: 1px solid var(--me-separator);
  background: color-mix(in srgb, var(--me-accent) 12%, var(--me-page-background));
  font-size: 13px;
  color: var(--me-primary-text);
}

.me-notice[hidden] { display: none; }

.me-notice[data-kind="conflict"] {
  background: color-mix(in srgb, #d97706 16%, var(--me-page-background));
}

.me-notice__text { flex: 1; min-width: 0; }

.me-notice__actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.me-notice__button {
  padding: 4px 10px;
  border: 1px solid var(--me-separator);
  border-radius: 6px;
  background: var(--me-page-background);
  color: var(--me-primary-text);
  font: inherit;
  cursor: pointer;
}

.me-notice__button:hover { border-color: var(--me-accent); }

.me-notice__button--primary {
  border-color: var(--me-accent);
  color: var(--me-accent);
  font-weight: 600;
}

.me-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: auto;
  background: var(--me-page-background);
}

.me-pane[hidden] { display: none; }

/* There is one pane, and it fills the editor. */
.me-pane--rich { flex: 1; }

/* The document is centred at a fixed measure rather than set to the width of
   the window, because a line of text that runs the width of a monitor is a
   line nobody can find their way back to the start of. */
.me-pane--rich .me-surface {
  width: 100%;
  /* Whatever room is left over each side of the column, up to the maximum —
     the same rule as EditorPaneGeometry.imageBleed, and it collapses to
     nothing on a screen too narrow to afford it rather than pushing the text
     off the side. The explorer floats, so the pane really is the viewport. */
  --me-image-bleed: clamp(
    0px,
    (100vw - var(--me-preview-width)) / 2,
    var(--me-image-bleed-max)
  );
  /* The page, not the column: the extra is margin a picture may reach into.
     The padding puts it back for the text, so the measure is exactly what it
     was before the margins existed. */
  max-width: calc(var(--me-preview-width) + 2 * var(--me-image-bleed));
  margin: 0 auto;
  padding-left: calc(var(--me-surface-padding) + var(--me-image-bleed));
  padding-right: calc(var(--me-surface-padding) + var(--me-image-bleed));
}

.me-surface {
  /* Basis auto, not 0: with `flex: 1` the surface is pinned to the pane's
     height, its bottom padding sits inside that frame, and overflowing text
     scrolls straight past it — so the document ends flush against the bottom
     edge with no breathing room and no way to scroll further. Sizing to
     content instead puts the padding at the end of the scroll range, and grow
     still fills a short document so the whole pane stays clickable. */
  flex: 1 0 auto;
  min-height: 100%;
  padding: 20px var(--me-surface-padding);      /* Y-7 */
  outline: none;
  font-family: var(--me-page-font);
  font-size: calc(var(--me-body-size) * var(--me-page-scale) * var(--me-text-scale));
  line-height: var(--me-line-height);
  color: var(--me-primary-text);
  caret-color: var(--me-primary-text);
  white-space: pre-wrap;
  overflow-wrap: break-word;
  tab-size: 4;
}

/* ------------------------------------------------------- rendered block styles */

.me-block { margin: 0; }
.me-block + .me-block { margin-top: calc(var(--me-paragraph-gap) * var(--me-text-scale)); }

.me-h1, .me-h2, .me-h3, .me-h4, .me-h5, .me-h6 {
  font-weight: 700;
  line-height: 1.2;
  margin: 0;
}

.me-block.me-h1, .me-block.me-h2 { margin-top: calc(var(--me-heading-gap-large) * var(--me-text-scale)); }
.me-block.me-h3, .me-block.me-h4,
.me-block.me-h5, .me-block.me-h6 { margin-top: calc(var(--me-heading-gap-small) * var(--me-text-scale)); }
.me-h1 + .me-block, .me-h2 + .me-block,
.me-h3 + .me-block, .me-h4 + .me-block,
.me-h5 + .me-block, .me-h6 + .me-block { margin-top: calc(var(--me-heading-gap-below) * var(--me-text-scale)); }

.me-h1 { font-size: calc(var(--me-h1-size) * var(--me-page-scale) * var(--me-text-scale)); }
.me-h2 { font-size: calc(var(--me-h2-size) * var(--me-page-scale) * var(--me-text-scale)); }
.me-h3 { font-size: calc(var(--me-h3-size) * var(--me-page-scale) * var(--me-text-scale)); }
.me-h4 { font-size: calc(var(--me-h4-size) * var(--me-page-scale) * var(--me-text-scale)); }
.me-h5 { font-size: calc(var(--me-h5-size) * var(--me-page-scale) * var(--me-text-scale)); }
.me-h6 { font-size: calc(var(--me-h6-size) * var(--me-page-scale) * var(--me-text-scale)); }

/* Y-3: a hanging indent so wrapped lines align under the text, not the bullet. */
.me-list {
  padding-left: calc(var(--me-list-indent) * var(--me-text-scale));
  text-indent: calc((-1 * var(--me-list-indent) + 5px) * var(--me-text-scale));
}

.me-quote {
  padding-left: calc(var(--me-quote-inset) * var(--me-text-scale));
  padding-right: calc(8px * var(--me-text-scale));   /* Y-4 */
  border-left: 3px solid color-mix(in srgb, var(--me-primary-text) 28%, transparent);
}

/* Every `>` line is a block of its own, and the gap between blocks is a
   margin, which the border does not cross: a quote of three lines drew as
   three dashes. The same gap as padding keeps it one bar (Y-4). */
.me-block.me-quote + .me-block.me-quote {
  margin-top: 0;
  padding-top: calc(var(--me-paragraph-gap) * var(--me-text-scale));
}

.me-rule {
  text-align: center;
  margin: calc(8px * var(--me-text-scale)) 0;         /* Y-6 */
  color: var(--me-secondary-text);
}

/* Y-5: one continuous rounded rectangle behind the whole fenced block, with
   the opening line flush with every following line. */
.me-code-block {
  font-family: var(--me-mono-font);
  font-size: calc(var(--me-code-size) * var(--me-text-scale));
  background: var(--me-code-block-background);
  padding: calc(2px * var(--me-text-scale)) calc(12px * var(--me-text-scale));
  margin: 0;
}

/* Lines inside one fence must not be separated, or the rounded rectangle
   breaks into stripes (Y-5). */
.me-block.me-code-block + .me-block.me-code-block { margin-top: 0; }

.me-code-block--first {
  padding-top: calc(9px * var(--me-text-scale));
  border-radius: 7px 7px 0 0;
  margin-top: calc(var(--me-paragraph-gap) * var(--me-text-scale));
}
.me-code-block--last { padding-bottom: calc(9px * var(--me-text-scale)); border-radius: 0 0 7px 7px; }
.me-code-block--first.me-code-block--last { border-radius: 7px; }

.me-bold { font-weight: 700; }
.me-italic { font-style: italic; }
.me-underline { text-decoration: underline; }
.me-strike { text-decoration: line-through; }

.me-code {
  font-family: var(--me-mono-font);
  font-size: calc(var(--me-code-size) * var(--me-text-scale));
  background: var(--me-inline-code-background);
  border-radius: 4px;
  padding: 1px 4px;
}

.me-link { color: var(--me-accent); text-decoration: underline; }

.me-image {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  vertical-align: middle;
}

.me-image img {
  max-width: min(100%, 640px);
  max-height: 420px;
  border-radius: 6px;
  vertical-align: middle;
}

/* An explicit size is the author's instruction, so the default cap must not
   quietly override it. Only the page still constrains it, because an image
   wider than the page would be unusable rather than merely large. */
.me-image img[width],
.me-image img[height] {
  max-width: calc(100% + 2 * var(--me-image-bleed));
  max-height: none;
  height: auto;
}

/* A line holding nothing but a picture gives up its share of the column as the
   picture outgrows it, so the picture spreads into both margins and stays
   centred on the column. The two rules meet exactly at the column's width, so
   there is no jump as a picture is dragged past it. The same arithmetic as
   EditorPaneGeometry.imageParagraphIndent, expressed the other way round:
   here it is the overhang rather than what is left of the indent. */
.me-block--image {
  --me-image-overhang: min(
    var(--me-image-bleed),
    max(0px, (var(--me-image-width, 0px) - var(--me-measure)) / 2)
  );
  margin-left: calc(-1 * var(--me-image-overhang));
  margin-right: calc(-1 * var(--me-image-overhang));
}

.me-image--selected img {
  outline: 2px solid var(--me-accent);
  outline-offset: 2px;
}

/* WI-22: the resize frame, drawn over the selected image rather than inside it.
   Nothing may be nested in `.me-image`, whose text content is one placeholder
   character standing in for the whole reference. */
.me-image-frame {
  position: absolute;
  z-index: 5;
  pointer-events: none;
}

.me-image-frame__handle {
  position: absolute;
  width: 11px;
  height: 11px;
  padding: 0;
  border: 1px solid var(--me-page-background);
  border-radius: 50%;
  background: var(--me-accent);
  box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
  pointer-events: auto;
}

.me-image-frame__handle:focus-visible {
  outline: 2px solid var(--me-accent);
  outline-offset: 2px;
}

/* Centred on the corner, so the grab point is the corner itself. */
.me-image-frame__handle--nw { top: -6px; left: -6px; cursor: nwse-resize; }
.me-image-frame__handle--ne { top: -6px; right: -6px; cursor: nesw-resize; }
.me-image-frame__handle--sw { bottom: -6px; left: -6px; cursor: nesw-resize; }
.me-image-frame__handle--se { bottom: -6px; right: -6px; cursor: nwse-resize; }

/* While dragging, the pointer is captured and may travel anywhere on screen;
   the cursor has to stay the resize cursor the whole way. */
.me-image-frame[data-dragging] { pointer-events: auto; }
.me-image-frame[data-dragging]::after {
  content: "";
  position: fixed;
  inset: 0;
  cursor: nwse-resize;
}

/* Moving a picture (WI-24).

   The pointer keeps a hand over a picture's body, so it reads as something to
   pick up rather than somewhere to type. The corners keep their resize cursors,
   which they must: a corner is a resize, not a move. */
.me-image { cursor: grab; }
.me-image--moving { cursor: grabbing; opacity: 0.45; }

/* While a picture is being carried the pointer may travel anywhere, so the
   grabbing cursor has to hold for the whole gesture. */
[data-moving-image] .me-block,
[data-moving-image] .me-image { cursor: grabbing; }

/* T-24: the selection's bars (selection-highlight.js).

   The layer follows the surface inside the scrolling pane, so the bars scroll
   with the words for free; it takes no room and no clicks. The clip covers
   exactly the surface, so a fade reaching past the pane's edge cannot make the
   pane scroll sideways. Neither may start a stacking context — no z-index,
   opacity, transform or isolation — because each bar blends with the text
   beneath it, and that only works if the text is in the same group. */
.me-selection-layer {
  position: relative;
  flex: none;
  height: 0;
  pointer-events: none;
  user-select: none;
}

.me-selection-layer__clip {
  position: absolute;
  left: 0;
  right: 0;
  overflow: hidden;
}

/* Over the words, blended so they keep their colours: multiply on a light
   page, screen on a dark one. The colour and the fades are set per bar. */
.me-selection-bar {
  position: absolute;
  mix-blend-mode: multiply;
}

.me-selection-layer[data-blend="screen"] .me-selection-bar { mix-blend-mode: screen; }

/* The rule marking where the picture would land.

   Drawn across the whole column rather than as a caret between two characters,
   because that is the promise being made: a picture goes *between* two lines. A
   caret here invites the drop it looks like it is offering, which on macOS
   produced `Ome![photo](a.png)ga paragraph.` from a drag aimed at the gap
   above. */
.me-image-drop-line {
  position: absolute;
  z-index: 7;
  height: 3px;
  border-radius: 2px;
  background: var(--me-accent, #2f6fed);
  pointer-events: none;
}

/* WI-17: the size panel, anchored under the image it describes. */
.me-image-size {
  position: absolute;
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-radius: 8px;
  border: 1px solid var(--me-separator);
  background: var(--me-page-background);
  box-shadow: 0 4px 14px rgb(0 0 0 / 12%);
  font-size: 12px;
  color: var(--me-secondary-text);
  user-select: none;
}

/* `hidden` is only a UA-stylesheet `display: none`, which the rule above beats.
   Without this the empty panel sits over every document, permanently. */
.me-image-size[hidden],
.me-image-frame[hidden] {
  display: none;
}

.me-image-size__label {
  display: flex;
  align-items: center;
  gap: 4px;
}

.me-image-size__field {
  width: 58px;
  padding: 2px 4px;
  border-radius: 4px;
  border: 1px solid var(--me-separator);
  background: var(--me-page-background);
  color: var(--me-primary-text);
  font: inherit;
}

.me-image-size__reset {
  border: 0;
  border-radius: 4px;
  padding: 3px 7px;
  background: var(--me-inline-code-background);
  color: var(--me-primary-text);
  font: inherit;
  cursor: pointer;
}

.me-image-size__reset:hover { background: var(--me-separator); }

.me-image--broken {
  font-family: var(--me-mono-font);
  font-size: calc(var(--me-code-size) * var(--me-text-scale));
  color: var(--me-secondary-text);
  background: var(--me-inline-code-background);
  border-radius: 4px;
  padding: 1px 5px;
}

/* The label is generated content so the placeholder stays the only character
   an image contributes to the document text. */
.me-image--broken::before {
  content: "\1F5BC  " attr(data-label);
}

/* --------------------------------------------------- source pane typography */

/* E-18/E-19: every marker stays visible, but headings, body, and code take the
   same sizes the preview uses. */
.me-src-line { margin: 0; font-family: var(--me-mono-font); }
.me-src-h1 { font-size: var(--me-h1-size); font-weight: 700; line-height: 1.2; }
.me-src-h2 { font-size: var(--me-h2-size); font-weight: 700; line-height: 1.2; }
.me-src-h3 { font-size: var(--me-h3-size); font-weight: 700; line-height: 1.2; }
.me-src-h4 { font-size: var(--me-h4-size); font-weight: 700; line-height: 1.2; }
.me-src-h5 { font-size: var(--me-h5-size); font-weight: 700; line-height: 1.2; }
.me-src-h6 { font-size: var(--me-h6-size); font-weight: 700; line-height: 1.2; }
.me-src-code { font-size: var(--me-code-size); }

/* ----------------------------------------------------------------- statusbar */

.me-statusbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  height: 24px;
  padding: 0 12px;
  font-size: 11px;
  color: var(--me-secondary-text);
  background: var(--me-page-background);
  border-top: 1px solid color-mix(in srgb, var(--me-separator) 45%, transparent);
  user-select: none;
}

.me-statusbar__spacer { flex: 1; }

/* ------------------------------------------------------------------- welcome */

.me-welcome-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--me-canvas-background);
}

.me-welcome-backdrop[hidden] { display: none; }

/* W-26: 760 x 470, hidden title, full-size content. */
.me-welcome {
  display: flex;
  width: 760px;
  /* 600 rather than 560 because the identity block now draws a real icon.
     The old inline mark collapsed to 5px tall — measured — so the column had
     been getting the space for free. The side column still scrolls on a short
     screen; this is only about not making it scroll on a normal one. */
  height: 600px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 32px);
  overflow: hidden;
  border-radius: 12px;
  box-shadow: 0 22px 60px rgb(0 0 0 / 0.32);
  background: var(--me-page-background);
}

.me-welcome__side {
  display: flex;
  flex-direction: column;
  /* The storage picker made this column tall enough to clip on a short
     screen, and the panel's own overflow is hidden. */
  overflow-y: auto;
  flex: 0 0 300px;
  padding: 34px 28px;
  background: var(--me-sidebar-background);
}

/* The icon carries its own white plate now, and the plate is inset inside the
   box — so this is the canvas, and the mark a reader sees is about 70px of it.
   84 against a 25px name is the ratio the Mac's landing screen uses, and the
   two screens show the same icon at the same size as each other. */
.me-welcome__mark { width: 84px; height: 84px; }
.me-welcome__title { font-size: 25px; font-weight: 700; margin: 8px 0 22px; }

.me-welcome__actions { display: flex; flex-direction: column; gap: 8px; }

.me-button {
  font: inherit;
  font-size: 13px;
  color: inherit;
  padding: 8px 14px;
  border-radius: 7px;
  border: 1px solid var(--me-separator);
  background: var(--me-page-background);
  cursor: default;
  text-align: left;
}

.me-button:hover { border-color: var(--me-accent); }

.me-button--default {
  background: var(--me-selection-background);
  color: var(--me-selection-text);
  border-color: var(--me-selection-background);
  font-weight: 600;
}

.me-welcome__footer { margin-top: auto; padding-top: 16px; display: flex; flex-direction: column; gap: 10px; }

/* Storage picker (WR-1). Both options stay visible so where a document is
   saved is never something you have to click to discover. */
.me-welcome__storage { margin-top: 22px; }
.me-welcome__heading {
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--me-secondary-text); margin: 0 0 8px;
}
.me-storage { display: flex; flex-direction: column; gap: 8px; }
.me-storage__option {
  border: 1px solid var(--me-separator); border-radius: 8px; padding: 10px 12px;
  background: var(--me-page-background);
}
.me-storage__option--active { border-color: var(--me-accent); }
.me-storage__title { font-size: 13px; font-weight: 600; }
.me-storage__detail {
  margin: 3px 0 0; font-size: 12px; line-height: 1.45; color: var(--me-secondary-text);
}
.me-storage__badge {
  display: inline-block; vertical-align: 1px; font-size: 10px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase; padding: 1px 6px; border-radius: 999px;
  background: var(--me-separator); color: var(--me-secondary-text);
}
.me-storage__badge--active { background: var(--me-accent); color: #fff; }
.me-button--small { margin-top: 8px; padding: 3px 10px; font-size: 12px; }

/* Which storage is in use, permanently on screen (WR-5). */
.me-statusbar__storage { color: var(--me-secondary-text); }
.me-statusbar__storage[data-storage="cloud"] { color: var(--me-accent); }
.me-statusbar__storage::after {
  content: ""; display: inline-block; width: 1px; height: 10px; margin: 0 8px -1px;
  background: var(--me-separator);
}

.me-checkbox { display: flex; align-items: center; gap: 7px; color: var(--me-secondary-text); }
.me-checkbox input { accent-color: var(--me-accent); }

.me-welcome__main {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  padding: 28px 26px;
  overflow: auto;
}

/* The last section absorbs the leftover height so a short saved list does not
   float in the middle of the panel. */
.me-welcome__section { display: flex; flex-direction: column; min-height: 0; }
.me-welcome__section:last-child { flex: 1; }
.me-welcome__section + .me-welcome__section { margin-top: 22px; }

.me-welcome__heading {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 12px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--me-secondary-text);
}

.me-welcome__clear {
  margin-left: auto;
  font: inherit;
  text-transform: none;
  letter-spacing: 0;
  color: var(--me-accent);
  background: none;
  border: 0;
  cursor: default;
  padding: 0;
}

.me-welcome__clear:hover { text-decoration: underline; }
.me-welcome__recents { overflow: auto; margin: 0 -8px; }
.me-welcome__section:last-child .me-welcome__recents { flex: 1; }

.me-recent {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: default;
}

/* W-25: hover fills with the accent and switches the label to whichever of
   black or white has the better measured contrast — the same rule the macOS
   build applies, precomputed into --me-selection-text. */
.me-recent:hover { background: var(--me-selection-background); color: var(--me-selection-text); }
.me-recent:hover .me-recent__folder { color: var(--me-selection-text); opacity: 0.8; }

.me-recent__icon { flex: 0 0 17px; width: 17px; height: 17px; color: var(--me-accent); }
.me-recent:hover .me-recent__icon { color: var(--me-selection-text); }
/* Block children, not inline: two spans in a row ran the file name straight
   into its folder path. */
.me-recent__text { min-width: 0; flex: 1; display: flex; flex-direction: column; align-items: flex-start; }
.me-recent__name { max-width: 100%; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.me-recent__folder {
  max-width: 100%;
  font-size: 11px;
  color: var(--me-secondary-text);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  direction: rtl;      /* W-14: long paths truncate in the middle-ish, at the front */
  text-align: left;
}

.me-welcome__empty { color: var(--me-secondary-text); padding: 10px 8px; }

/* WB-11: the welcome panel is a fixed 760x470 two-column card, so on a phone
   the 300px side column squeezed the document list down to a sliver. Stack it
   instead. This is a viewport query, not a layout-mode one — the panel lives
   outside .me-app, and a narrow desktop window has the same problem. */
@media (max-width: 700px), (max-height: 560px) {
  .me-welcome {
    flex-direction: column;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    border-radius: 0;
  }

  .me-welcome__side {
    flex: 0 0 auto;
    padding: max(22px, env(safe-area-inset-top)) 20px 16px;
  }

  .me-welcome__mark { width: 64px; height: 64px; }
  .me-welcome__title { font-size: 22px; margin: 6px 0 16px; }
  /* Nothing left to push against once the column is content-height. */
  .me-welcome__footer { margin-top: 16px; }

  .me-welcome__main {
    padding: 18px 18px calc(18px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--me-separator);
  }

  .me-button { font-size: 15px; padding: 12px 14px; }
  .me-recent { min-height: 46px; }
  .me-recent__name { font-size: 15px; }
  .me-recent__folder { font-size: 12px; }
}

/* -------------------------------------------------------------------- popover */

.me-popover-layer, .me-alert-layer { position: fixed; inset: 0; pointer-events: none; z-index: 70; }
.me-popover-layer > *, .me-alert-layer > * { pointer-events: auto; }

.me-popover {
  position: absolute;
  min-width: 268px;
  padding: 14px;
  border-radius: 10px;
  background: var(--me-page-background);
  border: 1px solid var(--me-separator);
  box-shadow: 0 14px 40px rgb(0 0 0 / 0.3);
}

/* WT-19: Customize Theme is one width whatever it previews. Were it to fit its
   preview, a larger size or a wider face would widen it — and the size slider
   with it, moving the thumb out from under the pointer as it is dragged. The
   preview wraps instead; the popover grows downward only, below the slider. */
.me-popover--theme { width: 316px; max-width: calc(100vw - 16px); }

.me-popover__title { font-weight: 700; margin: 0 0 12px; }
.me-popover__label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--me-secondary-text); margin: 0 0 7px; }
.me-popover__section { margin-bottom: 14px; }

.me-swatches { display: grid; grid-template-columns: repeat(8, 1fr); gap: 7px; }

/* T-9: rounded squares with a 3px border, using the site's exact fill and
   border colors; the active one is scaled slightly and glows. */
.me-swatch {
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 6px;
  border: 3px solid var(--swatch-border);
  background: var(--swatch-fill);
  cursor: default;
  transition: transform 110ms ease, box-shadow 110ms ease;
}

.me-swatch[aria-pressed="true"] {
  transform: scale(1.14);
  box-shadow: 0 0 0 2px var(--me-page-background), 0 0 9px 2px var(--swatch-border);
}

.me-radio-row { display: flex; gap: 7px; }

.me-radio {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  justify-content: center;
  font: inherit;
  color: inherit;
  padding: 7px 10px;
  border-radius: 7px;
  border: 1px solid var(--me-separator);
  background: var(--me-page-background);
  cursor: default;
}

.me-radio[aria-pressed="true"] {
  background: var(--me-selection-background);
  color: var(--me-selection-text);
  border-color: var(--me-selection-background);
}

.me-radio svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.6; }

.me-preview {
  border-radius: 8px;
  border: 1px solid var(--me-separator);
  padding: 11px 13px;
  background: var(--preview-page);
  color: var(--preview-text);
}

.me-preview__title { font-family: var(--preview-font); font-weight: 700; font-size: calc(15px * var(--preview-scale, 1) * var(--preview-text-scale, 1)); overflow-wrap: anywhere; }
.me-preview__body { font-family: var(--preview-font); font-size: calc(12px * var(--preview-scale, 1) * var(--preview-text-scale, 1)); opacity: 0.85; margin-top: 3px; overflow-wrap: anywhere; }
.me-preview__accent { display: inline-block; margin-top: 8px; padding: 2px 8px; border-radius: 5px; background: var(--preview-accent); font-size: 11px; }

.me-font-select {
  width: 100%;
  font: inherit;
  font-size: 13px;
  color: inherit;
  padding: 6px 8px;
  border-radius: 7px;
  border: 1px solid var(--me-separator);
  background: var(--me-page-background);
}

/* T-23: the size slider, a small A and a large A either side of it. */
.me-size-header { display: flex; align-items: baseline; justify-content: space-between; }
.me-size-value {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--me-secondary-text);
}
.me-size-row { display: flex; align-items: center; gap: 8px; }
.me-size-slider { flex: 1; min-width: 0; margin: 0; accent-color: var(--me-accent); }
.me-size-glyph { color: var(--me-secondary-text); line-height: 1; }
.me-size-glyph--small { font-size: 10px; }
.me-size-glyph--large { font-size: 16px; }

.me-popover__buttons { display: flex; justify-content: flex-end; gap: 8px; }
.me-popover__buttons .me-button { text-align: center; }

/* --------------------------------------------------------------------- alerts */

.me-alert-layer { display: flex; align-items: center; justify-content: center; background: rgb(0 0 0 / 0.28); }
.me-alert-layer[hidden] { display: none; }

.me-alert {
  width: 400px;
  max-width: calc(100vw - 40px);
  padding: 20px;
  border-radius: 11px;
  background: var(--me-page-background);
  box-shadow: 0 22px 60px rgb(0 0 0 / 0.35);
}

.me-alert__title { font-size: 14px; font-weight: 700; margin: 0 0 7px; }
.me-alert__message { margin: 0 0 6px; }
.me-alert__recovery { color: var(--me-secondary-text); margin: 0 0 16px; }
.me-alert__field { width: 100%; font: inherit; padding: 7px 9px; margin-bottom: 16px; border-radius: 6px; border: 1px solid var(--me-separator); background: var(--me-page-background); color: inherit; }
.me-alert__field:focus { outline: 2px solid var(--me-accent); outline-offset: -1px; }
.me-alert__buttons { display: flex; justify-content: flex-end; gap: 8px; }
.me-alert__buttons .me-button { text-align: center; }

/* -------------------------------------------------------------- startup error */

.me-startup-error {
  max-width: 560px;
  margin: 16vh auto;
  padding: 26px 30px;
  font-family: var(--me-ui-font);
  border-radius: 11px;
  background: var(--me-page-background);
  border: 1px solid var(--me-separator);
}

.me-startup-error h1 { font-size: 18px; margin: 0 0 10px; }
.me-startup-error__recovery { color: var(--me-secondary-text); }

/* ------------------------------------------------------------ mobile layout */
/*
 * WB-*. The desktop chrome is replaced rather than shrunk: a menu bar of hover
 * targets and a 20-button single-row toolbar do not become usable by being
 * narrower. Everything below is scoped to [data-layout="mobile"], so the
 * desktop rules above are untouched.
 */

.me-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.me-mobile, .me-format { display: none; }
.me-mobile[hidden], .me-format[hidden] { display: none; }

.me-app[data-layout="mobile"] .me-menubar,
.me-app[data-layout="mobile"] .me-toolbar,
.me-app[data-layout="mobile"] .me-statusbar,
.me-app[data-layout="mobile"] .me-divider {
  display: none;
}

.me-app[data-layout="mobile"] .me-mobile:not([hidden]) { display: flex; }
.me-app[data-layout="mobile"] .me-format:not([hidden]) { display: block; }

/* 100dvh, not 100%: a mobile URL bar that hides and shows changes the viewport
   height, and a stale 100vh leaves the bottom of the app off-screen.

   The keyboard inset is subtracted so the app ends where the keyboard begins.
   Without it the app stays full height, the caret can land under the keyboard,
   and the browser scrolls the whole page up to reveal it — taking the docked
   header, and the formatting row with it, off the top of the screen. */
.me-app[data-layout="mobile"] {
  height: calc(100dvh - var(--me-keyboard-inset, 0px));
}

/* Set on <html> by mobile.js, not on `.me-app`, because a touch action is the
   intersection of an element's value and every ancestor's — it has to sit
   above the popover layer for sheets to be covered too.

   `pan-x pan-y` rather than `pan-y`: both keep pinch and double-tap zoom out,
   but `pan-y` would intersect with the formatting bar's `pan-x` to allow
   nothing at all, leaving the bar unscrollable. */
:root[data-me-layout="mobile"] {
  touch-action: pan-x pan-y;
  overscroll-behavior: none;
}

:root[data-me-layout="mobile"] body { overscroll-behavior: none; }

/* iOS zooms the whole page in when you focus text smaller than 16px, and it
   ignores `user-scalable=no` when deciding to. Once it has zoomed, the layout
   viewport is wider than the screen — so the page has to be slid sideways to
   see its edge — and a bar positioned against a layout viewport that no longer
   matches what is on screen lands somewhere other than where it was put. Both reported symptoms come from this one trigger, so every
   focusable control in the mobile layout is at least 16px. */
:root[data-me-layout="mobile"] { --me-body-size: 16px; }

:root[data-me-layout="mobile"] input,
:root[data-me-layout="mobile"] select,
:root[data-me-layout="mobile"] textarea {
  font-size: 16px;
}

/* Keeps a fling at the end of a pane from rubber-banding the page behind it. */
.me-app[data-layout="mobile"] .me-pane { overscroll-behavior: contain; }

.me-app[data-layout="mobile"] .me-body { position: relative; }

/* Touch targets need room; 15px source text on a phone does not. */
.me-app[data-layout="mobile"] .me-surface {
  padding: 16px 18px;
  padding-bottom: calc(28px + env(safe-area-inset-bottom));
}

.me-app[data-layout="mobile"] .me-pane { flex: 1; }
.me-app[data-layout="mobile"] .me-editor .me-pane--rich .me-surface {
  max-width: none;
  margin: 0;
}

/* --- top bar --- */

.me-mobile {
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
  /* The formatting row (WB-26) sits directly beneath and carries the separator,
     so the two rows sit tight and read as one header block. */
  padding: 6px 8px 2px;
  padding-top: max(6px, env(safe-area-inset-top));
  background: var(--me-sidebar-background);
  user-select: none;
}

.me-mobile__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  padding: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: 1px solid transparent;
  border-radius: 9px;
  cursor: default;
  -webkit-tap-highlight-color: transparent;
}

.me-mobile__button:active:not(:disabled) {
  background: color-mix(in srgb, var(--me-accent) 22%, transparent);
}

.me-mobile__button:disabled { opacity: 0.3; }

.me-mobile__button svg, .me-format__button svg, .me-sheet__item svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.me-mobile__button svg .me-fill,
.me-format__button svg .me-fill,
.me-sheet__item svg .me-fill { fill: currentColor; stroke: none; }

.me-mobile__title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: inherit;
  background: none;
  border: 0;
  padding: 0 4px;
  text-align: center;
  cursor: default;
}

/* The checkbox itself is the accessible control; the bookmark is its look. */
.me-mobile__save {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
}

.me-mobile__save input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
}

.me-mobile__save-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 9px;
  border: 1px solid transparent;
  pointer-events: none;
}

.me-mobile__save-box svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linejoin: round;
}

.me-mobile__save[data-checked="true"] .me-mobile__save-box {
  background: var(--me-selection-background);
  color: var(--me-selection-text);
  border-color: var(--me-selection-background);
}

.me-mobile__save[data-checked="true"] .me-mobile__save-box svg { fill: currentColor; }
.me-mobile__save input:disabled + .me-mobile__save-box { opacity: 0.3; }
.me-mobile__save input:focus-visible + .me-mobile__save-box {
  outline: 2px solid var(--me-accent);
  outline-offset: 1px;
}

/* --- docked formatting row --- */

/* The second row of the header. This was a floating palette above the keyboard,
   which cannot be made to work on a phone: iOS stacks its own furniture over the
   bottom of the screen — the keyboard's AutoFill and dismiss row, the home
   indicator — and a web page has no way to reserve space above it or even to
   measure it reliably. Docking the tools into the header puts them somewhere the
   platform never covers, and keeps them in one fixed place instead of moving
   with the keyboard. */
.me-format {
  flex: 0 0 auto;
  background: var(--me-sidebar-background);
  border-bottom: 1px solid var(--me-separator);
  user-select: none;
}

.me-format__scroller {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px 6px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* The row is the one place horizontal panning is wanted, and a fling along
     it must not turn into a page pan or a back-navigation. */
  touch-action: pan-x;
  overscroll-behavior-x: contain;
}

.me-format__scroller::-webkit-scrollbar { display: none; }

.me-format__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 40px;
  height: 38px;
  padding: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: 1px solid transparent;
  border-radius: 9px;
  cursor: default;
  -webkit-tap-highlight-color: transparent;
}

.me-format__button:active:not(:disabled) {
  background: color-mix(in srgb, var(--me-accent) 22%, transparent);
}

/* Off where the command could not work: inside a fenced block or a code span,
   where Markdown is literal and bold could only write two asterisks into
   somebody's code. Greyed rather than hidden, so the bar does not change shape
   as the caret moves. Matches `.me-tool:disabled` on the desktop toolbar. */
.me-format__button:disabled { opacity: 0.35; }

.me-format__button[aria-pressed="true"] {
  background: var(--me-selection-background);
  color: var(--me-selection-text);
  border-color: var(--me-selection-background);
}

.me-format__select {
  flex: 0 0 auto;
  height: 34px;
  font: inherit;
  font-size: 13px;
  color: inherit;
  background: var(--me-page-background);
  border: 1px solid var(--me-separator);
  border-radius: 8px;
  padding: 0 6px;
}

.me-format__divider {
  flex: 0 0 auto;
  width: 1px;
  height: 22px;
  margin: 0 4px;
  background: var(--me-separator);
}

/* The drawer covers the document, and the formatting row acts on the document,
   so it goes with it — leaving live-looking controls above a file list would be
   a lie. The drawer takes over the row's space immediately, so the top bar
   never moves and nothing jumps. */
.me-app[data-layout="mobile"][data-drawer="open"] .me-format { display: none; }

/* --- sidebar as a drawer --- */

.me-app[data-layout="mobile"] .me-sidebar {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 50;
  flex: 0 0 auto;
  width: min(84vw, 320px);
  border-right: 1px solid var(--me-separator);
  box-shadow: 0 0 30px rgb(0 0 0 / 0.3);
}

/* Desktop-sized explorer controls are unusable with a finger. */
.me-app[data-layout="mobile"] .me-sidebar__header { padding: 8px 8px 8px 12px; }
.me-app[data-layout="mobile"] .me-sidebar .me-tool { width: 38px; height: 38px; }
.me-app[data-layout="mobile"] .me-sidebar .me-tool svg { width: 18px; height: 18px; }
.me-app[data-layout="mobile"] .me-sidebar__path { font-size: 15px; padding: 6px 6px; }
.me-app[data-layout="mobile"] .me-tree__row { min-height: 42px; font-size: 15px; }

.me-drawer-scrim {
  position: absolute;
  inset: 0;
  z-index: 46;
  background: rgb(0 0 0 / 0.35);
}

.me-drawer-scrim[hidden] { display: none; }

/* --- overflow sheet --- */

.me-sheet-backdrop { position: fixed; inset: 0; background: rgb(0 0 0 / 0.35); }

.me-sheet {
  position: fixed;
  left: 8px;
  right: 8px;
  bottom: calc(8px + env(safe-area-inset-bottom));
  max-height: 70vh;
  overflow-y: auto;
  padding: 6px;
  border-radius: 14px;
  background: var(--me-page-background);
  border: 1px solid var(--me-separator);
  box-shadow: 0 10px 34px rgb(0 0 0 / 0.32);
}

.me-sheet__item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 46px;
  padding: 0 12px;
  font: inherit;
  font-size: 15px;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 10px;
  text-align: left;
  cursor: default;
}

.me-sheet__item:active:not(:disabled) {
  background: color-mix(in srgb, var(--me-accent) 20%, transparent);
}

.me-sheet__item:disabled { opacity: 0.35; }

.me-sheet__item[aria-current="true"] {
  color: var(--me-accent);
  font-weight: 600;
}

.me-sheet__gap { width: 18px; }
.me-sheet__separator { height: 1px; margin: 5px 12px; background: var(--me-separator); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* ---------------------------------------------------------------------------
   AI assisted critique (WA-*)

   A rail of comments down the right-hand side, mirroring the macOS build's.
   Modelled on the one place this interaction is already familiar: a comment
   thread beside a document. A card per finding, the open one raised and
   tinted, the passage it describes shaded in the text, and a click on either
   side moving the other.
   --------------------------------------------------------------------------- */


:root {
  --me-critique-hand: var(--me-ui-font);
  --me-critique-hand-scale: 1;

  /* The colours the critique writes in. Its own rather than the theme's: the
     theme's text colours are chosen against the theme's page, and almost
     nothing here is on the page. The notes are on pale paper in a light theme
     and deep paper in a dark one. */
  --me-note-ink: #1f1c1c;
  --me-note-quiet: #57524f;

  --me-note-high-paper: #ffd9d7;
  --me-note-medium-paper: #fff5c2;
  --me-note-low-paper: #d9edff;

  /* The same hue carried to a legible lightness. `tint` is a fill, chosen to
     look right as a solid block; set as text on a wash of itself it is barely
     there, so the words get this one instead. */
  --me-note-high-ink: #9e1a1a;
  --me-note-medium-ink: #854505;
  --me-note-low-ink: #21529a;

  --me-note-high-tint: #d93d3d;
  --me-note-medium-tint: #e69919;
  --me-note-low-tint: #5c8ccc;

  --me-note-works: #217f4a;
}

[data-appearance="dark"] {
  --me-note-ink: #f2f2f0;
  --me-note-quiet: #c7c5c2;

  --me-note-high-paper: #4d2628;
  --me-note-medium-paper: #47391a;
  --me-note-low-paper: #23354f;

  --me-note-high-ink: #ff9995;
  --me-note-medium-ink: #ffc24d;
  --me-note-low-ink: #9ed1ff;

  --me-note-works: #6bd18f;
}

/* Docked against the document, not floating beside it.

   A gutter here would leave the rail unattached to anything: the notes are
   *about* the text they sit next to, and a gap plus a rule read as a divider
   between two panes rather than as a margin on one document. The cards have
   their own inset, so they still do not touch the edge.

   A fixed width, so the rail does not eat whatever the window has spare --
   a comment column that grows with the window stops looking like margin
   notes somewhere around the second screenful. */
.me-critique {
  flex: 0 0 340px;
  width: 340px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-left: 1px solid var(--me-separator);
  background: var(--me-canvas-background);
  font-family: var(--me-ui-font);
  color: var(--me-primary-text);
}

.me-critique[hidden] { display: none; }

.me-critique__header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--me-separator);
}

.me-critique__mark { display: flex; color: var(--me-accent); }
.me-critique__mark svg { width: 16px; height: 16px; }

/* Small and bold, rather than large and regular. A heading earns its place by
   weight and by the space around it; making it big *as well* means the
   signpost competes with the thing it is pointing at. */
.me-critique__title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.5px;
}

.me-critique__spacer { flex: 1; }

.me-critique__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 5px;
  background: none;
  color: var(--me-note-quiet);
  cursor: pointer;
}

.me-critique__icon svg { width: 15px; height: 15px; }
.me-critique__icon:hover { background: color-mix(in srgb, var(--me-primary-text) 10%, transparent); }

.me-critique__text-button {
  border: 0;
  background: none;
  font: inherit;
  font-size: 13px;
  color: var(--me-note-quiet);
  cursor: pointer;
}

.me-critique__hand-menu { display: flex; align-items: center; gap: 3px; color: var(--me-note-quiet); }
.me-critique__hand-glyph { display: flex; }
.me-critique__hand-glyph svg { width: 14px; height: 14px; }

.me-critique__hand-select {
  max-width: 96px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--me-note-quiet);
  cursor: pointer;
}

.me-critique__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 0 32px;
}

/* --- The states the rail can be in ---------------------------------------- */

.me-critique__state {
  padding: 18px 16px;
  text-align: left;
}

.me-critique__state-note {
  margin: 0 0 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--me-primary-text);
}

.me-critique__state-detail {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--me-secondary-text);
}

.me-critique__state--failed .me-critique__state-note { color: var(--me-note-high-ink); }

.me-critique__button {
  padding: 5px 12px;
  border: 1px solid var(--me-separator);
  border-radius: 6px;
  background: var(--me-page-background);
  font: inherit;
  font-size: 13px;
  color: var(--me-primary-text);
  cursor: pointer;
}

.me-critique__button:hover { border-color: var(--me-accent); color: var(--me-accent); }

.me-critique__spinner {
  width: 18px;
  height: 18px;
  margin-bottom: 10px;
  border: 2px solid var(--me-separator);
  border-top-color: var(--me-accent);
  border-radius: 50%;
  animation: me-critique-spin 0.8s linear infinite;
}

@keyframes me-critique-spin { to { transform: rotate(360deg); } }

/* --- The score ------------------------------------------------------------ */

.me-critique__score {
  margin: 0 12px 14px;
  padding: 12px 14px;
  border: 1px solid var(--me-score-tint);
  background:
    linear-gradient(color-mix(in srgb, var(--me-score-tint) 12%, transparent),
                    color-mix(in srgb, var(--me-score-tint) 12%, transparent)),
    var(--me-page-background);
  box-shadow: 2px 2px 0 var(--me-separator);
}

.me-critique__score--low { --me-score-tint: var(--me-note-low-tint); --me-score-ink: var(--me-note-low-ink); }
.me-critique__score--medium { --me-score-tint: var(--me-note-medium-tint); --me-score-ink: var(--me-note-medium-ink); }
.me-critique__score--high { --me-score-tint: var(--me-note-high-tint); --me-score-ink: var(--me-note-high-ink); }

.me-critique__score-top {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.me-critique__score-number {
  font-size: 42px;
  font-weight: 700;
  line-height: 1;
  color: var(--me-score-ink);
  font-variant-numeric: tabular-nums;
}

.me-critique__score-outof { font-size: 16px; font-weight: 600; color: var(--me-score-ink); }

.me-critique__score-verdict {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
}

.me-critique__score-caption {
  font-size: 11px;
  letter-spacing: 0.6px;
  color: var(--me-note-quiet);
}

.me-critique__score-word { font-size: 13px; color: var(--me-primary-text); }

/* Stepped, not smooth: the bar reads in whole blocks, the way a health meter
   does, rather than as a continuous measurement it cannot honestly claim to
   be. */
.me-critique__bar {
  display: flex;
  gap: 2px;
  height: 7px;
  margin-top: 9px;
}

.me-critique__bar-block { flex: 1; background: color-mix(in srgb, var(--me-secondary-text) 16%, transparent); }
.me-critique__bar-block.is-filled { background: var(--me-score-tint); }

.me-critique__score-answered {
  margin: 8px 0 0;
  font-size: 11px;
  color: var(--me-note-quiet);
}

.me-critique__score-again { margin-top: 9px; }

/* --- The stale notice ----------------------------------------------------- */

.me-critique__stale {
  margin: 0 12px 14px;
  padding: 10px;
  border: 1px solid var(--me-separator);
  background: color-mix(in srgb, var(--me-note-quiet) 10%, transparent);
}

.me-critique__stale-text {
  margin: 0 0 9px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--me-note-quiet);
}

/* --- A note on the pad ---------------------------------------------------- */

/* The tilt and the nudge are what make a stack of these read as paper rather
   than as a list of rows. Stable per note, so answering one does not reshuffle
   the pad. */
.me-critique__note {
  position: relative;
  margin: 0 12px 16px;
  margin-left: calc(12px + var(--me-note-nudge, 0px));
  padding: 14px 12px 10px;
  background: var(--me-note-paper, var(--me-page-background));
  box-shadow: 2px 2px 0 var(--me-separator);
  transform: rotate(var(--me-note-angle, 0deg));
  cursor: default;
  transition: transform 0.14s ease-out, box-shadow 0.14s ease-out;
}

.me-critique__note--high { --me-note-paper: var(--me-note-high-paper); --me-note-tint: var(--me-note-high-tint); --me-note-severity-ink: var(--me-note-high-ink); }
.me-critique__note--medium { --me-note-paper: var(--me-note-medium-paper); --me-note-tint: var(--me-note-medium-tint); --me-note-severity-ink: var(--me-note-medium-ink); }
.me-critique__note--low { --me-note-paper: var(--me-note-low-paper); --me-note-tint: var(--me-note-low-tint); --me-note-severity-ink: var(--me-note-low-ink); }

/* Straightened and faded once it has been dealt with, which reads as "this one
   has been handled" without needing a word for it. */
.me-critique__note.is-answered {
  --me-note-paper: var(--me-page-background);
  opacity: 0.62;
}

.me-critique__note.is-selected {
  box-shadow: 0 0 0 2px var(--me-note-tint, var(--me-accent)), 3px 3px 0 var(--me-separator);
  transform: rotate(0deg) translateX(-2px);
}

/* The summary is the only white note, because it is not a finding -- it is the
   reader's impression of the whole draft. Colour on this one would file it
   alongside the problems, which is exactly what it is not. */
.me-critique__note--summary { --me-note-paper: var(--me-page-background); }

.me-critique__note-body { display: flex; flex-direction: column; gap: 6px; }

/* Sits over the note's top edge, the way a tag does. */
.me-critique__tag {
  position: absolute;
  top: -9px;
  left: 10px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  color: #ffffff;
  /* The deep member of the hue, not the bright one: white on bright amber
     measures 2.35:1, which is a colour with a word hidden in it. */
  background: var(--me-note-severity-ink);
  box-shadow: 2px 2px 0 var(--me-separator);
}

.me-critique__tag--answered {
  color: var(--me-note-ink);
  background: color-mix(in srgb, var(--me-note-quiet) 22%, transparent);
}

.me-critique__note-head { display: flex; align-items: flex-start; gap: 6px; }

/* Larger than the body it introduces, and in the reviewer's hand rather than
   the app's: it is part of what they wrote on the note, not a label the app
   has stuck on top of it. Inside a card there is no surrounding space to give
   a heading weight, so it has to come from size. */
.me-critique__note-category {
  margin: 0;
  flex: 1;
  font-family: var(--me-critique-hand);
  font-size: calc(17px * var(--me-critique-hand-scale));
  font-weight: 400;
  line-height: 1.25;
  color: var(--me-note-ink);
}

.me-critique__flag {
  padding: 1px 5px;
  font-size: 11px;
  color: var(--me-note-quiet);
  background: color-mix(in srgb, var(--me-note-quiet) 18%, transparent);
}

/* The author's own sentence quoted back at them, so it has to be recognisable
   as theirs. Deliberately not the hand. */
.me-critique__quote {
  margin: 0;
  padding-left: 7px;
  border-left: 2px solid color-mix(in srgb, var(--me-note-tint) 55%, transparent);
  font-size: 12px;
  line-height: 1.45;
  color: var(--me-note-quiet);
}

/* The criticism itself. The smallest of the three, because it is the only one
   there is a lot of. */
.me-critique__why {
  margin: 0;
  font-family: var(--me-critique-hand);
  font-size: calc(13px * var(--me-critique-hand-scale));
  line-height: 1.45;
  color: var(--me-note-ink);
}

.me-critique__advice { display: flex; flex-direction: column; gap: 2px; padding-top: 2px; }

/* A sub-heading within the note, so between the two. */
.me-critique__advice-label {
  font-family: var(--me-critique-hand);
  font-size: calc(15px * var(--me-critique-hand-scale));
  letter-spacing: 0.4px;
  color: var(--me-note-quiet);
}

.me-critique__advice-text {
  margin: 0;
  font-family: var(--me-critique-hand);
  font-size: calc(13px * var(--me-critique-hand-scale));
  line-height: 1.45;
  color: var(--me-note-ink);
}

.me-critique__note-foot {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-top: 3px;
}

.me-critique__location { font-size: 11px; color: var(--me-note-quiet); }

/* Deep enough to carry white, on any of the four papers. A tinted glyph on
   tinted paper is the version that does not work: a green tick on a pale
   yellow note is two washes of the same lightness. */
.me-critique__stamp { width: 20px; height: 20px; color: #ffffff; border-radius: 0; }
.me-critique__stamp svg { width: 12px; height: 12px; }
.me-critique__stamp--done { background: #17752f; }
.me-critique__stamp--dismiss { background: #cc2621; }
.me-critique__stamp:hover { filter: brightness(1.15); background: var(--me-stamp-hover, inherit); }
.me-critique__stamp--done:hover { background: #17752f; }
.me-critique__stamp--dismiss:hover { background: #cc2621; }

/* --- The summary note ----------------------------------------------------- */

/* Entirely in the app's own face rather than the hand: it is a summary *of*
   the handwritten notes rather than one of them. */
.me-critique__job {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--me-note-quiet);
}

/* The overall read, when the critic lists nothing holding the draft back. Ink
   rather than the quiet grey of the job read above it: it is the verdict. */
.me-critique__overall {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--me-note-ink);
}

.me-critique__summary-section { display: flex; flex-direction: column; gap: 3px; }

.me-critique__section-title {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: var(--me-primary-text);
}

.me-critique__summary-section--works .me-critique__section-title { color: var(--me-note-works); }
.me-critique__summary-section--problems .me-critique__section-title { color: var(--me-note-high-ink); }

.me-critique__summary-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; }

.me-critique__summary-list li {
  display: flex;
  gap: 6px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--me-note-ink);
}

.me-critique__summary-mark { flex: 0 0 auto; color: var(--me-note-quiet); }
.me-critique__summary-section--works .me-critique__summary-mark { color: var(--me-note-works); }
.me-critique__summary-section--problems .me-critique__summary-mark { color: var(--me-note-high-ink); }

.me-critique__counts { display: flex; flex-wrap: wrap; gap: 10px; padding-top: 1px; }

.me-critique__count { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--me-note-quiet); }
.me-critique__count-swatch { width: 6px; height: 6px; }
.me-critique__count--high .me-critique__count-swatch { background: var(--me-note-high-tint); }
.me-critique__count--medium .me-critique__count-swatch { background: var(--me-note-medium-tint); }
.me-critique__count--low .me-critique__count-swatch { background: var(--me-note-low-tint); }

.me-critique__answered-heading {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 12px 6px;
}

.me-critique__rule { flex: 1; height: 1px; background: color-mix(in srgb, var(--me-separator) 70%, transparent); }

/* --- The shading in the document ------------------------------------------ */

/* Painted with the Custom Highlight API rather than by wrapping the passage in
   an element. The surfaces are contenteditable, and inserting a <mark> into
   one moves every offset after it, corrupts the mapping the editor reads
   selections through, and lands in the undo stack as though the author had
   typed it. A highlight paints over the text without touching the tree.

   Where the API is missing the cards still work and say so; nothing silently
   half-happens. */
::highlight(me-critique-high) { background-color: rgba(217, 61, 61, 0.26); }
::highlight(me-critique-medium) { background-color: rgba(230, 153, 25, 0.30); }
::highlight(me-critique-low) { background-color: rgba(92, 140, 204, 0.26); }
::highlight(me-critique-selected-high) { background-color: rgba(217, 61, 61, 0.48); }
::highlight(me-critique-selected-medium) { background-color: rgba(230, 153, 25, 0.55); }
::highlight(me-critique-selected-low) { background-color: rgba(92, 140, 204, 0.48); }

/* The rail is a desktop affordance. On the mobile layout there is no room
   beside the document for a column of comments, so it becomes the whole view
   when it is open rather than a sliver of one. */
.me-app[data-layout="mobile"] .me-critique {
  position: absolute;
  inset: 0;
  z-index: 6;
  width: auto;
  flex: 1;
  border-left: 0;
}

/* The critique's settings panel: provider, model, and the reader's own key.
   Wider than an alert because it is a form rather than a sentence. */
.me-alert--settings { max-width: 460px; text-align: left; }

.me-settings__row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 8px 0;
}

.me-settings__label {
  flex: 0 0 78px;
  font-size: 13px;
  color: var(--me-secondary-text);
}

.me-settings__control {
  flex: 1;
  min-width: 0;
  padding: 5px 8px;
  border: 1px solid var(--me-separator);
  border-radius: 6px;
  background: var(--me-page-background);
  font: inherit;
  font-size: 13px;
  color: var(--me-primary-text);
}

.me-settings__status {
  margin: 6px 0 0;
  font-size: 12px;
  color: var(--me-secondary-text);
}

/* Green for a key that is there, red for one that is not. Not colour alone —
   the sentence says which either way, so this only speeds up a glance. */
.me-settings__status[data-state="ok"] { color: var(--me-note-works); }
.me-settings__status[data-state="missing"] { color: var(--me-note-high-ink); }
