:root {
  color-scheme: light;
  --ink: #171717;
  --ink-soft: #2a2a2a;
  --muted: #68645e;
  --line: #ddd8d0;
  --line-soft: #ebe6de;
  --surface: #fbfaf7;
  --page: #f5f2ec;
  --accent: #171717;
  --danger: #8b2424;
  --danger-line: #d4b4b4;
  --radius: 0.7rem;
  --radius-sm: 0.45rem;
  --space: clamp(1rem, 2.2vw, 1.6rem);
  --chrome-gap: clamp(1rem, 2.5vw, 1.75rem);
  --shell: min(48rem, calc(100% - 2 * var(--space)));
  --font: system-ui, -apple-system, "Segoe UI", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", sans-serif;
  --mono: ui-monospace, "Cascadia Code", "Segoe UI Mono", "Consolas", monospace;
  --bp-narrow: 40rem; /* narrow viewport; children read via getComputedStyle */
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
  height: 100%;
}

body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  font-family: var(--font);
  color: var(--ink-soft);
  background: var(--page);
  line-height: 1.5;
  overflow-wrap: anywhere;
  font-size: 1rem;
  -webkit-font-smoothing: antialiased;
}

/* WHY: chrome never scrolls; only .app-viewport scrolls.
   Logical list size must not equal DOM size (virtual window owns scale).
   Notes copy, not shared with the sibling app. */
.app-frame {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100dvh;
  max-height: 100dvh;
}

.app-chrome {
  flex: 0 0 auto;
  width: 100%;
  background: color-mix(in srgb, var(--page) 94%, var(--ink));
  border-bottom: 1px solid var(--line-soft);
}

.app-topbar {
  position: relative;
  display: flex;
  flex-wrap: nowrap; /* never line-wrap */
  align-items: center;
  justify-content: center;
  gap: 0.45rem 0.7rem;
  width: 100%;
  max-width: none;
  box-sizing: border-box;
  margin-inline: 0;
  min-height: 3.4rem; /* slight bump for logo */
  padding-block: 0.45rem;
  padding-inline: clamp(0.55rem, 1.1vw, 0.85rem);
}

/* Go Home: the logo and the "Notes" title are links to "/" that run goHome(). */
.app-topbar-home {
  position: absolute;
  left: clamp(0.55rem, 1.1vw, 0.85rem);
  top: 50%;
  transform: translateY(-50%);
  display: block;
  border-radius: var(--radius);
  z-index: 1;
}

.app-topbar-logo {
  display: block;
  width: auto;
  height: 3.15rem;
  max-height: 3.15rem;
  object-fit: contain;
  object-position: left center;
}

.app-title-link {
  color: inherit;
  text-decoration: none;
  border-radius: calc(var(--radius) * 0.6);
}

.app-topbar-home:focus-visible,
.app-title-link:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.app-topbar-cluster {
  display: flex;
  flex-wrap: nowrap; /* never line-wrap */
  align-items: center;
  justify-content: center;
  gap: 0.45rem 0.7rem;
  box-sizing: border-box;
  /* Almost stream/shell width; keep clear gap from far-left logo. */
  width: min(var(--shell), calc(100% - 8.5rem));
  min-width: 0;
  max-width: 100%;
}

/* Full-bleed top bar: logo sits on the absolute left of the chrome. */
.sidebars-shell > .app-chrome .app-topbar {
  width: 100%;
  max-width: none;
  margin-inline: 0;
  box-sizing: border-box;
  padding-inline: clamp(0.55rem, 1.1vw, 0.85rem);
}

/* Fixed to the real viewport corner — outside sidebars / app-frame. Hidden until corner hover/press. */
.mode-switch {
  position: fixed;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.28rem;
  margin: 0;
  /* Generous invisible hit target in the corner */
  min-width: 5.5rem;
  min-height: 2.4rem;
  padding: 0.55rem 0.7rem;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  opacity: 0;
  pointer-events: auto;
  transition: opacity 140ms ease;
}

.mode-switch:hover,
.mode-switch:focus-within,
.mode-switch.is-open {
  opacity: 1;
}

.mode-switch button {
  margin: 0;
  padding: 0.05rem 0.1rem;
  border: none;
  background: transparent;
  color: var(--muted);
  font: inherit;
  cursor: pointer;
}

.mode-switch button[aria-pressed="true"] {
  color: var(--ink);
  font-weight: 650;
}

.mode-switch-sep {
  color: var(--muted);
  opacity: 0.7;
}

.app-title {
  margin: 0;
  cursor: pointer;
  flex: 0 0 auto;
  min-width: 0;
  color: var(--ink);
  font-size: clamp(1.15rem, 2.2vw, 1.4rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
  white-space: nowrap;
}

.app-topbar-search {
  flex: 1 1 auto;
  width: auto;
  min-width: 0; /* shrink before wrap */
  max-width: none;
  display: flex;
  align-items: center;
  padding-block: 0;
}

.app-topbar-search input {
  width: 100%;
  min-width: 0;
  padding: 0.45rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-soft);
}

.app-topbar-search input::placeholder {
  color: color-mix(in srgb, var(--muted) 85%, var(--page));
}

.app-topbar-action {
  flex: 0 0 auto;
  flex-shrink: 0;
  padding-block: 0.45rem;
  padding-inline: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.app-topbar-note-actions {
  display: inline-flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.35rem;
}

.app-topbar-note-extra {
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease;
}

.app-topbar-note-actions:hover .app-topbar-note-extra,
.app-topbar-note-actions:focus-within .app-topbar-note-extra {
  opacity: 1;
  pointer-events: auto;
}

@media (hover: none), (pointer: coarse) {
  .app-topbar-note-extra {
    opacity: 1;
    pointer-events: auto;
  }
}

.app-viewport {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.app-viewport::-webkit-scrollbar {
  width: 0;
  height: 0;
}

button,
input,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
}

button:disabled {
  opacity: 0.5;
  cursor: default;
}

button:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.shell {
  width: var(--shell);
  margin-block: 0 var(--chrome-gap);
  margin-inline: auto;
  padding-inline: var(--space);
  padding-inline-end: calc(var(--space) + 0.25rem);
}

h2 {
  margin: 0;
  color: var(--ink);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.page-status {
  margin: 0 0 1.15rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--surface);
  color: var(--muted);
  font-size: 0.92rem;
}

.page-status.is-error {
  border-color: var(--danger-line);
  color: var(--danger);
}

.editor-dialog input,
.editor-dialog textarea {
  width: 100%;
  max-inline-size: 100%;
  padding: 0.78rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-soft);
}

.editor-dialog input,
.editor-dialog textarea {
  overflow-wrap: anywhere;
}

.editor-dialog textarea {
  resize: none;
  min-block-size: 8.5rem;
  max-block-size: min(34vh, 17rem);
  overflow-x: hidden;
  overflow-y: auto;
  font-family: var(--mono);
  line-height: 1.55;
  font-size: 0.95rem;
}

button {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.62rem 0.95rem;
  background: var(--surface);
  color: var(--ink-soft);
  font-weight: 500;
}

button.primary {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--surface);
}


/* Note-authored actions (Settings + stream HTML): New note look, smaller than top-bar New note. */
.stream-body button:not(.attach):not(.comment-delete):not(.comment-send):not(.note-carousel-button):not(.note-audio-toggle),
.note-focus-body button:not(.attach):not(.comment-delete):not(.comment-send):not(.note-carousel-button):not(.note-audio-toggle):not(.overlay-close):not(.stream-edit):not(.stream-expand),
.standalone-note-body button:not(.attach):not(.comment-delete):not(.comment-send):not(.note-carousel-button):not(.note-audio-toggle),
.stream-body a.primary-action,
.note-focus-body a.primary-action,
.standalone-note-body a.primary-action {
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 0.4rem 0.72rem;
  background: var(--accent);
  color: var(--surface);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1.25;
}

.stream-body a.primary-action,
.note-focus-body a.primary-action,
.standalone-note-body a.primary-action {
  display: inline-block;
  text-decoration: none;
}

.stream-body a.primary-action:visited,
.note-focus-body a.primary-action:visited,
.standalone-note-body a.primary-action:visited {
  color: var(--surface);
}

.stream-body button.danger,
.note-focus-body button.danger,
.standalone-note-body button.danger {
  border-color: var(--danger-line);
  background: transparent;
  color: var(--danger);
  font-weight: 500;
}

.stream-body button:disabled,
.note-focus-body button:disabled,
.standalone-note-body button:disabled {
  opacity: 0.5;
}

button.danger {
  border-color: var(--danger-line);
  color: var(--danger);
  background: transparent;
}

button.mode {
  padding-block: 0.38rem;
  padding-inline: 0.8rem;
  font-size: 0.9rem;
  font-weight: 500;
}

button.mode.active {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--surface);
}

#list {
  display: block;
}

.virtual-spacer-top,
.virtual-spacer-bottom {
  width: 100%;
  pointer-events: none;
}

.stream-note {
  position: relative;
  overflow-anchor: none;
  margin-block-end: 0.55rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "title meta"
    "body body"
    "comments comments";
  column-gap: 1rem;
  row-gap: 0.85rem;
  align-items: start;
  padding: clamp(1.05rem, 2.2vw, 1.35rem);
  padding-block-end: 0.45rem;
  border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 0.1rem);
  background: var(--surface);
  /* Never a scrollport — the Stream viewport scrolls; the note grows. */
  overflow: visible;
}

/* #hide-comments (body only): no Comments section; same card padding all round. */
.stream-note.is-comments-hidden {
  grid-template-areas:
    "title meta"
    "body body";
  padding-block-end: clamp(1.05rem, 2.2vw, 1.35rem);
}

/* #collapse (body only): the Stream card shows the beginning of the Note with a fade and a
   Read more / Show less control. The whole body stays rendered; only the clip changes.
   The fade is a mask, so it follows every theme and dark World without its own colours. */
.stream-note.is-collapsible {
  grid-template-areas:
    "title meta"
    "body body"
    "collapse collapse"
    "comments comments";
}

.stream-note.is-collapsible.is-comments-hidden {
  grid-template-areas:
    "title meta"
    "body body"
    "collapse collapse";
}

.stream-note.is-collapsible .stream-body.is-collapsed {
  max-block-size: min(24rem, 60vh);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 5rem), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 5rem), transparent);
}

.stream-note .stream-collapse-toggle {
  grid-area: collapse;
  justify-self: start;
  margin-block-start: -0.35rem;
}

/* ACTIVE-NOTE-NO-VISUAL-01: .is-active-note is state only (click, arrow keys, games).
   By default an active Note looks exactly like an inactive one; restyle it with
   .stream-note.is-active-note / .note-embed.is-active-note. Keyboard focus rings stay. */

.stream-note:focus-visible {
  border-color: var(--ink-soft, #404040);
  outline: 2px solid var(--ink, #171717);
  outline-offset: 2px;
}

.note-embed:focus-visible {
  outline: 2px solid var(--ink, #171717);
  outline-offset: 2px;
}

.note-preview-frame:focus {
  outline: none;
}

.note-preview-frame:focus-visible {
  outline: 2px solid var(--ink, #171717);
  outline-offset: 2px;
}


.stream-title {
  grid-area: title;
  margin: 0;
  color: var(--ink);
  font-size: clamp(1.3rem, 2.8vw, 1.65rem);
  font-weight: 700;
  letter-spacing: -0.018em;
  line-height: 1.22;
  overflow-wrap: anywhere;
}

.stream-meta {
  grid-area: meta;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.35rem 0.55rem;
  padding-block-start: 0.15rem;
}

.stream-tags {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.3rem;
  max-inline-size: 100%;
}

.pill,
.stream-tag,
.stream-edit,
.stream-expand {
  display: inline-block;
  margin: 0;
  padding: 0.18rem 0.5rem;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.pill,
.stream-edit,
.stream-expand {
  font-variant-numeric: normal;
  cursor: pointer;
  border-color: var(--line);
}

.pill:hover,
.pill:focus-visible,
.stream-edit:hover,
.stream-edit:focus-visible,
.stream-expand:hover,
.stream-expand:focus-visible {
  border-color: var(--ink-soft);
  color: var(--ink);
}

.pill:focus-visible,
.stream-edit:focus-visible,
.stream-expand:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}


/* Body host spans both grid columns; inner .stream-body fills the shell (Living Signal wrapper). */
.stream-body-shell {
  grid-area: body;
  min-inline-size: 0;
  max-inline-size: 100%;
}

.stream-body {
  /* Notes show their full content. Only the Stream viewport scrolls. */
  overflow: visible;
  max-inline-size: 100%;
  color: var(--ink-soft);
  font-size: 1.02rem;
  line-height: 1.58;
}

.stream-note .stream-body-shell > .stream-body {
  grid-area: auto;
}

/* REF-01: in-body note identity references (render-only) — styled in settings-stream-control-surface */
.note-ref { color: var(--ink); }
/* .note-ref.is-missing moved to settings-stream-control-surface */

/* REF-02: safe inline note embeds */
.note-embed {
  display: block;
  margin: 0.75rem 0;
  padding: 0.65rem 0.8rem;
  border: 1px solid color-mix(in srgb, var(--ink, #171717) 18%, transparent);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--page, #fff) 92%, var(--ink, #171717));
}
.note-embed.is-missing,
.note-embed.is-cycle {
  color: var(--ink-soft, #666);
  font-style: italic;
}
.note-embed-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.45rem 0.75rem;
  margin-bottom: 0.45rem;
}
/* .note-embed-title moved to settings-stream-control-surface */
.note-embed-id {
  color: var(--ink-soft, #666);
  font-size: 0.85em;
}
.note-embed-body {
  margin: 0;
}
.note-embed-body > :first-child { margin-top: 0; }
.note-embed-body > :last-child { margin-bottom: 0; }
.note-embed-cycle-inline {
  color: var(--ink-soft, #666);
  font-style: italic;
}


.comments {
  grid-area: comments;
  display: grid;
  gap: 0.7rem;
  margin-block-start: 0.15rem;
  padding-block-start: 1rem;
  border-block-start: 1px solid var(--line-soft);
}

.comments-heading {
  margin: 0;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.comments-list {
  display: grid;
  gap: 0.35rem;
}

.comments-list:empty {
  display: none;
}

.comments-empty {
  margin: 0;
  color: var(--muted);
  font-size: 0.88rem;
}

.comments-empty.is-error {
  color: var(--danger);
}

.comment {
  position: relative;
  display: block;
  padding: 0.4rem 2.1rem 0.4rem 0.65rem;
  border-top: 1px solid var(--line-soft);
}

.comment-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.65rem;
  min-width: 0;
}

.comment-delete {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: 0.3rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--ink);
  opacity: 0;
  pointer-events: none;
}

.comment:hover .comment-delete,
.comment:focus-within .comment-delete,
.comment-delete:focus-visible {
  opacity: 1;
  pointer-events: auto;
}

.comment-delete:hover,
.comment-delete:focus-visible {
  background: transparent;
  border: 0;
  color: var(--ink);
}

.comment-delete:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  opacity: 1;
  pointer-events: auto;
}

.comment-delete-icon {
  display: block;
  width: 1.05rem;
  height: 1.05rem;
}

@media (hover: none), (pointer: coarse) {
  .comment-delete {
    opacity: 0;
    pointer-events: none;
  }
  .comment:focus-within .comment-delete,
  .comment-delete:focus-visible,
  .comment-delete:active {
    opacity: 1;
    pointer-events: auto;
  }
}

.comment-time {
  flex: 0 0 auto;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.comment-body {
  flex: 1 1 12rem;
  margin: 0;
  min-width: 0;
  color: var(--ink-soft);
  font-size: 0.92rem;
  line-height: 1.35;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.comment-form {
  display: grid;
  gap: 0.35rem;
}

.comment-composer {
  position: relative;
  display: block;
}

.comment-composer textarea {
  width: 100%;
  max-inline-size: 100%;
  min-block-size: 3rem;
  padding: 0.75rem 3rem 0.75rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--page) 40%, var(--surface));
  color: var(--ink-soft);
  resize: none;
  overflow: hidden;
  field-sizing: content;
  font-size: 0.95rem;
  line-height: 1.45;
}

.comment-composer textarea::placeholder {
  color: color-mix(in srgb, var(--muted) 85%, var(--page));
}

.comment-send {
  position: absolute;
  inset-block-start: 0.45rem;
  inset-inline-end: 0.28rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
}

.comment-send:hover {
  color: var(--ink);
  background: color-mix(in srgb, var(--page) 75%, var(--surface));
  border-color: var(--line-soft);
}

.comment-send:focus-visible {
  color: var(--ink);
  background: color-mix(in srgb, var(--page) 75%, var(--surface));
  border-color: var(--line);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.comment-send:disabled {
  opacity: 0.4;
}

.comment-send-icon {
  display: block;
  flex: 0 0 auto;
  transform: translateY(-1px);
}

.comment-meta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.35rem 0.75rem;
  min-block-size: 1.1rem;
}

.comment-count {
  margin: 0;
  color: var(--muted);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.comment-form-error {
  margin: 0;
  margin-inline-start: auto;
  color: var(--danger);
  font-size: 0.86rem;
}

.stream-body > :first-child {
  margin-block-start: 0;
}

.stream-body > :last-child {
  margin-block-end: 0;
}

.stream-body pre {
  overflow: visible;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Rendered note content (code, preview) uses the body column, not a side grid cell. */
.stream-body :is(pre, .mermaid, .note-explicit, .note-preview-frame, .note-run-output) {
  box-sizing: border-box;
  width: 100%;
  max-inline-size: 100%;
  min-inline-size: 0;
}

dialog.app-overlay:not([open]) {
  display: none;
}

dialog.editor-dialog,
dialog.confirm-dialog {
  width: min(40rem, calc(100% - 1.25rem));
  overflow: hidden;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 0.1rem);
  background: var(--surface);
  color: var(--ink-soft);
}

/* WHY: size to content (fit-content). Do NOT put the same vh max on both
   dialog and form, browsers then stretch the dialog to the max and leave
   empty space under the footer. Cap only the dialog; form follows content. */
dialog.editor-dialog {
  display: flex;
  flex-direction: column;
  height: fit-content;
  max-block-size: calc(100dvh - 2 * var(--space));
  overflow: hidden;
  padding: 0;
}

.app-overlay::backdrop {
  background: color-mix(in srgb, var(--ink) 42%, transparent);
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
}

.overlay-close {
  position: absolute;
  inset-block-start: 0.55rem;
  inset-inline-end: 0.55rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  color: var(--muted);
}

.overlay-close:hover,
.overlay-close:focus-visible {
  color: var(--ink);
  border-color: var(--line);
  background: var(--surface);
}

.overlay-close:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.lightbox-dialog {
  position: relative;
  width: fit-content;
  max-width: calc(100vw - 2rem);
  max-height: calc(100dvh - 2rem);
  height: fit-content;
  margin: auto;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  overflow: visible;
}

.lightbox-dialog::backdrop {
  background: color-mix(in srgb, var(--ink) 48%, transparent);
}

dialog.note-focus-dialog {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(56rem, calc(100% - 1.25rem));
  height: fit-content;
  max-block-size: calc(100dvh - 2 * var(--space));
  margin: auto; /* vertical + horizontal center when shorter than the viewport */
  padding-block: clamp(0.95rem, 2.2vw, 1.45rem);
  padding-inline: clamp(0.85rem, 1.8vw, 1.25rem);
  border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 0.1rem);
  background: var(--surface);
  color: var(--ink-soft);
  /* One outer scrollbar when content exceeds the viewport; none when it fits. */
  overflow-x: hidden;
  overflow-y: auto;
}

.note-focus-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-block-end: 0.85rem;
  padding-inline-end: 2.6rem;
}

.note-focus-header .stream-title {
  font-size: clamp(1.35rem, 2.6vw, 1.75rem);
}

.note-focus-actions {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.35rem;
}

.note-focus-open {
  text-decoration: none;
}

.note-focus-body {
  flex: 0 0 auto;
  min-block-size: 0;
  overflow: visible;
}

.note-focus-body .stream-body,
.note-focus-body .note-explicit,
.note-focus-body .note-embed-body {
  overflow: visible;
  max-height: none;
}

/* Full natural height; avoid nested scrollports inside the overlay. */
.note-focus-body iframe,
.note-focus-body .note-preview-frame {
  width: 100%;
  border: 0;
  overflow: hidden;
}

/* New Tab / standalone: chrome-less body host (shared renderer; not a Mother card).
   Full viewport; no Stream max-width / card padding / shell chrome.
   Single HTML capability may fill via .is-html-fill (sandboxed iframe remains). */
html[data-view="standalone"],
html[data-view="standalone"] body {
  margin: 0;
  width: 100%;
  min-height: 100dvh;
  height: auto;
  overflow-x: hidden;
  overflow-y: auto;
  background: var(--page);
}

html[data-view="standalone"] .app-chrome,
html[data-view="standalone"] .mode-switch,
html[data-view="standalone"] .app-footer,
html[data-view="standalone"] #app-panels,
html[data-view="standalone"] .page-status {
  display: none !important;
}

html[data-view="standalone"] .app-frame,
html[data-view="standalone"] .app-viewport,
html[data-view="standalone"] .shell,
html[data-view="standalone"] .standalone-host {
  margin: 0;
  padding: 0;
  width: 100%;
  max-width: none;
  min-height: 100dvh;
  height: auto;
  border: none;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  overflow: visible;
  flex: 0 0 auto;
}

html[data-view="standalone"] .standalone-note-body {
  box-sizing: border-box;
  width: 100%;
  max-width: none;
  height: auto;
  min-height: 0;
  margin: 0;
  /* Readable inset for prose/capabilities — not a Stream card. */
  padding: clamp(0.75rem, 2.5vw, 1.25rem);
  overflow: visible;
  color: var(--ink-soft);
}

html[data-view="standalone"] .standalone-note-body > :first-child {
  margin-block-start: 0;
}

/* New Tab: media may use nearly the whole tab; the tab scrolls. */
html[data-view="standalone"] .standalone-note-body {
  --note-media-max-height: calc(100dvh - 2.5rem);
}

/* New Tab has no Stream column: one calm, centred reading column. Running text,
   separators, audio players and QR codes keep a readable measure on one axis; images,
   sheet music, code, tables and frames keep the full width (images stay centred). */
html[data-view="standalone"] .standalone-note-body :is(p, ul, ol, dl, blockquote, h1, h2, h3, h4, h5, h6, hr, .note-audio, .qr-code) {
  /* rem, not ch: headings and text share one column edge whatever their font size. */
  max-inline-size: 40rem;
  margin-inline: auto;
}

html[data-view="standalone"] .standalone-note-body:not(.is-html-fill) {
  padding-block: clamp(1rem, 4vw, 2.5rem);
}

html[data-view="standalone"] .standalone-note-body :is(h1, h2, h3) {
  margin-block-start: 2rem;
}

html[data-view="standalone"] .standalone-note-body .note-explicit {
  margin: 0;
  gap: 0;
}

html[data-view="standalone"] .standalone-note-body iframe,
html[data-view="standalone"] .standalone-note-body .note-preview-frame {
  display: block;
  border: 0;
  overflow: hidden;
}

html[data-view="standalone"] .standalone-note-body .note-explicit,
html[data-view="standalone"] .standalone-note-body .note-embed-body {
  overflow: visible;
  max-height: none;
}

/* Pure HTML capability as the only body content: fill viewport (iframe stays sandboxed). */
html[data-view="standalone"] .standalone-note-body.is-html-fill {
  padding: 0;
  min-height: 100dvh;
  height: 100dvh;
  overflow: hidden;
}

html[data-view="standalone"] .standalone-note-body.is-html-fill .note-explicit {
  height: 100%;
  min-height: 100dvh;
}

html[data-view="standalone"] .standalone-note-body.is-html-fill iframe.note-preview-frame {
  width: 100% !important;
  height: 100% !important;
  min-height: 100dvh;
}

html[data-view="standalone"] .standalone-error {
  margin: 1.25rem;
  color: var(--danger, #a11);
  font: 1rem var(--font);
}

html[data-view="standalone"].is-html-fill-doc,
html[data-view="standalone"].is-html-fill-doc body {
  overflow: hidden;
  height: 100dvh;
}

/* NEWTAB-LAYOUT-01: New Tab sections grouped by arrangeStandaloneLayout (order unchanged).
   Running text keeps the one reading column above. The hero (opening image, heading, text and
   player) and sheet music get a wider, still centred measure; narrow screens stay one column. */
html[data-view="standalone"] .standalone-note-body .standalone-hero {
  max-inline-size: 40rem;
  margin-inline: auto;
}

html[data-view="standalone"] .standalone-note-body .standalone-hero-cover .note-image {
  margin-block: 0 1.5rem;
}

html[data-view="standalone"] .standalone-note-body .standalone-hero-text > :first-child {
  margin-block-start: 0;
}

html[data-view="standalone"] .standalone-note-body .standalone-hero-text > :last-child {
  margin-block-end: 0;
}

html[data-view="standalone"] .standalone-note-body .standalone-hero-text h1 {
  font-size: clamp(1.6rem, 2.4vw, 2.1rem);
  line-height: 1.15;
  margin-block-end: 0.35rem;
}

html[data-view="standalone"] .standalone-note-body .standalone-hero-text h1 + p {
  margin-block-start: 0;
  color: var(--muted);
  font-size: 1.05rem;
}

@media (min-width: 60rem) {
  html[data-view="standalone"] .standalone-note-body .standalone-hero {
    display: grid;
    grid-template-columns: minmax(0, 34rem) minmax(20rem, 34rem);
    justify-content: center;
    align-items: center;
    gap: clamp(2rem, 4vw, 3.5rem);
    max-inline-size: 72rem;
    padding-block: 0.5rem 1rem;
  }

  html[data-view="standalone"] .standalone-note-body .standalone-hero-cover .note-image {
    margin: 0;
  }

  /* The cover column is the width limit here (about 1.6 times a 340 px hint); the image is
     still never enlarged beyond its natural size, cropped or taller than the view. */
  html[data-view="standalone"] .standalone-note-body .standalone-hero-cover img {
    max-inline-size: 100% !important;
  }

  html[data-view="standalone"] .standalone-note-body .standalone-hero-text > * {
    max-inline-size: none;
    margin-inline: 0;
  }
}

/* New Tab player: a little larger, with a clearer timeline that shows the played part.
   The volume slider keeps its normal look. Stream and Focus keep the compact player. */
html[data-view="standalone"] .standalone-note-body .note-audio {
  gap: 0.8rem;
  margin-block: 1.25rem;
  padding: 0.55rem 1.1rem 0.55rem 0.55rem;
}

html[data-view="standalone"] .standalone-note-body .note-audio-toggle {
  inline-size: 2.75rem;
  block-size: 2.75rem;
}

html[data-view="standalone"] .standalone-note-body .note-audio-toggle::before {
  inline-size: 0.9rem;
  block-size: 1rem;
  margin-inline-start: 0.2rem;
}

html[data-view="standalone"] .standalone-note-body .note-audio-toggle[data-playing="true"]::before {
  margin-inline-start: 0;
}

html[data-view="standalone"] .standalone-note-body .note-audio-seek {
  -webkit-appearance: none;
  appearance: none;
  box-sizing: border-box;
  block-size: 1.5rem;
  padding-block: 0.5625rem;
  border: 0;
  background-color: color-mix(in srgb, var(--ink) 16%, transparent);
  background-image: linear-gradient(var(--ink), var(--ink));
  background-repeat: no-repeat;
  background-size: 0 100%;
  background-origin: content-box;
  background-clip: content-box;
}

html[data-view="standalone"] .standalone-note-body .note-audio-seek::-webkit-slider-runnable-track {
  block-size: 0.375rem;
  background: transparent;
}

html[data-view="standalone"] .standalone-note-body .note-audio-seek::-moz-range-track {
  block-size: 0.375rem;
  background: transparent;
}

html[data-view="standalone"] .standalone-note-body .note-audio-seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  inline-size: 1rem;
  block-size: 1rem;
  margin-block-start: -0.3125rem;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--ink);
}

html[data-view="standalone"] .standalone-note-body .note-audio-seek::-moz-range-thumb {
  box-sizing: border-box;
  inline-size: 1rem;
  block-size: 1rem;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--ink);
}

html[data-view="standalone"] .standalone-note-body .note-audio-time {
  font-size: 0.9rem;
}

/* Sheet music: wider than the reading column, but centred and never the whole tab width.
   The wrapper sets the width because abcjs sizes the score from its parent. */
html[data-view="standalone"] .standalone-note-body .standalone-wide {
  max-inline-size: min(100%, 60rem);
  margin-inline: auto;
}

/* A paragraph right before a QR code sits next to the code, above its visible link. */
html[data-view="standalone"] .standalone-note-body .standalone-qr {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: 1.25rem;
  max-inline-size: 40rem;
  margin: 1rem auto;
}

html[data-view="standalone"] .standalone-note-body .standalone-qr > p {
  grid-column: 2;
  grid-row: 1;
  align-self: end;
  max-inline-size: none;
  margin: 0;
}

html[data-view="standalone"] .standalone-note-body .standalone-qr > .qr-code {
  display: contents;
}

html[data-view="standalone"] .standalone-note-body .standalone-qr .qr-svg {
  grid-column: 1;
  grid-row: 1 / span 2;
  inline-size: min(9.5rem, 32vw);
}

html[data-view="standalone"] .standalone-note-body .standalone-qr .qr-text {
  grid-column: 2;
  grid-row: 2;
  align-self: start;
  margin-block: 0.4rem 0;
  font-size: 0.95rem;
}

.lightbox-dialog img {
  display: block;
  width: auto;
  height: auto;
  max-width: calc(100vw - 2.5rem);
  max-height: calc(100dvh - 2.5rem);
  object-fit: contain;
  box-shadow: 0 0.4rem 1.4rem color-mix(in srgb, var(--ink) 22%, transparent);
  transform-origin: center center;
  touch-action: none;
  user-select: none;
  -webkit-user-drag: none;
  cursor: zoom-in;
  will-change: transform;
}

.lightbox-dialog img.is-zoomed {
  cursor: grab;
}

.lightbox-dialog img.is-panning {
  cursor: grabbing;
}

dialog.editor-dialog form {
  display: flex;
  flex-direction: column;
  flex: 0 1 auto;
  width: 100%;
  min-block-size: 0;
  max-height: none;
  overflow: hidden;
  padding: 0;
  gap: 0;
}

.confirm-dialog form {
  display: grid;
  gap: 0.9rem;
  padding: 1.2rem;
}

.editor-scroll {
  display: grid;
  gap: 0.95rem;
  padding: 1.2rem 1.2rem 0.75rem;
  overflow-x: hidden;
  overflow-y: auto;
  min-block-size: 0;
  flex: 0 1 auto;
}

.editor-footer {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 0.65rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 1.2rem 0.9rem;
  border-top: 1px solid var(--line);
}

.editor-dialog label.editor-created {
  display: inline-flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.5rem;
  margin-inline-start: auto;
  min-width: 0;
}

.editor-dialog .editor-created input[type="datetime-local"] {
  width: auto;
  max-inline-size: min(100%, 16.5rem);
  min-inline-size: 11.5rem;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.88rem;
  color-scheme: light;
}

.editor-dialog .editor-created input[type="datetime-local"]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.editor-footer > .error {
  flex: 1 1 100%;
}

.editor-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.mode-toggle {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}

.editor-dialog label {
  display: grid;
  gap: 0.35rem;
}

.editor-dialog label > span {
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 600;
}

.preview {
  min-block-size: 8rem;
  /* Grow with content; .editor-scroll is the only scrollport in the dialog. */
  overflow: visible;
  padding: 0.9rem 1rem;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--page) 55%, var(--surface));
}

.prose :is(h1, h2, h3, h4, h5, h6) {
  color: var(--ink);
  line-height: 1.25;
  margin-block: 1.05rem 0.45rem;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
}

/* One heading scale in Note text, below the Note title (the global h2 rule made h2 smaller than h3). */
.prose h1 { font-size: 1.32em; }
.prose h2 { font-size: 1.18em; }
.prose h3 { font-size: 1.06em; }
.prose h4 { font-size: 1em; }
.prose :is(h5, h6) { font-size: 0.94em; }

.prose :is(p, ul, ol, pre, blockquote, table) {
  margin-block: 0.75rem;
}

.prose pre {
  overflow: visible;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  padding: 0.8rem 0.9rem;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--page) 80%, var(--line));
  font-family: var(--mono);
  font-size: 0.88rem;
}

.prose code {
  font-family: var(--mono);
  font-size: 0.9em;
  overflow-wrap: anywhere;
}

.prose :not(pre) > code {
  padding: 0.08em 0.28em;
  border-radius: 0.28rem;
  background: color-mix(in srgb, var(--page) 72%, var(--line));
}

/* A quote reads as a quote: a quiet rule at the start, not a card. */
.prose blockquote {
  margin-inline: 0;
  padding-inline-start: 0.9rem;
  border-inline-start: 3px solid var(--line);
}
.prose blockquote > :first-child { margin-block-start: 0; }
.prose blockquote > :last-child { margin-block-end: 0; }

.prose table {
  width: 100%;
  max-inline-size: 100%;
  border-collapse: collapse;
}
.prose th,
.prose td {
  padding: 0.3rem 0.55rem;
  border-bottom: 1px solid var(--line-soft);
  overflow-wrap: anywhere;
  vertical-align: top;
}
/* Author alignment (|:---:|) stays; unaligned headers start like their cells. */
.prose th:not([align]) {
  text-align: start;
}

.prose .mermaid {
  margin-block: 1rem;
  max-inline-size: 100%;
  overflow: visible;
  text-align: center;
}

.prose .mermaid svg {
  max-inline-size: 100%;
  height: auto;
}

/* ABC sheet music: abcjs sizes the SVG to the width (responsive "resize"); ink follows the theme. */
.abc-notation {
  margin-block: 1rem;
  max-inline-size: 100%;
  color: var(--ink);
}

.abc-error {
  margin-block: 0.35rem 0.9rem;
  color: var(--danger);
  font-size: 0.88rem;
}

@media print {
  .abc-notation {
    color: #000;
    break-inside: avoid;
  }
}

.prose .katex-display {
  max-inline-size: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  padding-block: 0.15rem;
}

.prose .katex {
  font-size: 1.05em;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.form-status {
  margin: 0;
  margin-inline-start: auto;
  color: var(--muted);
  font-size: 0.88rem;
}

.form-status:empty {
  display: none;
}

/* Fixed tip for Copy ID — must not participate in .actions flex wrap. */
.copy-tip {
  position: fixed;
  z-index: 10000;
  margin: 0;
  padding: 0.28rem 0.55rem;
  border-radius: 0.35rem;
  background: color-mix(in srgb, var(--ink) 92%, transparent);
  color: var(--page);
  font-size: 0.78rem;
  line-height: 1.2;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 0.15rem 0.45rem color-mix(in srgb, var(--ink) 25%, transparent);
}

.attach-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1rem;
  margin-block: 0.25rem 0.15rem;
}

/* Hidden attach chrome must not reserve flex/grid space (ghost height). */
.attach-row[hidden],
#edit-pane[hidden] .attach-row {
  display: none !important;
  margin: 0;
  padding: 0;
  min-block-size: 0;
}

.image-status:empty {
  display: none;
}

button.attach {
  border-style: dashed;
  border-color: color-mix(in srgb, var(--line) 70%, var(--muted));
  color: var(--muted);
  font-weight: 500;
}

button.attach:hover,
button.attach:focus-visible {
  border-color: var(--ink-soft);
  color: var(--ink);
}

.image-status {
  margin: 0;
  color: var(--muted);
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}

/* Visual presentation, media (docs/text-and-capabilities.md#visual-presentation).
   An image prefers the body width, is shown whole and scales down only to fit the
   usable height of its view: width-limited while it fits, height-limited (centred)
   otherwise. Never cropped, stretched or enlarged past its natural size.
   --note-media-max-height is an internal layout helper per view, not a theme token. */
.prose {
  /* Stream and Settings: viewport minus top bar, Note header, card padding and a small margin. */
  --note-media-max-height: calc(100dvh - 9rem);
}

/* Focus: dialog margins, its padding and the Note header. */
.note-focus-body {
  --note-media-max-height: calc(100dvh - 2 * var(--space) - 6.5rem);
}

/* Published page: page margin, Note title and card padding. */
body[data-page="published"] .prose {
  --note-media-max-height: calc(100dvh - 7.5rem);
}

/* Editor preview (the draft pane in the edit dialog) keeps a compact height.
   A Note carousel/slideshow uses the same per-view media height as a single image. */
.preview,
.preview .note-carousel {
  --note-media-max-height: min(36vh, 18rem);
}

.prose :is(img, video, iframe) {
  max-inline-size: 100%;
}

.prose :is(img, video) {
  height: auto;
  max-block-size: var(--note-media-max-height);
  object-fit: contain;
}

.note-image {
  margin: 1rem 0;
  padding: 0;
  max-inline-size: 100%;
}

.note-image img {
  display: block;
  margin-inline: auto;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--page) 70%, var(--surface));
  cursor: zoom-in;
}

.prose hr {
  margin-block: 2rem;
  border: 0;
  border-block-start: 1px solid var(--line);
}

/* Uploaded audio: a small theme-aware player over a hidden <audio>. Only Play/Pause, the
   seek timeline (no buffered bar), the time and the volume; it narrows with the body. */
.note-audio {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  box-sizing: border-box;
  inline-size: 100%;
  margin: 1rem 0;
  padding: 0.4rem 0.8rem 0.4rem 0.4rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
}

.note-audio audio {
  display: none;
}

.note-audio-toggle {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--surface);
  cursor: pointer;
}

.note-audio-toggle:hover {
  opacity: 0.85;
}

.note-audio-toggle::before {
  content: "";
  display: block;
  inline-size: 0.75rem;
  block-size: 0.85rem;
  margin-inline-start: 0.15rem;
  background: currentColor;
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

.note-audio-toggle[data-playing="true"]::before {
  margin-inline-start: 0;
  background: linear-gradient(to right, currentColor 0 35%, transparent 35% 65%, currentColor 65% 100%);
  clip-path: none;
}

.note-audio :is(.note-audio-toggle, input):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.note-audio input[type="range"] {
  min-inline-size: 0;
  margin: 0;
  accent-color: var(--ink);
  cursor: pointer;
}

.note-audio-seek {
  flex: 1 1 auto;
}

.note-audio-time {
  flex: none;
  color: var(--muted);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.note-audio-volume {
  flex: 0 1 5.5rem;
  inline-size: 5.5rem;
}

@media (max-width: 30rem) {
  .note-audio {
    gap: 0.45rem;
  }

  .note-audio-volume {
    flex-basis: 3.5rem;
  }
}

/* ```qr fence: dark modules on white in every theme; at most about 200 px, narrower with the body. */
.qr-code {
  margin-block: 1rem;
}

.qr-svg {
  display: block;
  inline-size: min(100%, 200px);
  block-size: auto;
  background: #ffffff;
}

.qr-text {
  margin-block: 0.4rem 0;
  color: var(--muted);
  font-size: 0.85rem;
  overflow-wrap: anywhere;
  user-select: text;
}

.qr-error {
  margin-block: 0.35rem 0.9rem;
  color: var(--danger);
  font-size: 0.88rem;
}

/* FILE-REF-01: a files .html page is a whole page. Its frame fills the view's usable height
   (the same per-view height as media) and grows past it with its content; New Tab fills the tab.
   The placeholder keeps that room while the file loads, so the Stream does not jump. */
.note-file,
.prose .note-file-frame {
  min-block-size: var(--note-media-max-height);
}

.note-file-error {
  margin-block: 0.35rem 0.9rem;
  color: var(--danger);
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}

.note-carousel {
  margin-block: 1rem;
  max-inline-size: 100%;
  min-inline-size: 0;
}

.note-carousel-viewport {
  overflow: hidden;
  max-inline-size: 100%;
  touch-action: pan-y pinch-zoom;
}

/* Spacing sits before each slide and outside the viewport, so a full-width slide
   keeps the whole body width and no edge of its neighbour shows. */
.note-carousel-container {
  display: flex;
  margin-inline-start: -1rem;
  touch-action: pan-y pinch-zoom;
}

/* The slide row is as tall as its tallest slide, so changing slides never moves the
   controls; a shorter slide is centred in that stage. */
.note-carousel-slide {
  box-sizing: border-box;
  flex: 0 0 100%;
  min-inline-size: 0;
  max-inline-size: 100%;
  padding-inline-start: 1rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: center;
}

.note-carousel .note-image {
  margin: 0;
}

/* The controls below the slide are the slideshow's own chrome: slide plus controls
   fit the view's usable height. The editor preview keeps its compact cap. */
.note-carousel img {
  max-block-size: calc(var(--note-media-max-height) - 3.5rem);
}

.preview .note-carousel img {
  max-block-size: var(--note-media-max-height);
}

.note-carousel-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.45rem 0.7rem;
  margin-block-start: 0.7rem;
}

.note-carousel-button {
  padding-block: 0.28rem;
  padding-inline: 0.7rem;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--muted);
}

.note-carousel-button:disabled {
  opacity: 0.4;
  cursor: default;
}

.note-carousel-indicator {
  margin: 0;
  color: var(--muted);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.empty {
  margin: 0;
  padding: 1.5rem 1.15rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--muted);
  text-align: center;
  font-size: 0.95rem;
}

.empty.is-error {
  border-style: solid;
  border-color: var(--danger-line);
  color: var(--danger);
}

.error {
  margin: 0;
  color: var(--danger);
  min-block-size: 0;
  font-size: 0.92rem;
  overflow-wrap: anywhere;
}

.error:empty {
  display: none;
}

[hidden] {
  display: none !important;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 40rem) {
  .stream-note {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "title"
      "meta"
      "body"
      "comments";
    row-gap: 0.7rem;
  }

  .stream-meta {
    justify-content: flex-start;
  }

  .editor-dialog textarea {
    min-block-size: 6.5rem;
    max-block-size: min(34vh, 17rem);
  }

  .form-status {
    margin-inline-start: 0;
    flex: 1 1 100%;
  }

}


/* Top bar: hide logo first, then tighten cluster — never wrap. */
@media (max-width: 50rem) {
  .app-topbar-home {
    display: none;
  }

  .app-topbar-cluster {
    width: min(var(--shell), 100%);
  }
}

@media (max-width: 34rem) {
  .app-topbar {
    gap: 0.35rem 0.5rem;
    padding-inline: 0.45rem;
  }

  .app-topbar-cluster {
    gap: 0.35rem 0.5rem;
  }

  .app-title {
    font-size: 1.05rem;
  }

  .app-topbar-search input {
    padding: 0.38rem 0.55rem;
  }

  .app-topbar-action {
    padding-block: 0.38rem;
    padding-inline: 0.65rem;
  }
}

@media (max-width: 26rem) {
  /* Last resort: slight scale — still one row, no wrap. */
  .app-topbar-cluster {
    transform: scale(0.9);
    transform-origin: center center;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

.note-explicit {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.45rem;
  margin-block: 0.2rem 0;
}

/* Starts at 0; content height is applied from notes:frame-size (natural content size). */
.note-preview-frame {
  box-sizing: border-box;
  width: 100%;
  height: 0;
  border: 0;
  background: transparent;
  display: block;
  overflow: hidden;
}


.note-source-hidden {
  display: none !important;
}

.note-run-output {
  width: 100%;
  margin: 0;
  white-space: pre-wrap;
  font: 0.85rem ui-monospace, Consolas, monospace;
}

.app-footer {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.35rem var(--space) 0.65rem;
  color: var(--muted);
  font-size: 0.78rem;
  text-align: center;
}

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


body[data-page="published"] {
  background: var(--page);
}

.published-page {
  box-sizing: border-box;
  width: min(48rem, 100%);
  margin: 2rem auto 3rem;
  padding: 0 1.25rem;
}

/* === settings-stream-control-surface === */
/* Links in note bodies: near-black/text tokens, permanent subtle underline, no purple visited. */
.prose a,
.stream-body a,
.note-focus-body a,
.standalone-note-body a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-offset: 0.14em;
  text-decoration-color: color-mix(in srgb, var(--ink) 34%, transparent);
}

.prose a:visited,
.stream-body a:visited,
.note-focus-body a:visited,
.standalone-note-body a:visited {
  color: var(--ink);
  text-decoration-color: color-mix(in srgb, var(--ink) 34%, transparent);
}

.prose a:hover,
.stream-body a:hover,
.note-focus-body a:hover,
.standalone-note-body a:hover {
  color: var(--ink);
  text-decoration-color: var(--ink);
}

.prose a:focus-visible,
.stream-body a:focus-visible,
.note-focus-body a:focus-visible,
.standalone-note-body a:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Identity refs / embed titles: same calm ink, never blue fallback. */
.note-ref {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 0.12em;
  text-decoration-color: color-mix(in srgb, var(--ink) 34%, transparent);
  cursor: pointer;
}

.note-ref:hover {
  text-decoration-color: var(--ink);
}

.note-ref:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.note-ref.is-missing {
  color: var(--muted);
  text-decoration: underline dotted;
  text-decoration-color: color-mix(in srgb, var(--muted) 55%, transparent);
  cursor: default;
}

.note-embed-title {
  border: 0;
  background: none;
  padding: 0;
  color: var(--ink);
  font: inherit;
  font-weight: 650;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.12em;
  text-decoration-color: color-mix(in srgb, var(--ink) 34%, transparent);
}

.note-embed-title:hover {
  text-decoration-color: var(--ink);
}

.note-embed-title:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* Reuse outline look as secondary (Settings + stream HTML classes). */
button.secondary {
  border-color: var(--line);
  background: var(--surface);
  color: var(--ink-soft);
  font-weight: 500;
}

button.secondary:hover,
button.secondary:focus-visible {
  border-color: var(--ink-soft);
  color: var(--ink);
}

.stream-body button.secondary,
.note-focus-body button.secondary,
.standalone-note-body button.secondary {
  border-color: var(--line);
  background: var(--surface);
  color: var(--ink-soft);
  font-weight: 500;
}

/* Settings stream: one calm control surface (does not redesign ordinary Stream). */
body[data-notes-view="settings"] .settings-stream .prose h2 {
  margin-block: 1.15rem 0.4rem;
  font-size: 1.12rem;
  font-weight: 650;
  letter-spacing: -0.02em;
}

body[data-notes-view="settings"] .settings-stream .prose h3 {
  margin-block: 0.95rem 0.35rem;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--ink);
}

body[data-notes-view="settings"] .settings-stream .prose blockquote {
  margin-block: 0.7rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--line-soft);
  border-inline-start: 3px solid var(--line);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--surface) 88%, var(--page));
  color: var(--ink-soft);
}

body[data-notes-view="settings"] .settings-stream .prose blockquote > :first-child {
  margin-block-start: 0;
}

body[data-notes-view="settings"] .settings-stream .prose blockquote > :last-child {
  margin-block-end: 0;
}

body[data-notes-view="settings"] .settings-stream .prose hr {
  border: 0;
  border-top: 1px solid var(--line-soft);
  margin-block: 0.95rem;
}

body[data-notes-view="settings"] .settings-stream .prose :is(ul, ol) {
  margin-block: 0.55rem;
  padding-inline-start: 1.2rem;
}

body[data-notes-view="settings"] .settings-stream .prose li {
  margin-block: 0.18rem;
}

body[data-notes-view="settings"] .settings-stream .prose :not(pre) > code {
  padding: 0.08em 0.28em;
  border-radius: 0.28rem;
  background: color-mix(in srgb, var(--page) 72%, var(--line));
  color: var(--ink);
  font-size: 0.88em;
}

body[data-notes-view="settings"] .settings-stream .prose table {
  width: 100%;
  max-inline-size: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

body[data-notes-view="settings"] .settings-stream .prose th,
body[data-notes-view="settings"] .settings-stream .prose td {
  padding: 0.28rem 0.55rem;
  border-bottom: 1px solid var(--line-soft);
  text-align: start;
  vertical-align: top;
  overflow-wrap: anywhere;
}

body[data-notes-view="settings"] .settings-stream .prose th {
  color: var(--muted);
  font-weight: 550;
  white-space: nowrap;
}

body[data-notes-view="settings"] .settings-stream .prose .mermaid,
body[data-notes-view="settings"] .settings-stream .prose img {
  max-inline-size: 100%;
  height: auto;
}

body[data-notes-view="settings"] .settings-stream .stream-note,
body[data-notes-view="settings"] .settings-stream .stream-body,
body[data-notes-view="settings"] .settings-stream .note-explicit,
body[data-notes-view="settings"] .settings-stream .note-preview-frame {
  max-inline-size: 100%;
  overflow-x: hidden;
}

body[data-notes-view="settings"] .settings-stream .prose a {
  overflow-wrap: anywhere;
  word-break: break-word;
}

@media (prefers-reduced-motion: reduce) {
  .mode-switch {
    transition: none;
  }
}

/* Necessity pass 2026-10-09: remove shapes without a reason (see UI-NECESSITY-REVIEW-2026-10-09.md). */
/* Tags are non-interactive metadata: plain muted text, no oval. */
.stream-tag {
  padding: 0;
  border: 0;
  border-radius: 0;
}

/* Focus dialog close sits on a plain surface: no resting circle (lightbox keeps it over images). */
.note-focus-dialog .overlay-close {
  background: transparent;
}

.note-focus-dialog .overlay-close:hover,
.note-focus-dialog .overlay-close:focus-visible {
  border-color: transparent;
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}

.overlay-close:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* Carousel prev/next: same pattern as calendar chevrons, text with invisible hit area. */
.note-carousel-button {
  border-color: transparent;
  background: transparent;
}

.note-carousel-button:hover:not(:disabled) {
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}

/* ==== ELEGANT-01: small, calm refinements (typography, touch, narrow screens) ==== */

/* Calmer line breaks where the browser supports it: balanced headings, no lone last words.
   Text, order and wrapping rules are unchanged; unsupported browsers ignore these lines. */
.stream-title,
.prose :is(h1, h2, h3, h4, h5, h6) {
  text-wrap: balance;
}

.prose :is(p, li, blockquote, td) {
  text-wrap: pretty;
}

/* Code keeps its own indentation, in a narrower step that suits phones. */
.prose pre {
  tab-size: 2;
}

/* Narrow screens: the Stream card uses the same calm 0.75rem edge as New Tab, so the text
   column is wider and Stream reads like New Tab. The card grid (minmax(0, 1fr)) is unchanged. */
@media (max-width: 40rem) {
  :root {
    --space: 0.75rem;
  }
}

/* Touch screens: the small pills (Edit, Focus, expand) and the dialog close button get a
   44 px hit area. The pills look the same; only the invisible target grows. */
@media (pointer: coarse) {
  .pill,
  .stream-edit,
  .stream-expand {
    position: relative;
  }

  .pill::after,
  .stream-edit::after,
  .stream-expand::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    inline-size: max(100%, 44px);
    block-size: max(100%, 44px);
    transform: translate(-50%, -50%);
  }

  .overlay-close {
    width: 2.75rem;
    height: 2.75rem;
  }
}

/* ==== LAN guest role (server-enforced; this only hides controls a guest cannot use) ==== */
html.role-guest #new-note,
html.role-guest #export-note,
html.role-guest #import-note,
html.role-guest #mode-switch,
html.role-guest .stream-edit:not(.stream-expand),
html.role-guest .comment-delete,
html.role-guest .note-run,
html.role-guest #delete {
  display: none !important;
}

/* Read-only LAN guests: hide the comment composer (server refuses POST anyway). */
html.role-guest-readonly .comment-form {
  display: none !important;
}

/* Notes Public (PHP hosting adapter): a capability this host does not have; the Note text is kept. */
.public-unsupported {
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border-left: 3px solid #b45309;
  background: rgba(180, 83, 9, 0.08);
  font-size: 0.9rem;
}

/* Notes Public (PHP hosting adapter): Export note / Import note in grey; New note stays black. */
html:has(meta[name="notes-profile"][content="public"]) #export-note,
html:has(meta[name="notes-profile"][content="public"]) #import-note {
  border-color: var(--muted);
  background: var(--muted);
  color: var(--surface);
}

/* Notes Public: Export/Import sit OUTSIDE the centred header group (Notes + search + New note), to the right
   of New note, so the group stays centred over the Stream exactly as without them. The host page wraps the two
   buttons in .public-note-extras (PHP adapter only). Narrow screens: back in the row, as before. */
.public-note-extras {
  display: contents;
}

@media (min-width: 60rem) {
  html:has(meta[name="notes-profile"][content="public"]) .app-topbar-cluster {
    width: min(var(--shell), calc(100% - 2 * 16.5rem)); /* symmetric room for the extras on the right */
  }

  html:has(meta[name="notes-profile"][content="public"]) .app-topbar-note-actions {
    position: relative;
  }

  html:has(meta[name="notes-profile"][content="public"]) .public-note-extras {
    position: absolute;
    left: calc(100% + 0.35rem);
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    white-space: nowrap;
  }
}
