:root {
  --bg: #eef6ff;
  --panel: #ffffff;
  --ink: #2a3a50;
  --muted: #7a90b0;
  --line: #e2eef8;
  --accent: #6ab8e8;
  --accent-soft: #e4f4fc;
  --note: #ffffff;
  --reply: #4fa8d8;
  --viewport-pad: 16px;
  --sidebar-width: 236px;
  --detail-width: 380px;
  --scrollbar-thumb: rgba(106, 184, 232, 0.42);
  --scrollbar-thumb-hover: rgba(106, 184, 232, 0.62);
  --avatar-size: 38px;
  --avatar-line-gap: 5px;
  --thread-line: 2px;
  --thread-line-color: #aed8f0;
  --avatar-line-left: 18px;
  --memo-column-gap: 12px;
  --reply-group-pad-y: 12px;
  --thread-branch-y: calc(var(--reply-group-pad-y) + var(--avatar-size) / 2 - var(--thread-line) / 2);
  --memo-action-gutter: 30px;
  --thread-connector-left: calc(var(--avatar-line-left) - var(--avatar-size) - var(--memo-column-gap));
  --thread-branch-width: calc(var(--avatar-size) + var(--memo-column-gap) - var(--avatar-line-left) - var(--avatar-line-gap));
  --reply-indent: calc(var(--avatar-size) + var(--memo-column-gap));
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html {
  touch-action: manipulation;
}

button {
  cursor: pointer;
}

body.resizing-panels {
  cursor: col-resize;
  user-select: none;
}

html {
  width: 100%;
  height: 100%;
  min-height: 100%;
  background: var(--panel);
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 0;
  display: grid;
  place-items: stretch;
  overflow: hidden;
  background: var(--panel);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Apple SD Gothic Neo", "Noto Sans KR", sans-serif;
}

.window {
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  min-height: 100lvh;
  overflow: hidden;
  border: none;
  border-radius: 0;
  background: var(--panel);
  box-shadow: none;
}

@supports (-webkit-touch-callout: none) {
  html,
  body {
    min-height: -webkit-fill-available;
  }
}

.titlebar {
  display: none;
}

.mobile-bottom-bar {
  display: none;
}

.panel-toggle {
  width: 32px;
  height: 32px;
  display: none;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  appearance: none;
  background: #fff;
  color: var(--muted);
  cursor: pointer;
}

.panel-toggle svg {
  width: 17px;
  height: 17px;
  stroke: currentColor;
  stroke-width: 2.2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.compose-box {
  display: grid;
  grid-template-columns: var(--avatar-size) 1fr;
  column-gap: var(--memo-column-gap);
  padding: 22px 18px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}

.compose-input {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

#compose-quote-slot:empty {
  display: none;
}

.compose-placeholder {
  font-size: 15px;
  color: #a8c4d4;
  padding-top: 6px;
}

.compose-editor {
  font-size: 16px;
  color: var(--ink);
  padding: 3px 0;
  min-height: 22px;
  outline: none;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}

[contenteditable][data-placeholder]:empty::before {
  content: attr(data-placeholder);
  color: #a8c4d4;
  pointer-events: none;
}

.compose-quote {
  margin-bottom: 8px;
}

.quote-clear {
  margin-left: 8px;
  background: transparent;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  font-size: 12px;
  text-decoration: underline;
}

.body-editor {
  outline: none;
  min-height: 22px;
  padding: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  line-height: inherit;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.edit-actions {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 4px;
}

.edit-actions button {
  font: inherit;
  padding: 3px 9px;
  border-radius: 999px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  font-weight: 650;
  cursor: pointer;
}

.edit-actions button:hover {
  color: var(--accent);
  background: rgba(106, 184, 232, 0.1);
}

.edit-actions button.primary {
  background: rgba(106, 184, 232, 0.16);
  border-color: var(--accent);
  color: var(--accent);
}

.edit-actions button.primary:hover {
  background: rgba(106, 184, 232, 0.24);
}

.compose-footer {
  display: flex;
  justify-content: flex-end;
}

.app {
  position: relative;
  height: 100%;
  display: grid;
  grid-template-columns: var(--sidebar-width) 6px minmax(0, 1fr);
  min-height: 0;
  overflow: hidden;
}

.panel-resizer {
  position: relative;
  z-index: 5;
  padding: 0;
  border: 0;
  appearance: none;
  background: var(--panel);
  cursor: col-resize;
}

.sidebar-resizer {
  background: linear-gradient(to right, #e8f4fc 50%, var(--panel) 50%);
}

.panel-resizer::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--line);
  transform: translateX(-50%);
}

.scrim {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 15;
  border: 0;
  padding: 0;
  /* Invisible click-catcher — no visible overlay over the timeline peek. */
  background: transparent;
  appearance: none;
  cursor: pointer;
}

.sidebar {
  padding: 16px 16px 22px;
  background: #e8f4fc;
  overflow-y: auto;
}

.sidebar-search {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 14px;
  margin-bottom: 14px;
  border: 1px solid #cce6f5;
  border-radius: 9999px;
  background: #ffffff;
  color: #7a90b0;
  font-size: 13.5px;
}

.sidebar-search input {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--ink);
  font: inherit;
}

.sidebar-search input::placeholder {
  color: #7a90b0;
}

.sidebar-search svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  stroke: currentColor;
  stroke-width: 2.2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.search-view-bar {
  display: none;
  align-items: center;
  gap: 10px;
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 0 14px;
  height: 44px;
  margin: 0 18px 14px;
  flex-shrink: 0;
}
.app.search-view .search-view-bar {
  display: flex;
}
.search-view-bar > svg {
  width: 17px; height: 17px;
  stroke: var(--muted);
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}
#search-view-input {
  flex: 1;
  border: none;
  background: none;
  outline: none;
  font-size: 16px;
  color: var(--ink);
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
}
#search-view-input::placeholder { color: var(--muted); }
.search-view-clear {
  display: none;
  padding: 2px;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--muted);
  line-height: 0;
}
.search-view-clear.visible { display: flex; align-items: center; }
.search-view-clear svg { width: 16px; height: 16px; }
.search-empty {
  padding: 48px 16px;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
}

.timeline-empty,
.timeline-load-state {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 34px 16px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.timeline-spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(106, 184, 232, 0.22);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: timeline-spinner-spin 0.75s linear infinite;
  flex: 0 0 auto;
}

@keyframes timeline-spinner-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.pull-refresh-indicator {
  height: 0;
  opacity: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 13px;
  pointer-events: none;
  transition: opacity 120ms ease;
}

.pull-refresh-indicator.visible,
.pull-refresh-indicator.refreshing {
  height: 42px;
  opacity: 1;
}

.pull-refresh-indicator.ready {
  color: var(--accent);
}

.pull-refresh-indicator .timeline-spinner {
  animation: none;
  transform: rotate(var(--pull-refresh-rotation, 0deg));
  will-change: transform;
}

.pull-refresh-indicator.ready .timeline-spinner,
.pull-refresh-indicator.refreshing .timeline-spinner {
  animation: timeline-spinner-spin 0.75s linear infinite;
}

.pull-refresh-indicator.settling {
  transition: height 180ms ease, opacity 140ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .timeline-spinner {
    animation: none;
  }
}

.timeline-load-state.error {
  color: #b46b72;
}

.timeline-load-state button {
  margin-left: 8px;
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--accent);
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}

.nav-title {
  margin: 14px 10px 8px;
  color: #9ac4d8;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
}

.nav-item {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 10px 0 13px;
  border-left: 3px solid transparent;
  color: #2a3a50;
  font-size: 14px;
  font-weight: 560;
}

.nav-item.active {
  color: var(--accent);
  font-weight: 700;
  border-left-color: var(--accent);
}

#nav-timeline,
#nav-bookmarks,
#nav-settings {
  cursor: pointer;
}

#nav-timeline:hover,
#nav-bookmarks:hover,
#nav-settings:hover {
  background: rgba(106, 184, 232, 0.10);
  border-radius: 0 6px 6px 0;
}

.count {
  color: #9ac4d8;
  font-size: 12px;
  font-weight: 600;
}

.main {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 6px var(--detail-width);
  min-width: 0;
  min-height: 0;
}

.timeline {
  padding: 28px 40px 34px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) transparent;
  background: var(--panel);
}

.timeline::-webkit-scrollbar,
.detail::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.timeline::-webkit-scrollbar-track,
.detail::-webkit-scrollbar-track {
  background: transparent;
}

.timeline::-webkit-scrollbar-thumb,
.detail::-webkit-scrollbar-thumb {
  border-radius: 999px;
  background: var(--scrollbar-thumb);
}

.timeline::-webkit-scrollbar-thumb:hover,
.detail::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
}

.timeline-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  margin-bottom: 18px;
}

h1 {
  margin: 0;
  font-size: 28px;
  line-height: 1.1;
  letter-spacing: 0;
}

.sub {
  margin-top: 6px;
  color: var(--muted);
  font-size: 13px;
}

.sync-status {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.78);
  color: var(--muted);
  font-size: 12px;
  font-weight: 650;
  white-space: nowrap;
}

.sync-status.pending {
  color: #4c86aa;
  background: rgba(106, 184, 232, 0.11);
  border-color: rgba(106, 184, 232, 0.28);
}

.sync-status.error {
  color: #c93856;
  background: rgba(224, 71, 106, 0.08);
  border-color: rgba(224, 71, 106, 0.2);
}

.sidebar-sync-status {
  display: none;
}

/* ── Quick-compose bottom-sheet modal ──────────────────────────────────── */
.quick-compose-dialog {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  visibility: hidden;
  align-items: flex-end;
  justify-content: center;
  background: rgba(30, 50, 70, 0);
  pointer-events: none;
  transition: background 280ms ease;
}
.quick-compose-dialog.open,
.quick-compose-dialog.preopen,
.quick-compose-dialog.closing {
  visibility: visible;
}
.quick-compose-dialog.preopen {
  pointer-events: none;
}
.quick-compose-dialog.preopen .quick-compose-editor,
.quick-compose-dialog.opening .quick-compose-editor {
  caret-color: transparent;
}
.quick-compose-dialog.open {
  background: rgba(30, 50, 70, 0.18);
  pointer-events: auto;
}
.quick-compose-dialog.closing {
  pointer-events: none;
}
.quick-compose-dialog.closing .quick-compose-card {
  transition: transform 420ms cubic-bezier(0.22, 0.68, 0.18, 1),
              box-shadow 420ms ease;
}

.quick-compose-card {
  /* Partial (bottom-sheet) state */
  position: fixed;
  bottom: 0; left: 0; right: 0;
  display: flex;
  flex-direction: column;
  max-height: 72svh;
  padding: 12px 18px calc(20px + env(safe-area-inset-bottom));
  border-radius: 22px 22px 0 0;
  border: 1px solid var(--line);
  border-bottom: none;
  background: rgba(255, 255, 255, 0.98);
  box-shadow: none;
  transform: translateY(100%);
  top: auto;
  transition: transform 300ms cubic-bezier(0.05, 0.7, 0.1, 1),
              top 300ms cubic-bezier(0.05, 0.7, 0.1, 1),
              border-radius 300ms ease,
              padding-top 300ms ease,
              box-shadow 300ms ease;
  will-change: transform;
  overflow: hidden;
  pointer-events: auto;
}
.quick-compose-dialog.open .quick-compose-card {
  transform: translateY(0);
  box-shadow: none;
}
/* Fullscreen state — fills the screen but keeps the same visual style as
   the partial sheet (rounded top, handle, 새 메모 + X head, post footer).
   The transparent backdrop lets the timeline show behind the card edge. */
.quick-compose-card.qc-full {
  top: env(safe-area-inset-top, 0px);
  max-width: none;
  border-radius: 22px 22px 0 0;
  max-height: none;
  border: none;
  box-shadow: none;
  background: #fff;
  padding: 8px 18px calc(20px + env(safe-area-inset-bottom));
  transition: transform 300ms cubic-bezier(0.05, 0.7, 0.1, 1),
              box-shadow 300ms ease;
}
.quick-compose-dialog.qc-full-active {
  background: none;
}

.quick-compose-handle {
  flex-shrink: 0;
  width: 100%;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none;
}
.quick-compose-handle::after {
  content: '';
  width: 36px;
  height: 4px;
  border-radius: 999px;
  background: var(--line);
}
/* Fullscreen keeps the same UI as partial: handle, 새 메모 + X head,
   body, and the footer post button. The nav-bar cancel/post are unused. */

.quick-compose-head {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  cursor: grab;
  touch-action: none;
}
/* Match the detail panel close button design (.close). */
.quick-compose-close {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  appearance: none;
  background: #fff;
  color: var(--muted);
  cursor: pointer;
}
.quick-compose-close svg { width: 16px; height: 16px; stroke-width: 2.2; }

.quick-compose-body {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: var(--avatar-size) 1fr;
  /* Bound the row to the body height so the editor below resolves to a fixed
     height and scrolls internally instead of growing the whole panel. */
  grid-template-rows: minmax(0, 1fr);
  column-gap: var(--memo-column-gap);
  /* The editor is the only scroll container; the body itself never scrolls so
     a growing caret cannot scroll the panel or the timeline behind it. */
  overflow: hidden;
}
.quick-compose-content {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.quick-compose-editor {
  flex: 1;
  font-size: 16px;
  color: var(--ink);
  /* Open the partial bottom sheet at roughly slightly-below-half height.
     The sheet is bottom-anchored with no fixed height (so the drag-to-full
     gesture can grow it), so the initial size comes from the editor's
     min-height plus the surrounding chrome. */
  min-height: 30svh;
  max-height: 48svh;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  outline: none;
  line-height: 1.6;
  white-space: pre-wrap;
  word-wrap: break-word;
  padding: 2px 0;
  transition: max-height 300ms ease;
}
/* Let content fill in fullscreen */
.quick-compose-card.qc-full .quick-compose-body {
  flex: 1;
  min-height: 0;
}
.quick-compose-card.qc-full .quick-compose-content {
  flex: 1;
  min-height: 0;
}
.quick-compose-card.qc-full .quick-compose-editor {
  max-height: none;
  min-height: 0;
  flex: 1;
}
/* Nudge the head row (X / 임시저장 / ME!) down from the very top edge. */
.quick-compose-card.qc-full .quick-compose-head {
  margin-top: 10px;
}

.quick-compose-post {
  height: 34px;
  padding: 0 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 140ms ease;
  white-space: nowrap;
}
.quick-compose-post:hover { background: var(--reply); }

.qc-head-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.quick-compose-drafts-btn {
  height: 34px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.quick-compose-drafts-btn.active { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.qc-drafts-count {
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  display: inline-grid;
  place-items: center;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 11px;
}
/* In-panel drafts list replaces the editor area when the 임시저장 button is on. */
.qc-drafts {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: #fff;
  margin: 0 -18px;
  padding: 4px 0 calc(8px + env(safe-area-inset-bottom));
}
.qc-drafts .draft-item { padding-left: 18px; padding-right: 18px; }
.qc-drafts-empty {
  padding: 40px 18px;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
}

.search-hit {
  font-weight: 800;
  color: inherit;
}

.draft-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
}
.draft-item-body {
  flex: 1;
  min-width: 0;
  cursor: pointer;
}
.draft-item-text {
  font-size: 15px;
  color: var(--ink);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}
.draft-item-time {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
}
.draft-item-delete {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: #fff;
  color: var(--muted);
  cursor: pointer;
}
.draft-item-delete:hover { color: #c93856; border-color: #c93856; }

.auth-dialog {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(238, 246, 255, 0.78);
  backdrop-filter: blur(10px);
}

.auth-dialog.open {
  display: flex;
}

.auth-card {
  width: min(390px, 100%);
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: none;
}

.auth-card h2 {
  margin: 0;
  font-size: 21px;
  line-height: 1.25;
  letter-spacing: 0;
}

.auth-card p {
  margin: 7px 0 18px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.45;
}

.auth-field {
  display: grid;
  gap: 7px;
  margin-top: 12px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
}

.auth-field input {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #fff;
  color: var(--ink);
  font: inherit;
  font-size: 16px;
  outline: none;
}

.auth-field input:focus {
  border-color: rgba(106, 184, 232, 0.72);
  box-shadow: 0 0 0 4px rgba(106, 184, 232, 0.14);
}

.auth-remember {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.3;
  cursor: pointer;
  user-select: none;
}

.auth-remember input {
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.auth-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
}

.auth-actions button {
  min-height: 28px;
  padding: 0 11px;
  border: 0;
  border-radius: 999px;
  color: var(--muted);
  background: transparent;
  font: inherit;
  font-size: 13px;
  font-weight: 400;
  transition: background-color 140ms ease, color 140ms ease, box-shadow 140ms ease;
}

.auth-actions button:hover {
  color: var(--muted);
  background: var(--accent-soft);
}

.auth-actions .primary {
  color: #fff;
  background: var(--accent);
}

.auth-actions .primary:hover {
  color: #fff;
  background: var(--reply);
}

.auth-actions button:disabled {
  cursor: default;
  opacity: 0.62;
  box-shadow: none;
}

.auth-error {
  min-height: 18px;
  margin-top: 12px;
  color: #c93856;
  font-size: 12px;
  font-weight: 500;
}

.app.settings-view .compose-box,
.app.search-view .compose-box {
  display: none;
}
.app.selection-mode .compose-box {
  display: none;
}

.settings-page {
  padding: 0 18px 60px;
}

.settings-section {
  padding: 20px;
  margin-bottom: 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.72);
}

.settings-section h2 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font-size: 16px;
  letter-spacing: 0;
}

.settings-section h2 svg {
  flex-shrink: 0;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--muted);
}

.settings-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 10px;
}

.settings-input {
  flex: 1;
  min-width: 0;
  max-width: 200px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  color: var(--ink);
  font: inherit;
  outline: none;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}

.settings-input:focus {
  border-color: rgba(106, 184, 232, 0.72);
  box-shadow: 0 0 0 4px rgba(106, 184, 232, 0.12);
}

.settings-button {
  min-height: 32px;
  padding: 0 13px;
  border: 0;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  transition: background-color 140ms ease, color 140ms ease;
}

.settings-button:hover {
  background: rgba(106, 184, 232, 0.18);
  color: var(--accent);
}

.settings-button.primary {
  background: var(--accent);
  color: #fff;
}

.settings-button.primary:hover {
  background: var(--reply);
  color: #fff;
}

.settings-button.danger {
  background: rgba(224, 71, 106, 0.08);
  color: #c93856;
}

.settings-button.danger:hover {
  background: rgba(224, 71, 106, 0.16);
  color: #b8304a;
}

.settings-profile-preview {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--profile-avatar-bg, radial-gradient(circle at 35% 30%, #d0eaf8 0 18%, #6abce8 19% 39%, #3a7aaa 40% 100%));
  background-size: cover;
  background-position: center;
  flex: 0 0 44px;
}

.settings-avatar-upload {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 13px;
  border: 1px dashed var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease, background-color 140ms ease;
}

.settings-avatar-upload:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}

.settings-avatar-upload svg {
  flex-shrink: 0;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.settings-muted {
  margin-top: 10px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}

.settings-status {
  min-height: 18px;
  margin-top: 8px;
  color: var(--muted);
  font-size: 12px;
}

.memo-select-check {
  position: absolute;
  top: 18px;
  left: 18px;
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
  z-index: 3;
}

.app.selection-mode .memo {
  padding-left: 48px;
}

.selection-bar {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 18px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(10px);
  box-shadow: none;
  z-index: 100;
  animation: selection-bar-up 200ms ease-out both;
}

.selection-bar-count {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}

.selection-bar button {
  min-height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 140ms ease, color 140ms ease;
}

.selection-bar .sel-cancel {
  background: var(--accent-soft);
  color: var(--muted);
}

.selection-bar .sel-cancel:hover {
  background: rgba(106, 184, 232, 0.18);
  color: var(--accent);
}

.selection-bar .sel-delete {
  background: rgba(224, 71, 106, 0.08);
  color: #c93856;
}

.selection-bar .sel-delete:hover {
  background: rgba(224, 71, 106, 0.16);
  color: #b8304a;
}

@keyframes selection-bar-up {
  from { opacity: 0; transform: translateX(-50%) translateY(12px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

.confirm-dialog {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(238, 246, 255, 0.78);
  backdrop-filter: blur(10px);
}

.confirm-dialog.open {
  display: flex;
}

/* Backdrop-less popup: no heavy blue blur, just the same subtle white veil the
   sliding panels use, so it's clear a popup is up without dimming hard. */
.confirm-dialog.popup-veil {
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.confirm-card {
  width: min(360px, 100%);
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: none;
  animation: menu-slide-down 140ms ease-out both;
}

.confirm-card h3 {
  margin: 0 0 8px;
  font-size: 17px;
  color: var(--ink);
}

.confirm-card p {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.confirm-actions button {
  min-height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background-color 140ms ease, color 140ms ease;
}

.confirm-actions .confirm-cancel {
  background: transparent;
  color: var(--muted);
}

.confirm-actions .confirm-cancel:hover {
  background: var(--accent-soft);
}

.confirm-actions .confirm-ok {
  background: rgba(224, 71, 106, 0.08);
  color: #c93856;
}

.confirm-actions .confirm-ok:hover {
  background: rgba(224, 71, 106, 0.16);
  color: #b8304a;
}

.confirm-actions .confirm-save {
  background: var(--accent);
  color: #fff;
}
.confirm-actions .confirm-save:hover {
  background: var(--reply);
}
/* Three choices: discard (left) separated from cancel/save (right). */
.draft-choice-actions {
  justify-content: space-between;
}

.crop-dialog {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(10, 20, 36, 0.72);
  backdrop-filter: blur(12px);
}
.crop-dialog.open { display: flex; }

.crop-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: none;
  animation: menu-slide-down 140ms ease-out both;
}

.crop-card h3 {
  margin: 0;
  font-size: 15px;
  color: var(--ink);
  align-self: flex-start;
}

.crop-canvas-wrap {
  position: relative;
  width: 300px;
  height: 300px;
  border-radius: 12px;
  overflow: hidden;
  background: #111;
  cursor: grab;
  touch-action: none;
}
.crop-canvas-wrap:active { cursor: grabbing; }

#crop-canvas {
  display: block;
  width: 300px;
  height: 300px;
}

.crop-zoom-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
}

.crop-zoom-row svg {
  flex-shrink: 0;
  stroke: var(--muted);
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.crop-zoom-slider {
  flex: 1;
  height: 4px;
  accent-color: var(--accent);
  cursor: pointer;
}

.crop-hint {
  font-size: 11px;
  color: var(--muted);
}

.crop-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  width: 100%;
}

.crop-actions button {
  min-height: 32px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background-color 140ms ease, color 140ms ease;
}

.crop-cancel {
  background: transparent;
  color: var(--muted);
}
.crop-cancel:hover { background: var(--accent-soft); }

.crop-ok {
  background: var(--accent);
  color: #fff;
}
.crop-ok:hover { background: var(--reply); }

.compose {
  height: 38px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--muted);
  font-size: 13px;
}

.memo {
  position: relative;
  padding: 18px 18px 18px 18px;
  border-top: 1px solid var(--line);
}

.memo-post {
  position: relative;
  display: grid;
  grid-template-columns: var(--avatar-size) 1fr;
  column-gap: var(--memo-column-gap);
}

.memo-content,
.memo-post > div:last-child {
  position: relative;
  padding-right: var(--memo-action-gutter);
}

.memo.selected {
  background: rgba(106, 184, 232, 0.11);
}

.meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 650;
}

.meta strong {
  color: var(--ink);
  font-size: 13px;
}

.body {
  max-width: 690px;
  font-size: 15px;
  line-height: 1.55;
  letter-spacing: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.hashtag {
  color: #b88fd8;
  font-weight: 650;
  text-decoration: none;
}

.actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 260px;
  margin-top: 11px;
  color: #7a90b0;
  font-size: 13px;
  font-weight: 400;
  line-height: 1;
}

.memo-post > .memo-content > .actions,
.memo-post > div:last-child > .actions,
.thread-content > .actions {
  width: 100%;
  max-width: none;
}

.icon-action {
  position: relative;
  display: inline-flex;
  align-items: center;
  align-content: center;
  justify-content: center;
  gap: 4px;
  min-width: 32px;
  height: 24px;
  padding: 0;
  border: 0;
  appearance: none;
  background: transparent;
  color: #7a90b0;
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: color 120ms ease;
}

.icon-action svg {
  width: 18px;
  height: 18px;
  display: block;
  flex: 0 0 auto;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  z-index: 1;
}

.icon-action.reply,
.icon-action.quote {
  display: grid;
  grid-template-columns: 20px auto;
  column-gap: 4px;
  align-items: center;
  justify-content: start;
}

.icon-action span {
  display: inline-block;
  min-width: 0;
  margin-left: -1px;
  font-weight: 400;
  transform: translateY(-0.5px);
  z-index: 1;
}

.icon-action.reply span,
.icon-action.quote span {
  margin-left: 0;
}

.icon-action::before,
.icon-action::after,
.actions::before,
.actions::after {
  content: none;
  display: none;
}

.icon-action.bookmarked svg {
  fill: rgba(106, 184, 232, 0.16);
  color: var(--accent);
}

.icon-action:hover {
  background: transparent;
  color: var(--accent);
}

.icon-action.active {
  color: var(--accent);
}

.icon-action.bookmarked:hover svg {
  fill: rgba(106, 184, 232, 0.22);
}

.reply-actions {
  width: 100%;
  max-width: none;
  margin-top: 8px;
  color: #9ac4d8;
}

.thread {
  position: relative;
  margin-top: 0;
  margin-right: calc(-1 * var(--memo-action-gutter));
}

.thread::before {
  content: none;
}

.preview-group {
  position: relative;
  margin-top: 0;
  padding: var(--reply-group-pad-y) 0;
}

.preview-group::before {
  content: "";
  position: absolute;
  left: var(--thread-connector-left);
  top: var(--thread-branch-y);
  width: var(--thread-branch-width);
  height: var(--thread-line);
  background: var(--thread-line-color);
  z-index: 0;
  pointer-events: none;
}

/* The continuous vertical trunk now lives on .memo-post::before
   so it can extend from just below the root avatar (CSS-only top)
   down to the last L-branch (JS-computed height). */
.memo-post:has(.thread .preview-group)::before {
  content: "";
  position: absolute;
  left: var(--avatar-line-left);
  top: calc(var(--avatar-size) + var(--avatar-line-gap));
  height: var(--thread-trunk-height, 0px);
  width: var(--thread-line);
  background: var(--thread-line-color);
  z-index: 0;
  pointer-events: none;
}

.preview-group > .thread-row,
.preview-group > .thread-gap {
  position: relative;
  z-index: 1;
}

.preview-group + .preview-group {
  margin-top: 0;
  border-top: 1px solid rgba(180, 220, 245, 0.55);
}

.preview-group .thread-row:last-of-type {
  padding-bottom: 0;
}

.thread > .preview-group:last-child {
  padding-bottom: 0;
}


.thread-gap {
  position: relative;
  height: 20px;
  margin: 2px 0;
}

.thread-gap::before {
  content: "";
  position: absolute;
  left: var(--avatar-line-left);
  top: 0;
  bottom: 0;
  width: var(--thread-line);
  background: repeating-linear-gradient(
    to bottom,
    var(--thread-line-color) 0px,
    var(--thread-line-color) 3px,
    transparent 3px,
    transparent 7px
  );
}

.thread-gap span {
  display: none;
}

.thread-toggle {
  display: block;
  margin: 0;
  padding: 8px 0 4px;
  padding-left: var(--reply-indent);
  background: transparent;
  border: 0;
  color: var(--accent);
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}

.thread-toggle:hover {
  text-decoration: underline;
}

.reply-summary {
  margin-top: 10px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
}

.quote-preview {
  margin-top: 12px;
  padding: 11px 12px;
  border: 1px solid #cce6f4;
  border-radius: 10px;
  background: rgba(234, 246, 255, 0.7);
}

.avatar-sm {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex: 0 0 26px;
  background: var(--profile-avatar-bg, radial-gradient(circle at 35% 30%, #d0eaf8 0 18%, #6abce8 19% 39%, #3a7aaa 40% 100%));
  background-size: cover;
  background-position: center;
}

.quote-meta {
  display: flex;
  align-items: baseline;
  gap: 6px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.25;
  margin-bottom: 6px;
}

.quote-meta strong {
  color: var(--ink);
  font-size: 14px;
  font-weight: 700;
}

.quote-body {
  font-size: 14px;
  line-height: 1.5;
  color: #2a3a50;
}

.quoted-source {
  margin-top: 10px;
  padding: 10px 11px;
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  column-gap: 10px;
  align-items: start;
  border: 1px solid #cce6f4;
  border-radius: 9px;
  background: rgba(234, 246, 255, 0.7);
}

.quoted-content {
  min-width: 0;
}

.detail {
  padding: 24px 22px;
  background: #ffffff;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) transparent;
}

/* Suppress transitions while the window is being resized, so the
   .detail panel doesn't animate when it switches layout modes across
   the 760px breakpoint. */
.app.resizing .detail,
.app.resizing .main,
.app.resizing .sidebar {
  transition: none !important;
}

.conversation-empty {
  padding: 36px 8px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.detail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}

.detail h2 {
  margin: 0;
  font-size: 15px;
  letter-spacing: 0;
}

.close {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  appearance: none;
  background: #fff;
  color: var(--muted);
  cursor: pointer;
}

.close svg {
  width: 16px;
  height: 16px;
  stroke: currentColor;
  stroke-width: 2.2;
  fill: none;
  stroke-linecap: round;
}

.detail-body {
  margin-top: 0;
  font-size: 15px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.detail-timestamp {
  margin-top: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.35;
}

.search-state {
  margin-top: 4px;
  color: var(--muted);
  font-size: 12px;
}

.conversation {
  margin-top: 8px;
}

.reply-group {
  margin-top: 0;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}

.root-row + .reply-group {
  padding-top: 18px;
}

.conversation > .reply-compose {
  margin-top: 0;
  padding-top: 12px;
  padding-bottom: 18px;
  border-top: 0;
  border-bottom: 1px solid var(--line);
}

.thread-row {
  position: relative;
  display: block;
  min-height: var(--avatar-size);
  padding: 0 0 12px;
}

.thread-row::before {
  content: "";
  position: absolute;
  left: var(--avatar-line-left);
  top: calc(var(--avatar-size) + var(--avatar-line-gap));
  bottom: 7px;
  width: var(--thread-line);
  background: var(--thread-line-color);
}

/* Hide the vertical line on the LAST reply of any thread (timeline preview-group
   or conversation reply-group). Using :last-of-type so a thread-toggle button
   sibling doesn't break this. */
.thread-row:last-of-type::before {
  display: none;
}

.reply-group .thread-row:last-of-type {
  padding-bottom: 0;
}

.root-row {
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.root-row::before {
  display: none;
}

.avatar {
  width: var(--avatar-size);
  height: var(--avatar-size);
  border-radius: 50%;
  background: var(--profile-avatar-bg, radial-gradient(circle at 35% 30%, #d0eaf8 0 18%, #6abce8 19% 39%, #3a7aaa 40% 100%));
  background-size: cover;
  background-position: center;
}

.thread-row > .avatar {
  position: absolute;
  left: 0;
  top: 0;
}

.thread-content {
  position: relative;
  min-width: 0;
  width: 100%;
  padding-left: var(--reply-indent);
  padding-right: 28px;
  padding-top: 1px;
}

.thread-author {
  display: flex;
  align-items: baseline;
  gap: 5px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.25;
}

.thread-author strong {
  color: var(--ink);
  font-size: 14px;
}


.more-button {
  position: absolute;
  top: -4px;
  right: 0;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  appearance: none;
  background: transparent;
  color: var(--muted);
  padding: 0;
  cursor: pointer;
}

.more-button svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.more-button:hover {
  background: rgba(104, 176, 216, 0.1);
  color: #2a3a50;
}

/* Menu's top-right corner anchors at the ... button's center.
   The button is positioned at top:-4 right:0 width:24 height:24,
   so its center sits at top:8 right:12. */
.more-menu {
  position: absolute;
  top: 8px;
  right: 12px;
  width: fit-content;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
  box-shadow: none;
  color: #5aaee0;
  font-size: 13px;
  font-weight: 700;
  z-index: 2;
  transform-origin: top right;
  animation: menu-slide-down 140ms ease-out both;
}

.menu-item {
  position: relative;
  padding: 10px 18px;
  border-radius: 0;
  white-space: nowrap;
  cursor: pointer;
}

.menu-item:first-child {
  border-radius: 7px 7px 0 0;
}

.menu-item:last-child {
  border-radius: 0 0 7px 7px;
}

.menu-item:only-child {
  border-radius: 7px;
}

.menu-item:hover {
  background: rgba(106, 184, 232, 0.12);
}

.menu-item.danger {
  color: #e0476a;
}

.menu-item.danger:hover {
  background: rgba(224, 71, 106, 0.1);
}

.quote-wrap {
  position: relative;
  display: inline-flex;
}

.quote-menu {
  position: absolute;
  top: 50%;
  right: 50%;
  width: max-content;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
  box-shadow: none;
  color: #5aaee0;
  font-size: 13px;
  font-weight: 700;
  z-index: 3;
  transform-origin: top right;
  animation: menu-slide-down 140ms ease-out both;
}

.quote-menu .menu-item {
  padding: 10px 16px;
  text-align: center;
}

@keyframes menu-slide-down {
  from {
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.reply-compose {
  display: grid;
  grid-template-columns: 32px 1fr;
  column-gap: 10px;
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.reply-compose .avatar-sm {
  margin-top: 3px;
}

.reply-compose-field {
  font-size: 16px;
  color: #a8c4d4;
  padding: 3px 0;
  line-height: 1.5;
  outline: none;
  color: var(--ink);
  min-height: 21px;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.reply-compose-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}

.reply-post-btn {
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  appearance: none;
  background: rgba(106, 184, 232, 0.62);
  color: #fff;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  cursor: pointer;
  transition: background 120ms ease;
}

.reply-post-btn:hover {
  background: var(--accent);
}

.reply-post-btn svg {
  width: 15px;
  height: 15px;
  stroke: #fff;
  stroke-width: 2.4;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.detail-reply-body {
  margin-top: 4px;
  font-size: 15px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.panel-hint {
  margin-top: 14px;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
}

.capture {
  position: absolute;
  left: 50%;
  bottom: 38px;
  transform: translateX(-50%);
  width: 560px;
  height: 58px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px 0 18px;
  border: 1px solid rgba(33, 107, 93, 0.28);
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: none;
}

.placeholder {
  color: #8c877f;
  font-size: 15px;
}

.post {
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  appearance: none;
  background: rgba(106, 184, 232, 0.62);
  color: #fff;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  cursor: pointer;
  transition: background 120ms ease;
}

.post:hover {
  background: var(--accent);
}

.post svg {
  width: 15px;
  height: 15px;
  stroke: #fff;
  stroke-width: 2.4;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (max-width: 1180px) {
  :root {
    --sidebar-width: 208px;
    --detail-width: 340px;
  }

  .timeline {
    padding: 24px 28px 32px;
  }

  .body {
    max-width: none;
  }
}

@media (max-width: 980px) {
  .app {
    grid-template-columns: minmax(0, 1fr);
  }
  .app.sidebar-open {
    background: var(--panel);
  }

  .panel-resizer {
    display: none;
  }

  .sidebar-toggle {
    display: grid;
  }

  /* Twitter-style reveal: the sidebar sits underneath (never moves), and the
     main content slides right to expose it. The main has an opaque background
     so the menu is hidden when closed. */
  .sidebar {
    position: absolute;
    inset: 0 auto 0 0;
    z-index: 1;
    display: block;
    width: min(280px, 72vw);
    visibility: hidden;
    opacity: 0;
    transition: opacity 160ms ease, visibility 0s linear 160ms;
    /* Sidebar background fills the notch area; push its content below notch */
    padding-top: calc(16px + env(safe-area-inset-top));
  }

  .app.sidebar-open .sidebar,
  .app.sidebar-revealing .sidebar {
    visibility: visible;
    opacity: 1;
    transition: opacity 160ms ease;
  }

  .main {
    position: relative;
    z-index: 2;
    background: var(--panel);
    transition: transform 220ms ease, border-radius 220ms ease, box-shadow 220ms ease;
    will-change: transform;
    grid-template-columns: minmax(0, 1fr) minmax(320px, 36vw);
    box-shadow: none;
    border-radius: 0;
    overflow: hidden;
  }

  .app.sidebar-open .main {
    transform: translateX(min(280px, 72vw));
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    box-shadow: none;
  }

  .app.sidebar-revealing .main {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    box-shadow: none;
  }

  /* Scrim only covers the visible peek of the timeline so the sidebar
     (revealed beneath) stays at its natural color. */
  .app.sidebar-open .scrim,
  .app.sidebar-revealing .scrim {
    display: block;
    left: min(280px, 72vw);
  }

}

@media (max-width: 760px) {
  :root {
    --viewport-pad: 0px;
    --mobile-sidebar-width: min(280px, 72vw);
    /* iPhone display corner radius (pt = CSS px): ~47 on 13/14, 55 on
       14 Pro / 15-series. Drives the PWA drawer card corners. */
    --ios-corner: 55px;
  }

  html,
  body {
    width: 100%;
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    display: block;
    overflow-x: hidden;
    overflow-y: auto;
    background: var(--panel);
  }

  /* While the compose panel is open, freeze the document scroller so the
     keyboard / caret cannot scroll the page (panel + timeline) behind the
     fixed sheet. The editor keeps its own internal scroll. */
  html.qc-scroll-lock,
  html.qc-scroll-lock body {
    overflow: hidden !important;
    overscroll-behavior: none;
    touch-action: none;
  }

  .window {
    width: 100%;
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: var(--panel);
  }

  .app {
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
    background: var(--panel);
  }

  .main {
    grid-template-columns: minmax(0, 1fr);
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
    will-change: auto;
    background: var(--panel);
  }

  .app.sidebar-open .main,
  .app.sidebar-revealing .main {
    position: relative;
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
    will-change: transform;
    border-top-left-radius: 28px;
    border-bottom-left-radius: 0;
    box-shadow: none;
  }

  .app.sidebar-open .main {
    transform: translateX(var(--mobile-sidebar-width));
  }

  .app.sidebar-open .timeline,
  .app.sidebar-revealing .timeline {
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
    border-top-left-radius: 28px;
    border-bottom-left-radius: 0;
  }

  .detail {
    position: fixed;
    inset: 0;
    z-index: 30;
    display: block;
    width: 100%;
    height: 100%;
    padding: calc(12px + env(safe-area-inset-top)) 16px calc(24px + env(safe-area-inset-bottom));
    border: 0;
    border-radius: 0;
    pointer-events: none;
    transform: translateX(100%);
    transition: transform 240ms ease;
    box-shadow: none;
  }

  .app.detail-open .detail {
    pointer-events: auto;
    transform: translateX(0);
    box-shadow: none;
  }

  /* At mobile, the detail panel opens as a centered modal *inside* .main
     (which forms its own stacking context). Showing the .scrim sibling at
     z-index 15 would visually and interactively sit on top of .main entirely,
     making the popup unclickable. So we keep the scrim hidden in this mode
     and instead close the modal via a click handler on .main outside .detail. */
  .app.detail-open .scrim {
    display: none;
  }

  .app.detail-open .main::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 25;
    background: transparent;
    cursor: pointer;
  }

  .app.detail-open .detail {
    z-index: 30;
  }

  .timeline {
    min-height: 100vh;
    min-height: 100dvh;
    height: auto;
    overflow: visible;
    -webkit-overflow-scrolling: touch;
    padding: 56px 16px calc(86px + env(safe-area-inset-bottom));
    border-right: 0;
  }

  .timeline-head {
    min-height: 56px;
    padding-top: 0;
    padding-bottom: 0;
  }

  .compose-box {
    display: none;
  }

  /* Sidebar search is redundant on mobile — the bottom bar has a dedicated
     Search page. */
  .sidebar-search {
    display: none;
  }

  /* The timeline's first memo box sits flush under the fixed header but its
     16px inner padding makes the content look spaced. Search/settings pages
     have no such padding, so add an equivalent top gap to match.
     Left/right margin is 12px so the search box edges line up with the memo
     content edges (avatar left / ... right = timeline 16px + memo 12px). */
  .search-view-bar {
    margin: 16px 12px 14px;
  }

  .app.search-view .timeline {
    padding-top: calc(118px + env(safe-area-inset-top, 0px));
  }

  .app.search-view .search-view-bar {
    position: fixed;
    top: calc(64px + env(safe-area-inset-top, 0px));
    left: 12px;
    right: 12px;
    z-index: 79;
    margin: 0;
  }

  .settings-page {
    padding: 16px 12px 60px;
  }

  .memo {
    padding: 16px 12px;
  }

  .app.selection-mode .memo {
    padding-left: 42px;
  }

  .memo-select-check {
    top: 16px;
    left: 12px;
  }

  .selection-bar {
    bottom: calc(18px + env(safe-area-inset-bottom));
    padding: 8px 14px;
  }

  .capture {
    width: calc(100% - 32px);
    bottom: calc(18px + env(safe-area-inset-bottom));
  }

  .mobile-bottom-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 70;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    align-items: center;
    gap: 0;
    min-height: calc(54px + env(safe-area-inset-bottom));
    padding: 2px 0 calc(4px + env(safe-area-inset-bottom));
    border-top: 1px solid rgba(133, 166, 184, 0.2);
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: blur(18px) saturate(1.12);
    -webkit-backdrop-filter: blur(18px) saturate(1.12);
  }

  .app.sidebar-open .mobile-bottom-bar,
  .app.sidebar-revealing .mobile-bottom-bar,
  .app.sidebar-dragging .mobile-bottom-bar,
  .app.sidebar-closing .mobile-bottom-bar {
    transform: translateY(var(--sidebar-scroll-offset, 0px));
  }

  .mobile-bottom-action {
    display: grid;
    place-items: center;
    width: 100%;
    min-width: 0;
    height: 42px;
    padding: 0;
    border: 0;
    border-radius: 0;
    appearance: none;
    background: transparent;
    color: #8aa0ad;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  .mobile-bottom-action svg {
    width: 29px;
    height: 29px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .mobile-bottom-action.active {
    color: #122033;
  }

  .mobile-bottom-action[data-mobile-tab="compose"] {
    align-self: center;
    justify-self: center;
    width: 100%;
    height: 42px;
    border-radius: 0;
    background: transparent;
    color: var(--accent);
  }

  .mobile-bottom-action[data-mobile-tab="compose"] svg {
    width: 31px;
    height: 31px;
    stroke-width: 1.9;
  }

  .mobile-bottom-action:active {
    transform: scale(0.94);
  }

  /* Sticky header — tapping it scrolls to top */
  .timeline-head {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 80;
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr) 48px;
    align-items: center;
    min-height: 56px;
    background: #fff;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    margin-bottom: 0;
    cursor: default;
    padding-top: 0;
    padding-bottom: 0;
    padding-left: 16px;
    padding-right: 16px;
    margin-left: 0;
    margin-right: 0;
    /* When the sidebar opens, .main gains a transform and becomes the
       containing block for this fixed header, which would otherwise shift
       it up by the current scroll offset. JS sets --sidebar-scroll-offset
       to the frozen scrollY while .main is transformed so the header stays
       visually pinned to the viewport top. It is 0 (no shift) otherwise. */
    transform: translateY(var(--sidebar-scroll-offset, 0px));
  }
  /* Keep the timeline header in place behind the detail panel. The panel
     (z-index 90, inset:0) already covers it while open, so it slides over
     the header on open and reveals it again on close/slide instead of the
     header abruptly disappearing. pointer-events stays off so the briefly
     exposed header edge during the slide can't trigger scroll-to-top. */
  .app.detail-open .timeline-head {
    pointer-events: none;
  }
  .app.detail-open .detail {
    z-index: 90;
  }
  .timeline-head > div {
    position: static;
    grid-column: 2;
    justify-self: center;
    transform: none;
    white-space: nowrap;
  }
  .timeline-head .panel-toggle {
    grid-column: 1;
    justify-self: start;
    margin-top: 0;
  }
  #timeline-list > .memo:first-child {
    border-top: 0;
  }
  #sync-status {
    display: none;
  }
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--mobile-sidebar-width);
    height: auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    background: var(--panel);
    padding-top: 16px;
    padding-bottom: calc(28px + env(safe-area-inset-bottom));
  }
  .sidebar-sync-status {
    display: none;
  }

  @media (display-mode: standalone) {
    /* PWA has no Safari toolbar, so the document-scroll model (needed only for
       Safari toolbar sampling) is not required here. Fixed app-shell: the document
       never scrolls, the timeline is the internal scroller, the dock stays pinned
       to the bottom and the keyboard simply overlays it. */
    html {
      height: 100lvh;
      overflow: hidden;
    }
    /* iOS reports the small viewport (svh/innerHeight = screen - top inset) as the
       layout viewport, so height:100% leaves the dock ~59px short of the screen
       bottom. The rendering surface is actually the full screen (vh = lvh = screenH).
       Size the body to 100lvh and make it a containing block (transform) so the fixed
       dock + dialogs anchor to the full-height body and reach the real screen bottom.
       position:fixed keeps the document from scrolling. */
    body {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100lvh;
      min-height: 0;
      overflow: hidden;
      overscroll-behavior: none;
      transform: translateZ(0);
    }
    .window,
    .app,
    .main {
      height: 100%;
      min-height: 0;
      overflow: hidden;
    }

    .timeline {
      padding-top: calc(56px + env(safe-area-inset-top));
      height: 100%;
      min-height: 0;
      overflow-y: auto;
      overflow-x: hidden;
      overscroll-behavior: contain;
    }

    .timeline-head {
      min-height: calc(56px + env(safe-area-inset-top));
      padding-top: env(safe-area-inset-top);
      padding-bottom: 0;
    }

    .timeline-head > div {
      position: static;
      transform: none;
    }

    .timeline-head .panel-toggle {
      margin-top: 0;
    }

    .app.search-view .timeline {
      padding-top: calc(118px + env(safe-area-inset-top, 0px));
    }

    .app.search-view .search-view-bar {
      top: calc(64px + env(safe-area-inset-top, 0px));
    }

    .detail {
      border-radius: var(--ios-corner) 0 0 var(--ios-corner);
    }

    .app.detail-open .detail {
      box-shadow: -3px 0 12px rgba(0, 0, 0, 0.12);
    }

    .sidebar {
      padding-top: calc(16px + env(safe-area-inset-top));
    }

    /* PWA drawer (standalone only — Safari box no longer a concern here):
       the pushed-back timeline peek reads as a floating card with a very
       faint white veil, rounded top + bottom left corners, and a light
       shadow. The fixed header and bottom bar are the panel's real top and
       bottom edges, so they carry the rounded corners; the bottom bar also
       slides with the panel (X-style) so it stays part of the card. */
    .app.sidebar-open .main,
    .app.sidebar-revealing .main,
    .app.sidebar-dragging .main,
    .app.sidebar-closing .main {
      height: 100dvh;
      min-height: 100dvh;
      overflow: hidden;
      border-top-left-radius: var(--ios-corner);
      border-bottom-left-radius: var(--ios-corner);
      box-shadow: -3px 0 12px rgba(0, 0, 0, 0.12);
    }

    /* Faint white veil across the whole shifted card: body, fixed header,
       and fixed bottom bar.
       Base: invisible. Open/revealing: opacity 1. During drag
       .sidebar-dragging disables the transition and --drawer-progress
       (0–1) overrides the opacity so the veil tracks the finger
       proportionally. Closing keeps only the card geometry, so the veil
       fades out immediately instead of waiting for the transform to end. */
    .main::after {
      content: "";
      display: block;
      position: absolute;
      inset: 0;
      z-index: 1;
      background: rgba(255, 255, 255, 0.4);
      pointer-events: none;
      border-top-left-radius: var(--ios-corner);
      border-bottom-left-radius: var(--ios-corner);
      opacity: 0;
      transition: opacity 220ms ease;
    }

    .timeline-head {
      overflow: hidden;
    }

    .timeline-head::after,
    .mobile-bottom-bar::after {
      content: "";
      display: block;
      position: absolute;
      inset: 0;
      z-index: 2;
      background: rgba(255, 255, 255, 0.4);
      pointer-events: none;
      opacity: 0;
      transition: opacity 220ms ease;
    }

    .timeline-head::after {
      border-top-left-radius: var(--ios-corner);
    }

    .app.sidebar-open .main::after,
    .app.sidebar-revealing .main::after,
    .app.detail-open .main::after,
    .app.quick-compose-open .main::after,
    .app.quick-compose-closing .main::after,
    .app.sidebar-open .timeline-head::after,
    .app.sidebar-revealing .timeline-head::after,
    .app.detail-open .timeline-head::after,
    .app.quick-compose-open .timeline-head::after,
    .app.quick-compose-closing .timeline-head::after,
    .app.sidebar-open .mobile-bottom-bar::after,
    .app.sidebar-revealing .mobile-bottom-bar::after,
    .app.detail-open .mobile-bottom-bar::after,
    .app.quick-compose-open .mobile-bottom-bar::after,
    .app.quick-compose-closing .mobile-bottom-bar::after {
      opacity: var(--drawer-progress, 1);
    }

    /* Sync the timeline veil fade with the quick-compose card slide (same
       duration + emphasized-decelerate curve) so the backdrop and panel
       settle together instead of the veil finishing ~80ms early. */
    .app.quick-compose-open .main::after,
    .app.quick-compose-open .timeline-head::after,
    .app.quick-compose-open .mobile-bottom-bar::after {
      transition: opacity 300ms cubic-bezier(0.05, 0.7, 0.1, 1);
    }

    .app.sidebar-closing .main::after,
    .app.sidebar-closing .timeline-head::after,
    .app.sidebar-closing .mobile-bottom-bar::after {
      transition-duration: 140ms;
    }

    .app.sidebar-dragging .main::after,
    .app.sidebar-dragging .timeline-head::after,
    .app.sidebar-dragging .mobile-bottom-bar::after {
      transition: none;
    }

    .app.detail-dragging .main::after,
    .app.detail-dragging .timeline-head::after,
    .app.detail-dragging .mobile-bottom-bar::after {
      transition: none;
    }

    .app.sidebar-open .timeline,
    .app.sidebar-revealing .timeline,
    .app.sidebar-dragging .timeline,
    .app.sidebar-closing .timeline {
      height: 100%;
      overflow-y: auto;
      border-top-left-radius: var(--ios-corner);
      border-bottom-left-radius: var(--ios-corner);
    }

    .app.sidebar-open .timeline-head,
    .app.sidebar-revealing .timeline-head,
    .app.sidebar-dragging .timeline-head,
    .app.sidebar-closing .timeline-head {
      border-top-left-radius: var(--ios-corner);
    }

    .app.sidebar-open .mobile-bottom-bar,
    .app.sidebar-revealing .mobile-bottom-bar,
    .app.sidebar-dragging .mobile-bottom-bar,
    .app.sidebar-closing .mobile-bottom-bar {
      background: #fff;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
    }

    .quick-compose-card,
    .quick-compose-card.qc-full {
      border-top-left-radius: var(--ios-corner);
      border-top-right-radius: var(--ios-corner);
    }

    .quick-compose-dialog.open .quick-compose-card {
      box-shadow: 0 -3px 12px rgba(0, 0, 0, 0.12);
    }
  }

  html.auth-boot,
  html.auth-boot body,
  html.auth-open,
  html.auth-open body,
  body.auth-open {
    width: 100%;
    height: 100vh;
    height: 100dvh;
    min-height: 100vh;
    min-height: 100dvh;
    overflow-x: hidden;
    overflow-y: hidden;
    background: var(--bg);
  }

  html.auth-boot body .window,
  html.auth-boot body .mobile-bottom-bar,
  body.auth-open .window,
  body.auth-open .mobile-bottom-bar {
    display: none !important;
  }

  body.auth-open .auth-dialog.open {
    position: fixed;
    inset: 0;
    z-index: auto;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    min-height: 0;
    padding: calc(18px + env(safe-area-inset-top)) 18px calc(18px + env(safe-area-inset-bottom));
    background: var(--bg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    overflow: hidden;
  }
}

@media (max-width: 520px) {
  :root {
    --avatar-size: 34px;
    --avatar-line-left: 16px;
    --memo-column-gap: 10px;
    --memo-action-gutter: 24px;
  }

  .timeline-head {
    margin-bottom: 14px;
  }

  .sub {
    display: none;
  }

  .quoted-source {
    grid-template-columns: 24px minmax(0, 1fr);
  }

  .avatar-sm {
    width: 24px;
    height: 24px;
    flex-basis: 24px;
  }
}
