/* ==========================================================================
   JandePad — style.css
   Main layout, typography, dark theme (default and only theme for v1).
   ========================================================================== */

/* Colours (backgrounds, text, accent, syntax) live in themes.css and switch via
   <html data-scheme data-mode>. Only non-colour tokens are defined here. */
:root {
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: "Noto Sans Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; /* overridden by the Editor font setting */

  --topbar-h: 46px;
  --tabbar-h: 38px;
  --toolbar-h: 40px;
  --statusbar-h: 26px;
  --radius: 6px;
  /* Set by app.js only while the visual viewport is smaller than the layout
     viewport (on-screen keyboard that doesn't resize the layout, pinch zoom). */
  --viewport-inset-bottom: 0px;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden; /* prevent mobile body-scroll bounce */
  background: var(--bg-0);
  color: var(--text-0);
  font-family: var(--font-ui);
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}

/* The app is pinned to all four edges of the layout viewport instead of being
   given a computed height. position:fixed + inset:0 always tracks whatever the
   browser considers the visible area (address bar shown/hidden, keyboard that
   resizes the layout), so there is no JS-measured height that can go stale.
   app.js only adds --viewport-inset-bottom when the *visual* viewport is
   smaller than the layout viewport (keyboard that overlays instead of resizes). */
.app {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: var(--viewport-inset-bottom, 0px);
  display: flex;
  flex-direction: column;
  background: var(--bg-0);
}

button {
  font-family: inherit;
}

/* ---------- Buttons ---------- */
.btn {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-1);
  border-radius: var(--radius);
  cursor: pointer;
  padding: 6px 9px;
  font-size: 13px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}
.btn:hover { background: var(--bg-3); color: var(--text-0); }
.btn:active { background: var(--bg-2); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.btn.btn-primary { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.btn.btn-primary:hover { background: var(--accent-hover); }

.icon-btn { padding: 7px; }
.icon { width: 17px; height: 17px; display: block; }

/* ---------- 1. Top Bar ---------- */
.topbar {
  height: var(--topbar-h);
  min-height: var(--topbar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 8px 0 12px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--border-soft);
  -webkit-user-select: none;
  user-select: none;
}
.topbar-left { display: flex; align-items: center; gap: 8px; min-width: 0; }
.app-mark { width: 22px; height: 22px; flex-shrink: 0; color: var(--text-0); }
.settings-version { margin: 4px 0 10px; text-align: right; }
.app-title { font-weight: 600; font-size: 14px; letter-spacing: .2px; color: var(--text-0); }
.topbar-actions { display: flex; align-items: center; gap: 2px; }
/* The overflow "more" button is always present: on narrow viewports (.compact)
   it holds the actions that don't fit; on wide ones it holds Focus mode. */
.menu-toggle { display: inline-flex; }

/* ---------- 2. Tab Bar ---------- */
.tabbar {
  height: var(--tabbar-h);
  min-height: var(--tabbar-h);
  display: flex;
  align-items: stretch;
  background: var(--bg-0);
  border-bottom: 1px solid var(--border-soft);
}
.tabbar-scroll {
  flex: 1;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.tabbar-scroll::-webkit-scrollbar { height: 4px; }
.tabbar-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

.tab {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 8px 0 12px;
  min-width: 96px;
  max-width: 200px;
  height: 100%;
  border-right: 1px solid var(--border-soft);
  color: var(--text-2);
  cursor: pointer;
  flex-shrink: 0;
  position: relative;
  -webkit-user-select: none;
  user-select: none;
}
.tab:hover { background: var(--bg-1); color: var(--text-1); }
.tab.active {
  background: var(--bg-2);
  color: var(--text-0);
}
.tab.active::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--accent);
}
.tab-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
  flex: 1;
  min-width: 0;
}
.tab-dirty-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--warn);
  flex-shrink: 0;
  display: none;
}
.tab.dirty .tab-dirty-dot { display: block; }
.tab-adapter-icon { flex-shrink: 0; opacity: .6; width: 12px; height: 12px; }
.tab-close {
  flex-shrink: 0;
  width: 18px; height: 18px;
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-2);
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
}
.tab-close:hover { background: var(--bg-3); color: var(--text-0); }
.tab-add {
  flex-shrink: 0;
  width: 34px;
  height: 100%;
  border-radius: 0;
  /* Sits right after the last tab; once the tabs overflow, it sticks to the right edge. */
  position: sticky;
  right: 0;
  background: var(--bg-0);
}

/* ---------- 3. Toolbar ---------- */
.toolbar {
  height: var(--toolbar-h);
  min-height: var(--toolbar-h);
  background: var(--bg-1);
  border-bottom: 1px solid var(--border-soft);
  display: flex;
  align-items: center;
}
.toolbar-scroll {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 0 6px;
  overflow-x: auto;
  overflow-y: hidden;
  width: 100%;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.toolbar-scroll::-webkit-scrollbar { display: none; }
/* Edge fade shows when buttons are scrolled off-screen (class toggled by app.js). */
.toolbar { position: relative; }
.toolbar.fade-end::after,
.toolbar.fade-start::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 22px;
  pointer-events: none;
  z-index: 2;
}
.toolbar.fade-end::after { right: 0; background: linear-gradient(to right, transparent, var(--bg-1)); }
.toolbar.fade-start::before { left: 0; background: linear-gradient(to left, transparent, var(--bg-1)); }
.tool-btn {
  flex-shrink: 0;
  min-width: 34px;
  min-height: 36px;
  padding: 6px 3px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 600;
}
.tool-btn[hidden] { display: none; }
.tool-btn .icon { width: 18px; height: 18px; }
/* Group gap in place of the old 1px separator lines: same grouping, ~5px cheaper each. */
.toolbar-sep { width: 4px; flex-shrink: 0; height: 1px; }
/* Formatting area (brackets popup + Markdown/HTML buttons), appended after the standard tools.
   display:contents makes the wrapper vanish from layout. */
.toolbar-fmt-group { display: contents; }
.tool-btn.fmt-b { font-weight: 800; }
.tool-btn.fmt-i { font-style: italic; }
.tool-btn.fmt-s { text-decoration: line-through; }
.fmt-popover { min-width: 0; }
.fmt-popover .popover-grid-inner { display: grid; grid-template-columns: repeat(4, minmax(44px, 1fr)); gap: 4px; padding: 6px; }
.fmt-popover .popover-list-inner { display: flex; flex-direction: column; padding: 4px; min-width: 190px; }
.fmt-popover .popover-item { font-family: var(--font-mono); }
/* Invisible characters (Show invisibles): CSS only, never part of the text */
.cm-inv-space { background-image: radial-gradient(circle, var(--text-2, #888) 0 1.1px, transparent 1.4px); background-repeat: no-repeat; background-position: center; opacity: 1; }
.cm-inv-nbsp { background-image: radial-gradient(circle, var(--danger, #e5534b) 0 1.4px, transparent 1.7px); background-repeat: no-repeat; background-position: center; }
.cm-inv-tab { position: relative; }
.cm-inv-tab::before { content: '\2192'; position: absolute; left: 1px; color: var(--text-2, #888); pointer-events: none; }
.cm-inv-eol::after { content: '\00b6'; color: var(--text-2, #888); opacity: .7; pointer-events: none; padding-left: 2px; }
.cm-inv-eof::after { content: '\2205'; }

/* ---------- 4. Main Editor Area ---------- */
.editor-area {
  flex: 1;
  min-height: 0;
  position: relative;
  background: var(--bg-2);
}
/* The editor container is now just a mount point for CodeMirror 6 — CM
   owns its own internal box model (font, line-height, padding, caret,
   selection, tab size, wrap, syntax colors) via the theme + HighlightStyle
   defined in editor.js, so this only needs to size and position it. */
.editor {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  overscroll-behavior: contain;
}
.editor .cm-editor { height: 100%; }
.editor.is-disabled { opacity: .6; }

/* ---------- Status Bar ---------- */
.statusbar {
  height: var(--statusbar-h);
  min-height: var(--statusbar-h);
  flex-shrink: 0;
  background: var(--bg-1);
  border-top: 1px solid var(--border-soft);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 12px;
  font-size: 11px;
  color: var(--text-2);
  -webkit-user-select: none;
  user-select: none;
  position: relative;
}
.status-item[hidden] { display: none; }
.status-spacer { flex: 1; }
/* Position and count are buttons (go to line / text statistics). The compact
   variants (.sp-short / .sc-short) replace the long labels on narrow screens. */
.status-btn {
  background: transparent;
  border: none;
  color: inherit;
  font: inherit;
  padding: 0 4px;
  margin: 0 -4px;
  align-self: stretch;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  border-radius: 4px;
}
.status-btn:hover { color: var(--text-0); background: var(--bg-3); }
.status-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.status-btn.is-selection { color: var(--accent); }
.sp-short, .sc-short { display: none; }
#status-connection { color: var(--good); font-size: 9px; cursor: pointer; padding: 6px 4px; }
#status-connection.offline { color: var(--text-2); }
#status-connection.error { color: var(--danger); }
/* Storage label: a plain word for saved files, a warning colour when the tab
   only exists as a browser draft. Tappable — explains itself in a toast. */
#status-adapter { cursor: pointer; padding: 6px 2px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#status-adapter.is-draft { color: var(--warn); }
.status-icon-btn {
  background: transparent;
  border: none;
  color: var(--text-1);
  min-width: 32px;
  height: 100%;
  padding: 0 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border-radius: 0;
}
.status-icon-btn:hover { background: var(--bg-3); color: var(--text-0); }
.status-icon-btn .icon { width: 14px; height: 14px; }
.status-icon-btn[hidden] { display: none; }
#status-hint { color: var(--accent); font-weight: 600; transition: opacity .25s ease; }
#status-hint.fade { opacity: 0; }
#status-dirty { color: var(--warn); display: none; }
.app.focus-mode #status-dirty:not([hidden]) { display: inline; }

/* Transient message above the status bar (dot / storage label taps, search notices). */
.toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(var(--statusbar-h) + var(--safe-bottom) + 10px + var(--viewport-inset-bottom, 0px));
  max-width: min(92vw, 420px);
  background: var(--bg-3);
  color: var(--text-0);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 12.5px;
  line-height: 1.4;
  box-shadow: 0 8px 24px var(--shadow);
  z-index: 60;
  pointer-events: none;
}
.toast[hidden] { display: none; }


/* ---------- Find / replace bar ---------- */
.findbar {
  background: var(--bg-1);
  border-bottom: 1px solid var(--border-soft);
  padding: 4px 6px 4px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex-shrink: 0;
}
.findbar[hidden] { display: none; }

.change-banner {
  background: var(--warn-bg, var(--bg-1));
  border-bottom: 1px solid var(--warn-border, var(--border-soft));
  color: var(--warn, var(--text-0));
  padding: 8px 10px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
  flex-shrink: 0;
  font-size: 12.5px;
}
.change-banner[hidden] { display: none; }
.change-banner-text { flex: 1; min-width: 160px; line-height: 1.4; }
.change-banner-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.change-banner-actions .btn { font-size: 12px; min-height: 30px; padding: 4px 10px; }
.find-row { display: flex; align-items: center; gap: 4px; }
.find-row[hidden] { display: none; }
.find-input {
  flex: 1;
  min-width: 0;
  background: var(--bg-0);
  border: 1px solid var(--border);
  color: var(--text-0);
  border-radius: var(--radius);
  padding: 0 8px;
  height: 34px;
  font: 14px var(--font-mono);
}
.find-input:focus { outline: 2px solid var(--accent); border-color: var(--accent); }
.find-input.invalid { border-color: var(--danger); outline-color: var(--danger); }
.find-count { font-size: 11px; color: var(--text-2); min-width: 54px; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.find-btn { min-width: 34px; min-height: 34px; padding: 4px 6px; }
.find-btn .icon { width: 16px; height: 16px; }
.find-toggle {
  min-height: 30px;
  min-width: 34px;
  padding: 3px 8px;
  font: 600 12px var(--font-mono);
  border: 1px solid var(--border);
  color: var(--text-1);
}
.find-toggle[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.find-toggle.wide { font-family: var(--font-ui); font-weight: 500; }
.find-spacer { flex: 1; }
.find-toggle { white-space: nowrap; }
.find-toggle[hidden] { display: none; }
.find-toggle:disabled { opacity: .45; cursor: default; }
.find-select {
  min-height: 30px;
  min-width: 0;
  max-width: 92px;
  background: var(--bg-2);
  color: var(--text-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0 4px;
  font: 500 12px var(--font-ui);
}
.find-check { display: inline-flex; align-items: center; gap: 4px; font: 500 12px var(--font-ui); color: var(--text-1); white-space: nowrap; cursor: pointer; }
.find-check input { margin: 0; }
.extract-count { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.find-error { margin: 0; font-size: 11.5px; color: var(--danger); padding: 0 4px; }
.find-error[hidden] { display: none; }
.find-results {
  max-height: clamp(84px, calc(var(--app-h, 100dvh) * .26), 240px);
  overflow-y: auto;
  border-top: 1px solid var(--border-soft);
  margin-top: 2px;
  font-size: 12px;
}
.find-results[hidden] { display: none; }
.find-group-head {
  position: sticky;
  top: 0;
  background: var(--bg-1);
  color: var(--text-1);
  font-weight: 600;
  padding: 5px 6px 3px;
  display: flex;
  justify-content: space-between;
  gap: 8px;
}
.find-group-head .count { color: var(--text-2); font-weight: 400; }
.find-hit {
  display: flex;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--text-1);
  padding: 4px 6px;
  min-height: 28px;
  font: 12px var(--font-mono);
  cursor: pointer;
  align-items: baseline;
  border-radius: 4px;
}
.find-hit:hover, .find-hit.current { background: var(--bg-3); color: var(--text-0); }
.find-hit .ln { color: var(--text-2); min-width: 32px; text-align: right; flex-shrink: 0; }
.find-hit .snippet { white-space: pre; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.find-hit mark { background: var(--find-bg); color: inherit; border-radius: 2px; }
.find-more { color: var(--text-2); padding: 4px 8px 8px; font-size: 11.5px; }

/* ---------- Focus mode ---------- */
.app.focus-mode .topbar,
.app.focus-mode .tabbar,
.app.focus-mode .toolbar { display: none; }
.focus-handle {
  position: fixed;
  top: calc(var(--safe-top) + 2px);
  left: 50%;
  transform: translateX(-50%);
  width: 64px;
  height: 22px;
  border-radius: 0 0 12px 12px;
  background: var(--bg-3);
  border: 1px solid var(--border);
  border-top: none;
  color: var(--text-1);
  opacity: .55;
  z-index: 40;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
}
.focus-handle::before { content: ""; width: 26px; height: 3px; border-radius: 2px; background: currentColor; }
.app.focus-mode .focus-handle { display: flex; }
.focus-strip {
  position: fixed;
  top: var(--safe-top);
  left: 0;
  right: 0;
  z-index: 41;
  display: none;
  align-items: center;
  gap: 2px;
  padding: 4px 6px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 8px 24px var(--shadow);
}
.focus-strip.visible { display: flex; }
.focus-strip .focus-title { flex: 1; min-width: 0; font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 6px; }
.focus-strip .btn { min-width: 40px; min-height: 36px; }
.focus-strip .btn[hidden] { display: none; }

/* ---------- Dialogs ---------- */
dialog {
  background: var(--bg-1);
  color: var(--text-0);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 18px 20px 16px;
  max-width: min(92vw, 420px);
  width: 100%;
  box-shadow: 0 20px 60px var(--shadow);
}
dialog::backdrop { background: var(--backdrop); }
dialog h2 { margin: 0 0 14px; font-size: 15px; font-weight: 600; }
dialog label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-1);
  margin-bottom: 12px;
}
/* `dialog label { display: flex }` above is an author rule, so it silently
   overrides the browser's built-in `[hidden] { display: none }` default —
   the hidden attribute is UA-origin and always loses to any author rule
   touching the same property, regardless of specificity. Every dialog in
   the app toggles rows via .hidden, so without this override a "hidden"
   label field stays visibly laid out (this was the SFTP password/key
   field-swap bug). */
dialog label[hidden] {
  display: none;
}
dialog input[type="text"], dialog select {
  background: var(--bg-0);
  border: 1px solid var(--border);
  color: var(--text-0);
  border-radius: var(--radius);
  padding: 8px 10px;
  font-size: 14px;
  font-family: var(--font-mono);
}
dialog input[type="text"]:focus, dialog select:focus { outline: 2px solid var(--accent); border-color: var(--accent); }
.dlg-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
/* Themed confirm/prompt dialog (askDialog) */
.dlg-confirm { max-width: min(92vw, 380px); }
.dlg-confirm .dlg-hint { margin: 0 0 14px; white-space: pre-line; color: var(--text-1); font-size: 13px; line-height: 1.45; }
.dlg-confirm .dlg-hint[hidden] { display: none; }
.dlg-confirm .btn[hidden] { display: none; }
.dlg-confirm .btn.is-danger { background: var(--danger); border-color: var(--danger); color: var(--on-accent); }
.settings-row { flex-direction: row !important; align-items: center; justify-content: space-between; }
.settings-row input[type="range"] { flex: 1; margin: 0 10px; }
/* flex-direction: row belongs here, not on .settings-row — a .settings-checkbox
   used on its own (e.g. the "Show hidden files" and "Save this connection"
   toggles) previously fell back to `dialog label`'s flex-direction: column
   and stacked the checkbox above its text instead of beside it. */
.settings-checkbox { flex-direction: row !important; justify-content: flex-start !important; align-items: center !important; gap: 10px !important; }
.settings-checkbox input { order: -1; }
#restore-summary { color: var(--text-1); font-size: 13px; margin: 0 0 16px; }

/* ---------- Virtual D-Pad ---------- */
.dpad {
  position: absolute;
  right: 10px;
  bottom: calc(var(--statusbar-h) + var(--safe-bottom) + 10px);
  display: none;
  grid-template-columns: repeat(3, 40px);
  grid-template-rows: repeat(3, 40px);
  gap: 4px;
  background: var(--float-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 6px;
  box-shadow: 0 8px 24px var(--shadow);
  z-index: 20;
  backdrop-filter: blur(6px);
}
.dpad.visible { display: grid; }
.dpad-btn {
  width: 40px; height: 40px;
  font-size: 15px;
  background: var(--bg-3);
}
#dpad-left { grid-column: 1; grid-row: 2; }
#dpad-word-left { grid-column: 1; grid-row: 1; }
#dpad-up { grid-column: 2; grid-row: 1; }
#dpad-down { grid-column: 2; grid-row: 3; }
#dpad-word-right { grid-column: 3; grid-row: 1; }
#dpad-right { grid-column: 3; grid-row: 2; }
#dpad-home { grid-column: 1; grid-row: 3; }
#dpad-end { grid-column: 2; grid-row: 2; }
.dpad-close { grid-column: 3; grid-row: 3; color: var(--danger); }

.dpad-toggle {
  position: absolute;
  right: 10px;
  bottom: calc(var(--statusbar-h) + var(--safe-bottom) + 10px);
  width: 42px; height: 42px;
  border-radius: 50%;
  background: var(--bg-3);
  border: 1px solid var(--border);
  color: var(--text-1);
  font-size: 17px;
  box-shadow: 0 4px 14px var(--shadow);
  z-index: 19;
  display: none;
}

/* Only show the dpad toggle affordance on touch-capable/coarse-pointer devices */
@media (pointer: coarse) {
  .dpad-toggle { display: flex; }
}

/* ---------- Account button ---------- */
.account-btn {
  gap: 6px;
  margin-left: 4px;
  padding-left: 8px;
  padding-right: 10px;
  border-left: 1px solid var(--border-soft);
  border-radius: 0;
}
.account-btn .icon { width: 15px; height: 15px; }
.account-btn.signed-in { color: var(--good); }
#account-label { font-size: 12.5px; max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- Popover (transforms / overflow / outline menus) ---------- */
.popover {
  position: fixed;
  z-index: 30;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 4px;
  min-width: 200px;
  max-width: calc(100vw - 16px);
  box-shadow: 0 12px 32px var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 0;
  /* app.js sets max-height from the space actually available; menus scroll
     instead of clipping on short screens / with the keyboard open. */
  max-height: calc(100dvh - 16px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.popover[hidden] { display: none; }
.popover-section {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 2px 0;
  border-bottom: 1px solid var(--border-soft);
}
.popover-section:last-child { border-bottom: none; }
/* item 47 bug fix: .popover-section's own `display: flex` (an author rule)
   overrides the UA's `[hidden] { display: none }`, so #overflow-prose-tools/
   #overflow-code-tools staying [hidden] had no visual effect — both sections
   showed at once regardless of the active tab's language. Same class of bug
   as .dlg-tabs[hidden] above; needs its own [hidden] rule. */
.popover-section[hidden] { display: none; }
.popover-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-2);
  padding: 3px 8px 2px;
  grid-column: 1 / -1;
}
/* Short options (the six text-case transforms) sit two per row. */
.popover-section.popover-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 2px;
}
.popover-item {
  justify-content: flex-start;
  text-align: left;
  padding: 5px 8px;
  min-height: 30px;
  min-width: 0;
  font-size: 13px;
  border-radius: 6px;
  width: 100%;
  white-space: nowrap;
}
.popover-item[hidden] { display: none; }
/* Long labels in a two-column popover-grid take the full row. */
.popover-grid > .popover-item.span-2 { grid-column: 1 / -1; }
/* Overflow-menu entries that duplicate a visible top-bar button on wide screens. */
.topbar:not(.compact) ~ .popover .compact-only { display: none; }

/* item 47: writing-tools / lint+format menu toggles show a checkmark + accent
   colour when on (role="menuitemcheckbox" — see syncWritingToolsMenu() in app.js). */
.popover-item[aria-checked="true"] { color: var(--accent); }
.popover-item[aria-checked="true"]::before { content: "✓ "; }

/* ---- item 47: readability check decorations (Hemingway-style) -------------
   Sentence-level bands (background) and word/phrase-level marks (underline)
   are allowed to overlap — CM6 handles nested mark decorations fine. */
.rd-hard { background: var(--rd-hard-bg, rgba(230, 180, 40, .16)); }
.rd-veryhard { background: var(--rd-veryhard-bg, rgba(220, 80, 60, .18)); }
.rd-adverb { text-decoration: underline; text-decoration-color: var(--rd-adverb, #3b82f6); text-decoration-thickness: 2px; text-underline-offset: 2px; }
.rd-passive { text-decoration: underline; text-decoration-color: var(--rd-passive, #16a34a); text-decoration-thickness: 2px; text-underline-offset: 2px; }
.rd-wordy { text-decoration: underline dotted; text-decoration-color: var(--rd-wordy, #a855f7); text-underline-offset: 2px; }

/* ---- item 47: grammar check (Harper) squiggly underline -------------------- */
.gr-issue {
  text-decoration: underline wavy;
  text-decoration-color: var(--danger, #dc2626);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* ---- item 47: spell check (Harper) squiggly underline ---------------------
   Visually distinct from .gr-issue (different color) so it's clear at a
   glance which check — Spell or Grammar — flagged a given word, since the
   two checks now run over the same text and can both leave marks at once. */
.sp-issue {
  text-decoration: underline wavy;
  text-decoration-color: var(--sp-issue, #ea580c);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
  cursor: pointer;
}

.grammar-popover {
  max-width: 280px;
  padding: 10px 12px;
}
.grammar-message { margin: 0 0 8px; font-size: 13px; line-height: 1.4; }
.grammar-suggestions { display: flex; flex-wrap: wrap; gap: 6px; }
.grammar-suggestions .btn { font-size: 12px; padding: 4px 10px; border-radius: 999px; }

/* item 47: the Grammar/Readability "N of M" stepper. Redesign: sits in
   normal document flow at the TOP of the editor area (like #change-banner/
   #findbar just above it), not position:fixed — it used to float above the
   bottom of the screen, where it could overlap or get covered by the
   grammar suggestion popover (which is positioned near the flagged text and
   can land anywhere in the viewport). Being in-flow means it takes its own
   space instead of covering anything, and CodeMirror's own resize handling
   already keeps the editor sized to whatever's left (same as toggling
   #change-banner/#findbar). Two rows so the full issue message has room
   without truncation: counter + nav buttons on top, the message below. */
.issue-nav {
  background: var(--bg-1);
  border-bottom: 1px solid var(--border-soft);
  padding: 6px 8px;
  flex-direction: column;
  gap: 2px;
  flex-shrink: 0;
}
.issue-nav[hidden] { display: none; }
.issue-nav-row {
  display: flex;
  align-items: center;
  gap: 2px;
}
.issue-nav-count {
  font-size: 12px;
  font-weight: 600;
  padding: 0 4px;
  white-space: nowrap;
}
.issue-nav-message {
  font-size: 12.5px;
  color: var(--text-1, var(--text-0));
  padding: 0 4px;
  line-height: 1.35;
  /* Long grammar/readability messages should be fully readable, not clipped —
     wrap onto a second line rather than the old single-line ellipsis. */
  overflow-wrap: break-word;
}
.issue-nav .icon-btn { min-height: 28px; min-width: 28px; margin-left: auto; }
.issue-nav #issue-nav-prev { margin-left: 0; }
.issue-nav #issue-nav-next { margin-left: 0; }

/* Outline popup (opens from the status bar, grows upward) */
.outline-popover { min-width: 220px; max-width: min(92vw, 360px); padding: 4px; }
.outline-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--text-1);
  padding: 5px 8px;
  min-height: 30px;
  border-radius: 6px;
  font-size: 12.5px;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.outline-item:hover { background: var(--bg-3); color: var(--text-0); }

/* ---------- Dialog extras (SFTP / account / regex / command palette) ---------- */
.dlg-row { margin-bottom: 12px; }
.dlg-sep { height: 1px; background: var(--border-soft); margin: 10px 0 14px; }
.dlg-hint { font-size: 12px; color: var(--text-2); margin: 0 0 12px; line-height: 1.5; }
.dlg-hint a { color: var(--accent); }
.dlg-error {
  font-size: 12.5px;
  color: var(--danger);
  background: var(--danger-bg);
  border: 1px solid var(--danger-border);
  border-radius: 6px;
  padding: 8px 10px;
  margin: 0 0 12px;
}
.sftp-trace {
  font: 10px/1.35 var(--font-mono);
  color: var(--text-1);
  background: var(--bg-0);
  border: 1px dashed var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  margin: 0 0 10px;
  max-height: 110px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
}
.dlg-grid { display: grid; grid-template-columns: 1fr 90px; gap: 10px; }
.dlg-fieldset {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px 10px;
  margin: 0 0 12px;
}
.dlg-fieldset legend { font-size: 11px; color: var(--text-2); padding: 0 4px; }
.dlg-radio { flex-direction: row !important; align-items: center; gap: 6px !important; font-size: 13px; margin-bottom: 4px !important; }
.dlg-radio input { order: -1; }
.dlg-save-profile-row { margin-top: 4px; }
.btn-danger-text { color: var(--danger); font-size: 12px; padding: 4px 0; }
.dlg-quick-patterns { display: flex; gap: 6px; flex-wrap: wrap; }
.btn-chip { font-size: 12px; padding: 5px 10px; border: 1px solid var(--border); }

.dlg-tabs { display: flex; gap: 4px; margin-bottom: 16px; border-bottom: 1px solid var(--border-soft); }
.dlg-tab {
  flex: 1;
  background: transparent;
  border: none;
  color: var(--text-2);
  padding: 8px 4px;
  font-size: 13px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
}
.dlg-tab.active { color: var(--text-0); border-bottom-color: var(--accent); }

/* ---------- Command palette ---------- */
.dlg-command-palette {
  padding: 0;
  max-width: 560px;
  width: 92vw;
  top: 14vh;
  margin-top: 0;
  overflow: hidden;
}
.cmdk { display: flex; flex-direction: column; max-height: 60vh; }
.cmdk-input {
  border: none;
  border-bottom: 1px solid var(--border-soft);
  background: transparent;
  color: var(--text-0);
  font-size: 16px;
  padding: 16px 18px;
  outline: none;
  font-family: var(--font-ui);
}
.cmdk-list { overflow-y: auto; padding: 6px; }
.cmdk-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-radius: 7px;
  font-size: 13.5px;
  color: var(--text-1);
  cursor: pointer;
}
.cmdk-item .cmdk-hint { font-size: 11px; color: var(--text-2); }
.cmdk-item.active { background: var(--bg-3); color: var(--text-0); }
.cmdk-empty { padding: 20px; text-align: center; color: var(--text-2); font-size: 13px; }

/* ---------- Remote workspace file browser ---------- */
.breadcrumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  font-size: 12.5px;
  color: var(--text-1);
  margin-bottom: 8px;
}
.breadcrumb-item {
  background: transparent;
  border: none;
  color: var(--text-1);
  cursor: pointer;
  padding: 3px 5px;
  border-radius: 5px;
  font-size: 12.5px;
  font-family: inherit;
}
.breadcrumb-item:hover { background: var(--bg-3); color: var(--text-0); }
.breadcrumb-item.current { color: var(--text-0); font-weight: 600; cursor: default; }
.breadcrumb-item.current:hover { background: transparent; }
.breadcrumb-sep { color: var(--text-2); width: 13px; height: 13px; opacity: .6; }

.file-list {
  border: 1px solid var(--border);
  border-radius: 8px;
  max-height: 240px;
  overflow-y: auto;
  margin-bottom: 10px;
}
.file-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text-1);
  border-bottom: 1px solid var(--border-soft);
}
.file-row:last-child { border-bottom: none; }
.file-row:hover { background: var(--bg-3); color: var(--text-0); }
.file-row .icon { width: 15px; height: 15px; flex-shrink: 0; opacity: .75; }
.file-row.dir .icon { color: var(--accent); opacity: 1; }
.file-row-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-list-empty { padding: 18px 10px; text-align: center; color: var(--text-2); font-size: 12.5px; }
.file-list-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.file-list-actions .btn { font-size: 12px; }
.file-list-hidden-toggle { margin: 0 0 0 auto !important; font-size: 12px; color: var(--text-2); }

/* ---------- Pinned tab ---------- */
.tab.pinned .tab-title { font-style: italic; }
.tab.pinned .tab-close { display: none; }


/* ---- Go to line popover --------------------------------------------------- */
.goto-popover { padding: 8px; min-width: 200px; max-width: min(92vw, 280px); }
.goto-popover form { display: flex; gap: 6px; }
.goto-popover input {
  flex: 1;
  min-width: 0;
  background: var(--bg-2);
  color: var(--text-0);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  font: inherit;
  font-size: 16px; /* 16px stops iOS zooming the page on focus */
}
.goto-popover input:focus { outline: 2px solid var(--accent); border-color: var(--accent); }
.goto-hint { margin: 6px 2px 0; font-size: 11px; color: var(--text-2); }
.goto-hint.is-error { color: var(--danger); }

/* ---- Text statistics dialog ------------------------------------------------ */
.dlg-stats { width: min(92vw, 440px); max-height: 86vh; overflow-y: auto; }
.dlg-stats .dlg-tabs { margin-bottom: 8px; }
/* `.dlg-tabs { display: flex }` is an author rule, so it would beat the UA [hidden] rule. */
.dlg-tabs[hidden] { display: none; }
.stats-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-2);
  margin: 12px 0 4px;
}
.stats-title:first-child { margin-top: 0; }
.stats-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 12px;
  margin: 0;
  font-size: 13px;
}
.stats-grid dt { color: var(--text-1); }
.stats-grid dd { margin: 0; color: var(--text-0); text-align: right; font-variant-numeric: tabular-nums; }
.stats-grid dt.wide { grid-column: 1 / -1; margin-top: 4px; }
.stats-grid dd.wide { grid-column: 1 / -1; text-align: left; }
.stats-note { color: var(--text-2); font-size: 11px; }
.stats-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.stats-chip {
  background: var(--bg-3);
  border-radius: 999px;
  padding: 2px 9px;
  font-size: 12px;
  color: var(--text-0);
}
.stats-longest { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.stats-longest .btn-chip { min-height: 0; padding: 3px 12px; }
.stats-quote { display: block; color: var(--text-1); font-size: 12px; font-style: italic; word-break: break-word; }

.settings-subhint { margin: -2px 0 10px 26px; font-size: 11.5px; }

/* ---- account dialog (v5.5): forgot password + repeat password ------------------- */
.account-link-row { margin: -4px 0 12px; font-size: 12.5px; }
.account-link-row a { color: var(--accent); }
.account-link-row[hidden] { display: none; }
.account-pw-hint { margin: -4px 0 10px; }
.account-pw-hint.is-error { color: var(--danger); }
.account-pw-hint[hidden], #account-mode-hint[hidden], #account-sync-hint[hidden] { display: none; }
.btn:disabled, .btn[disabled] { opacity: .5; cursor: not-allowed; }

/* ---- Save As chooser (v5.5) ------------------------------------------------------ */
.dlg-saveas { width: min(92vw, 420px); }
.saveas-options { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 14px; }
.saveas-option {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  text-align: left; width: 100%; min-height: 48px; padding: 10px 12px;
  background: var(--bg-2); color: var(--text-0);
  border: 1px solid var(--border); border-radius: var(--radius); cursor: pointer;
  font: inherit;
}
.saveas-option strong { font-size: 14px; font-weight: 600; }
.saveas-option span { font-size: 12px; color: var(--text-2); line-height: 1.4; }
.saveas-option:hover, .saveas-option:focus-visible { border-color: var(--accent); outline: none; }
.saveas-option.is-last { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.saveas-option[hidden] { display: none; }

/* ---- Scratchpad sync status on the tab dot (v5.5, item 45) -------------------------
   Shape as well as colour, so it still reads without telling greens from ambers.
   solid green = in sync · hollow amber ring = waiting/syncing · grey ring + slash = offline ·
   amber triangle = needs attention (conflict markers kept / too large). */
.tab.sync-on .tab-dirty-dot { display: block; }
.tab .tab-dirty-dot.sync-dot { width: 9px; height: 9px; position: relative; cursor: pointer; border: 0; background: var(--good); }
.tab .tab-dirty-dot.sync-dot::after { content: ''; position: absolute; inset: -9px; }   /* a bigger tap target */
.tab .tab-dirty-dot.sync-dot.sync-pending { background: transparent; box-shadow: inset 0 0 0 2px var(--warn); }
.tab .tab-dirty-dot.sync-dot.sync-pending.is-syncing { animation: syncpulse 1s ease-in-out infinite; }
.tab .tab-dirty-dot.sync-dot.sync-offline {
  background: linear-gradient(135deg, transparent 43%, var(--text-2) 43%, var(--text-2) 57%, transparent 57%);
  box-shadow: inset 0 0 0 2px var(--text-2);
}
.tab .tab-dirty-dot.sync-dot.sync-attention { border-radius: 0; background: var(--warn); clip-path: polygon(50% 0, 100% 100%, 0 100%); width: 10px; height: 9px; }
@keyframes syncpulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .tab .tab-dirty-dot.sync-dot.sync-pending.is-syncing { animation: none; } }

/* ---- Markdown / HTML preview (v5.5, item 41) --------------------------------------
   Wide screens: editor and preview side by side. Phones: the preview replaces the editor
   until you tap Edit (or the eye button) again. */
.preview-pane { display: flex; flex-direction: column; min-height: 0; background: var(--bg-0); }
.preview-pane[hidden] { display: none; }
.preview-bar {
  display: flex; align-items: center; gap: 10px; padding: 4px 8px;
  background: var(--bg-1); border-bottom: 1px solid var(--border-soft);
  font-size: 12px; color: var(--text-2);
}
.preview-spacer { flex: 1; }
.preview-scripts { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; white-space: nowrap; }
.preview-scripts[hidden] { display: none; }
.preview-edit { min-height: 28px; padding: 2px 12px; font-size: 12px; }
.preview-frame-wrap { flex: 1; min-height: 0; position: relative; }
.preview-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: transparent; }
.editor-area.previewing { display: flex; }
.editor-area.previewing .editor { flex: 1 1 50%; min-width: 0; width: auto; height: auto; }
.editor-area.previewing .preview-pane { flex: 1 1 50%; min-width: 0; border-left: 1px solid var(--border-soft); }
@media (max-width: 899px) {
  .editor-area.previewing .editor { display: none; }
  .editor-area.previewing .preview-pane { flex-basis: 100%; border-left: 0; }
}
@media (min-width: 900px) { .preview-edit { display: none; } }
#btn-preview[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
#btn-preview[hidden], #preview-sep[hidden] { display: none; }
@media (max-width: 899px) { .editor-area.previewing ~ .dpad, .editor-area.previewing ~ .dpad-toggle { display: none !important; } }

/* ---------- Dictionary & thesaurus (dlg-lookup) ---------- */
.dlg-lookup { width: min(94vw, 460px); max-height: 88vh; }
.dlg-lookup[open] { display: flex; flex-direction: column; } /* [open] only: a bare display rule would keep the closed dialog visible */
.dlg-lookup form { display: flex; flex-direction: column; min-height: 0; }
.lookup-search { display: flex; gap: 8px; margin-bottom: 10px; }
.lookup-search input { flex: 1; min-width: 0; background: var(--bg-0); border: 1px solid var(--border); color: var(--text-0); border-radius: var(--radius); padding: 8px 10px; font-size: 14px; }
.lookup-search input:focus { outline: 2px solid var(--accent); border-color: var(--accent); }
.lookup-status { margin: 0 0 10px; }
.lookup-status[hidden] { display: none; }
.lookup-body { overflow-y: auto; min-height: 60px; max-height: 52vh; margin-bottom: 8px; -webkit-overflow-scrolling: touch; }
.lookup-credit { font-size: 11px; color: var(--text-2); margin: 0 0 8px; }
.lk-pos { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--accent); margin: 12px 0 4px; font-weight: 600; }
.lk-pos:first-child { margin-top: 0; }
.lk-sense { margin: 0 0 10px; font-size: 13.5px; line-height: 1.45; }
.lk-def { color: var(--text-0); }
.lk-ex { color: var(--text-2); font-style: italic; margin-top: 2px; font-size: 12.5px; }
.lk-from { font-size: 12px; color: var(--text-2); margin: 0 0 8px; }
.lk-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.lk-chip { border: 1px solid var(--border); background: var(--bg-2); color: var(--text-0); border-radius: 999px; padding: 4px 10px; font-size: 13px; cursor: pointer; }
.lk-chip:hover, .lk-chip:focus-visible { border-color: var(--accent); outline: none; }
.lk-chip.is-opposite { border-style: dashed; }
.lk-label { font-size: 11.5px; color: var(--text-2); margin-top: 6px; }
