/* ============================================================
   mobile.css — MathematiX Mobile app shell.
   Design ported from mobile/New Mobile/mathematix-mobile.html:
   paper canvas, Spectral display type, mint accents, a gradient
   primary action, and a note-scoped chat over a drifting aura.
   Layout is full-bleed: each .mb-view fills the viewport and owns
   its own header. main.js publishes --app-h/--app-top from
   visualViewport minus the --kb-inset that keyboard-inset.js
   measures, and <body> is fixed to them, so the keyboard simply
   shrinks the app — no transforms, nothing to mis-position.
   ============================================================ */

:root {
  /* class palette — same values as app/app.css (store.colorVar emits var(--c-*)) */
  --c-green: #1c7c54; --c-amber: #b9892f; --c-plum: #7a557e;
  --c-sky: #2f6e9e; --c-rose: #a8516b; --c-teal: #2c8079;

  /* The 0px fallbacks matter: without them, a browser that does not know
     env() leaves the variable invalid, and every `calc(var(--safe-t) + 14px)`
     that reads it becomes invalid at computed-value time — which drops the
     whole padding declaration rather than just the inset. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  /* surfaces */
  --mb-bg: #f6f4ec;
  --mb-card: #ffffff;
  --mb-card-2: #fbfaf4;
  --mb-line: #e3dfd1;
  --mb-line-soft: #ece8db;
  /* ink */
  --mb-ink: #16201a;
  --mb-soft: #4c574f;
  --mb-faint: #828a82;
  /* accent */
  --mb-accent: #1c7c54;
  --mb-deep: #145c3d;
  --mb-mint: #e8f1ea;
  --mb-mint-line: #cfe3d6;
  --mb-danger: #b3463c;
  /* the gradient used by every primary action */
  --mb-flow: linear-gradient(105deg,#287e68 0%,#319b7c 30%,#347f91 55%,#319b7c 78%,#287e68 100%);

  --r-sm: 11px; --r-md: 14px; --r-lg: 16px; --r-sheet: 24px;
  --ease: cubic-bezier(.22,1,.36,1);
  --sh-card: 0 1px 2px rgba(16,40,28,.05), 0 2px 6px rgba(16,40,28,.04);
  --sh-pop: 0 30px 70px -30px rgba(16,40,28,.32), 0 8px 24px -12px rgba(16,40,28,.14);
}
body.dark {
  --mb-bg: #0e1a14;
  --mb-card: #14241c;
  --mb-card-2: #101d16;
  --mb-line: #23392e;
  --mb-line-soft: #1b2e24;
  --mb-ink: #e8f0ea;
  --mb-soft: #9fb3a6;
  --mb-faint: #7d9186;
  --mb-accent: #3fa776;
  --mb-deep: #7fd0a6;
  --mb-mint: rgba(63,167,118,.14);
  --mb-mint-line: rgba(63,167,118,.30);
  --mb-danger: #d97b6c;
  --sh-card: 0 1px 2px rgba(0,0,0,.3), 0 2px 6px rgba(0,0,0,.2);
  --sh-pop: 0 30px 70px -30px rgba(0,0,0,.7), 0 8px 24px -12px rgba(0,0,0,.5);
}

/* The selected accent is shared with the website and desktop notebook.
   Surface contrast stays stable; only the expressive brand scale changes. */
html[data-accent="forest"] body {
  --mb-accent: #1c7c54; --mb-deep: #145c3d;
  --mb-mint: #e8f1ea; --mb-mint-line: #cfe3d6;
  --mb-flow: linear-gradient(105deg,#226f5b 0%,#319b7c 32%,#347f91 58%,#319b7c 80%,#226f5b 100%);
}
html[data-accent="ocean"] body {
  --mb-accent: #256f92; --mb-deep: #185572;
  --mb-mint: #e7f1f5; --mb-mint-line: #c9e0e9;
  --mb-flow: linear-gradient(105deg,#235d86 0%,#2f8ba8 34%,#577db3 62%,#2f8ba8 82%,#235d86 100%);
}
html[data-accent="violet"] body {
  --mb-accent: #7657a6; --mb-deep: #5b3e89;
  --mb-mint: #f0ebf7; --mb-mint-line: #ddcfed;
  --mb-flow: linear-gradient(105deg,#654690 0%,#9169bd 34%,#a35993 64%,#9169bd 82%,#654690 100%);
}
html[data-accent="sunset"] body {
  --mb-accent: #bd5a3d; --mb-deep: #91412d;
  --mb-mint: #f8ebe5; --mb-mint-line: #efd3c7;
  --mb-flow: linear-gradient(105deg,#a84b36 0%,#d16f4d 34%,#b96872 64%,#d16f4d 82%,#a84b36 100%);
}
html.dark[data-accent="forest"] body { --mb-accent: #3fa776; --mb-deep: #7fd0a6; --mb-mint: rgba(63,167,118,.14); --mb-mint-line: rgba(63,167,118,.30); }
html.dark[data-accent="ocean"] body  { --mb-accent: #5badd0; --mb-deep: #93d1e8; --mb-mint: rgba(91,173,208,.14); --mb-mint-line: rgba(91,173,208,.30); }
html.dark[data-accent="violet"] body { --mb-accent: #ad8be0; --mb-deep: #cfb8ef; --mb-mint: rgba(173,139,224,.14); --mb-mint-line: rgba(173,139,224,.30); }
html.dark[data-accent="sunset"] body { --mb-accent: #ed8d6f; --mb-deep: #f5baa5; --mb-mint: rgba(237,141,111,.14); --mb-mint-line: rgba(237,141,111,.30); }

/* The app is pinned to the VISUAL viewport, never the layout viewport.
   Android/iOS browsers report window.innerHeight (and resolve 100dvh) against
   the largest viewport — toolbar hidden — while visualViewport.height is what
   you can actually see. Sizing to the former makes the page taller than the
   screen, so the whole document scrolls and headers slide away. main.js
   publishes --app-h/--app-top from visualViewport; body is fixed to them.
   In-app WebViews (Instagram, Facebook, TikTok) will not even do that much —
   they never resize for the keyboard — so main.js also subtracts the
   --kb-inset that assets/js/keyboard-inset.js measures for those browsers.
   Note: NO transform on body — that would make .sheet/.drawer (position:fixed)
   resolve against body instead of the viewport. */
html { height: 100%; overflow: hidden; overscroll-behavior: none; }
[hidden] { display: none !important; }
/* Border-box everywhere. Without it `width: 100%` plus padding is wider than
   its parent, and the phone gets a horizontal scrollbar it can never scroll
   away: the search field and every class card used to hang ~26px past the
   right edge, clipping "4 notes" off the end of each row. Nine rules already
   set this by hand, which is the tell that it belongs at the top. */
*, *::before, *::after { box-sizing: border-box; }
/* …except inside KaTeX, which is the one thing here that genuinely wants
   content-box: its rules, fraction bars, radical tails and strut heights are
   laid out in em with borders that are meant to ADD to the box. Folding those
   borders inward thins the fraction line and shortens the radical. */
.katex, .katex *, .katex *::before, .katex *::after { box-sizing: content-box; }
body.mb-body {
  margin: 0;
  position: fixed;
  left: 0; right: 0;
  top: var(--app-top, 0px);
  height: var(--app-h, 100dvh);
  overflow: hidden;
  overscroll-behavior: none;
  background: var(--mb-bg);
  color: var(--mb-ink);
  font-family: 'Hanken Grotesk', -apple-system, system-ui, sans-serif;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
  /* No double-tap-to-zoom. A zoomed page is the one state this shell cannot
     hold still in — the visual viewport shrinks and pans under the finger, and
     the app re-measures on every frame of it. `manipulation` keeps panning and
     keeps deliberate pinch-zoom (so this is not an accessibility trade); it
     only drops the accidental gesture, which on a screen full of tappable
     rows is the one people trigger by mistake. */
  touch-action: manipulation;
}
button { font-family: inherit; cursor: pointer; border: 0; background: none; color: inherit; }
.spacer { flex: 1; min-width: 0; }

/* ============ views ============ */
.mb-view {
  position: absolute; inset: 0;
  display: none; flex-direction: column; min-height: 0;
  overflow: hidden;
  overflow: clip; /* Decorative aura must not expand the fixed shell. */
  background: var(--mb-bg);
}
.mb-view.is-active { display: flex; }

/* Mobile scrolling stays fully functional, but persistent desktop-style rails
   (notably Chromium/WebView in landscape and high-contrast scrollbar modes)
   should not cut bright gutters through the app chrome. */
.hm-body, .thread, .reader, .drawer__list, .note-move-tray__list,
.sheet__card, .pop__list, .queue, .shots__strip {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.hm-body::-webkit-scrollbar, .thread::-webkit-scrollbar, .reader::-webkit-scrollbar,
.drawer__list::-webkit-scrollbar, .note-move-tray__list::-webkit-scrollbar,
.sheet__card::-webkit-scrollbar, .pop__list::-webkit-scrollbar,
.queue::-webkit-scrollbar, .shots__strip::-webkit-scrollbar {
  width: 0; height: 0; display: none;
}

/* shared round icon button in headers */
.icon-btn {
  width: 44px; height: 44px; flex: none;
  border-radius: var(--r-sm);
  display: grid; place-items: center;
  color: var(--mb-faint);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.icon-btn:active { background: var(--mb-mint); color: var(--mb-deep); }
.icon-btn svg { width: 19px; height: 19px; }

/* sync dot: mirrors persist.js sync state */
.mb-sync {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--mb-faint); flex: none;
  transition: background .3s var(--ease);
}
.mb-sync[data-state="saved"] { background: var(--mb-accent); }
.mb-sync[data-state="saving"] { background: var(--c-amber); }
.mb-sync[data-state="error"] { background: var(--mb-danger); }

/* ============================================================
   HOME
   ============================================================ */
.hm-top {
  flex: none;
  padding: calc(var(--safe-t) + 14px) 18px 12px;
  display: flex; align-items: center; gap: 8px;
  background: color-mix(in srgb, var(--mb-card-2) 86%, transparent);
  /* Safari still needs the prefix. Without it the header is simply a
     translucent panel on iOS and the list scrolls visibly through it. */
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid var(--mb-line-soft);
}
.hm-brand {
  font-family: Spectral, Georgia, serif;
  font-size: 21px; font-weight: 500; letter-spacing: -.02em;
}
.hm-brand em { color: var(--mb-accent); font-style: italic; }
.hm-avatar {
  width: 44px; height: 44px; flex: none;
  border-radius: 50%;
  background: var(--mb-accent); color: #fff;
  display: grid; place-items: center;
  font-weight: 600; font-size: 13px;
}
.hm-body {
  flex: 1; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 16px 18px 24px;
}

/* Ask Lemma — Home's entry into the global conversation. Without it the only
   way into chat is opening a note, which strands the note-less first run. */
.hm-dock {
  flex: none; position: relative; z-index: 2;
  padding: 8px 16px calc(12px + var(--safe-b));
  background: color-mix(in srgb, var(--mb-bg) 88%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--mb-line-soft);
}
.hm-ask {
  width: 100%; height: 50px;
  display: flex; align-items: center; gap: 10px;
  padding: 0 8px 0 14px;
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: 15px; text-align: left;
  box-shadow: var(--sh-card);
  transition: transform .16s var(--ease), border-color .16s var(--ease);
}
.hm-ask:active { transform: scale(.985); border-color: var(--mb-mint-line); }
.hm-ask__spark { color: var(--mb-accent); font-size: 15px; flex: none; }
.hm-ask__tx { flex: 1; min-width: 0; color: var(--mb-faint); font-size: 14.5px; }
.hm-ask__go {
  width: 34px; height: 34px; flex: none;
  border-radius: 11px; display: grid; place-items: center;
  background: var(--mb-accent); color: #fff;
}
body.dark .hm-ask__go { color: #06120c; }
.hm-ask__go svg { width: 16px; height: 16px; }

/* the primary gradient action */
.btn-flow {
  width: 100%; height: 54px;
  border-radius: 15px; color: #fff;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  font-weight: 600; font-size: 15.5px;
  border: 1px solid rgba(255,255,255,.12);
  background-image: var(--mb-flow);
  background-size: 220% 100%;
  animation: flowShift 7s ease-in-out infinite alternate;
  box-shadow: 0 1px 0 rgba(255,255,255,.16) inset, 0 10px 24px -12px rgba(16,40,28,.6);
  transition: transform .2s var(--ease);
}
.btn-flow:active { transform: scale(.985); }
.btn-flow:disabled { opacity: .55; }
.btn-flow svg { width: 19px; height: 19px; }
.btn-flow--sm { height: 44px; font-size: 14.5px; border-radius: var(--r-md); }
@keyframes flowShift { from { background-position: 0% 50%; } to { background-position: 100% 50%; } }

.searchbar {
  width: 100%;
  display: flex; align-items: center; gap: 9px;
  height: 42px; padding: 0 12px; margin-top: 14px;
  border: 1px solid var(--mb-line); border-radius: 12px;
  background: var(--mb-card); color: var(--mb-faint);
  font-size: 14.5px; text-align: left;
}
.searchbar svg { width: 16px; height: 16px; flex: none; }
.searchbar input {
  width: 100%; min-width: 0; border: 0; outline: 0; padding: 0;
  background: transparent; color: var(--mb-ink); font: inherit;
  /* 16px is not a style choice: iOS Safari zooms the page whenever a focused
     field is smaller, and a zoomed page is the one thing this fixed shell
     cannot survive — the visual viewport shrinks and pans on every finger
     move, so the app re-measures and re-lays-out continuously. Every field in
     the app is at least 16px for that reason. */
  font-size: 16px;
  -webkit-appearance: none; appearance: none;
}
.searchbar input::placeholder { color: var(--mb-faint); opacity: 1; }
.searchbar:focus-within { border-color: var(--mb-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mb-accent) 12%, transparent); }
.searchbar input::-webkit-search-cancel-button { opacity: .58; }
.searchbar--sm { height: 38px; margin: 2px 12px 8px; width: auto; border-radius: var(--r-sm); font-size: 13.5px; }

.rule { display: flex; align-items: center; gap: 8px; margin: 22px 2px 10px; }
.rule__label, .rule__count {
  font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: var(--mb-faint);
}
.rule__label { font-weight: 500; letter-spacing: .14em; text-transform: uppercase; }
.rule__line { flex: 1; height: 1px; background: var(--mb-line-soft); }

/* ---- class cards (rendered by main.js renderLibrary) ---- */
.classes { display: flex; flex-direction: column; gap: 12px; }
.lib__class {
  /* No content-visibility here. A class card is 120–320px tall depending on
     how many notes it holds, so the browser's placeholder guess was wrong for
     most of them: the list's height changed as you scrolled through it, and on
     a tall screen — where a dozen cards cross the boundary at once — that read
     as the whole library twitching. A library is tens of cards, not
     thousands; there is nothing here worth skipping paint for. It also means
     the arrival stagger below cannot re-fire on a card scrolling back in. */
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--sh-card);
}
.lib__head {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 13px 14px 11px;
  text-align: left; color: var(--mb-ink);
}
.lib__dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.lib__name {
  font-family: Spectral, Georgia, serif;
  font-size: 16.5px; font-weight: 600; letter-spacing: -.01em;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lib__code {
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px;
  letter-spacing: .1em; color: var(--mb-faint); padding-top: 2px;
}
.lib__count {
  margin-left: auto;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: var(--mb-faint);
}
.lib__notes { display: none; }
.lib__class.open .lib__notes { display: block; }
.lib__note {
  position: relative; width: 100%; min-height: 49px;
  display: flex; align-items: stretch;
  border-top: 1px solid var(--mb-line-soft);
  color: var(--mb-ink); text-align: left;
  transition: background .15s var(--ease), opacity .16s ease, transform .18s var(--ease), box-shadow .18s var(--ease);
}
.lib__note-open {
  min-width: 0; flex: 1; display: flex; align-items: center; gap: 11px;
  padding: 11px 4px 11px 14px; color: inherit; text-align: left;
  touch-action: pan-y; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.lib__note:active { background: var(--mb-mint); }
.lib__note.is-opening, .dw-note.is-opening { background: var(--mb-mint); }
.lib__note.is-opening .lib__note-open > svg,
.dw-note.is-opening .dw-note__open > svg {
  color: var(--mb-accent);
  animation: noteOpenPulse .72s ease-in-out infinite alternate;
}
@keyframes noteOpenPulse { to { opacity: .3; transform: scale(.84); } }
.lib__note-open > svg { width: 16px; height: 16px; color: var(--mb-faint); flex: none; }
.lib__note-open > span:first-of-type {
  flex: 1; min-width: 0; font-size: 14.5px; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lib__note-open .fresh {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--mb-accent); box-shadow: 0 0 8px var(--mb-accent);
  margin-left: auto; margin-right: 2px;
}
.lib__note-more {
  width: 45px; min-height: 45px; margin: 2px 3px 2px 0; flex: none; border-radius: 12px;
  display: grid; place-items: center; color: var(--mb-faint);
  transition: background .15s var(--ease), color .15s var(--ease), opacity .15s ease;
}
.lib__note-more svg { width: 18px; height: 18px; }
.lib__note-more:active, .lib__note-more:focus-visible { background: var(--mb-card-2); color: var(--mb-deep); outline: none; }
.lib__empty { text-align: center; color: var(--mb-faint); padding: 40px 20px; font-size: .9rem; line-height: 1.6; }

/* ============================================================
   CHAT
   ============================================================ */
/* `contain: paint` keeps this where it belongs. It is a blurred, permanently
   animating surface a quarter larger than the view in every direction; without
   isolation its repaints join the thread's, so scrolling a conversation on a
   big high-density screen re-rasterises the whole blur every frame. */
.aura { position: absolute; inset: -25%; z-index: 0; pointer-events: none; filter: blur(38px); opacity: .85; contain: paint; }
.aura i { position: absolute; inset: 0; display: block; }
.aura i:first-child {
  background: radial-gradient(38% 30% at 24% 30%, color-mix(in srgb, var(--mb-accent) 20%, transparent), transparent 70%),
              radial-gradient(34% 26% at 74% 68%, color-mix(in srgb, var(--mb-accent) 13%, transparent), transparent 72%);
  animation: auraA 26s linear infinite;
}
.aura i:last-child {
  background: radial-gradient(30% 24% at 68% 22%, color-mix(in srgb, var(--mb-accent) 16%, transparent), transparent 72%),
              radial-gradient(40% 30% at 30% 80%, color-mix(in srgb, var(--mb-deep) 12%, transparent), transparent 70%);
  animation: auraB 34s linear infinite;
}
@keyframes auraA { 0%{transform:translate3d(-8%,0,0) scale(1)} 50%{transform:translate3d(6%,-3%,0) scale(1.12)} 100%{transform:translate3d(-8%,0,0) scale(1)} }
@keyframes auraB { 0%{transform:translate3d(7%,2%,0) scale(1.08)} 50%{transform:translate3d(-6%,-4%,0) scale(1)} 100%{transform:translate3d(7%,2%,0) scale(1.08)} }

.ch-top {
  flex: none; position: relative; z-index: 2;
  padding: calc(var(--safe-t) + 12px) 12px 10px;
  display: flex; align-items: center; gap: 6px;
  background: color-mix(in srgb, var(--mb-card-2) 72%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid var(--mb-line-soft);
}
.ch-id { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; padding-left: 2px; }
.ch-id__cls { display: flex; align-items: center; gap: 6px; }
.ch-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--mb-accent); }
.ch-id__cls span {
  font-family: 'IBM Plex Mono', monospace; font-size: 10.5px;
  letter-spacing: .04em; color: var(--mb-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ch-id__note {
  font-family: Spectral, Georgia, serif; font-size: 16px; font-weight: 600;
  letter-spacing: -.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}


/* ============ thread ============ */
/* min-height is a floor, not a size: it is what stops a tall composer (an
   attached equation, a long draft) from shrinking the conversation to a
   sliver. Flexbox will not shrink an item past its min-height, so the
   composer — which can shrink — gives way first. */
.thread {
  /* Published as a variable because a sticky footer inside the thread has to
     cancel it: a scroll container's own bottom padding insets where `bottom: 0`
     lands, so the quiz control bar would otherwise float with a strip of the
     card still scrolling past underneath it. See .quiz-controls. */
  --thread-pad-b: 8px;
  flex: 1 200 auto; min-height: min(72px, 16%); position: relative; z-index: 1;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 18px 16px var(--thread-pad-b);
  display: flex; flex-direction: column; gap: 14px;
  background-image: linear-gradient(rgba(22,32,26,.045) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(22,32,26,.045) 1px, transparent 1px);
  background-size: 26px 26px;
}
body.dark .thread {
  background-image: linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px);
}
.msg { max-width: 88%; }
.msg--user {
  align-self: flex-end;
  max-width: 80%;
  background: var(--mb-accent); color: #fff;
  border-radius: 18px 18px 6px 18px;
  padding: 10px 14px;
  font-size: 14.5px; line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;
  box-shadow: 0 6px 16px -10px rgba(16,40,28,.8);
}
body.dark .msg--user { color: #06120c; }
.msg__att-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 9px;
  padding: 4px 9px;
  margin-bottom: 8px;
  font-size: 12px;
  color: #fff;
  max-width: 100%;
  box-sizing: border-box;
}
body.dark .msg__att-chip {
  background: rgba(0, 0, 0, 0.24);
  border-color: rgba(0, 0, 0, 0.32);
  color: #06120c;
}
.msg__att-chip .msg__att-ic {
  display: grid;
  place-items: center;
  flex: none;
  opacity: 0.95;
}
.msg__att-chip .msg__att-ic svg {
  width: 13px;
  height: 13px;
}
.msg__att-chip .msg__att-label {
  font-weight: 600;
  text-transform: uppercase;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9.5px;
  letter-spacing: .06em;
  opacity: 0.95;
  flex: none;
}
.msg__att-chip .msg__att-prev {
  /* capped for the same reason as .cmp-att-box__preview: a multi-row equation
     lays out as a grid and would otherwise stretch the bubble */
  max-height: 42px;
  overflow: auto;
  overscroll-behavior: contain;
  white-space: nowrap;
  opacity: 0.95;
  font-size: 12px;
  flex: 1;
  min-width: 0;
  scrollbar-width: none;
}
.msg__att-chip .msg__att-prev::-webkit-scrollbar { display: none; }
.msg__att-chip .msg__att-prev .katex {
  font-size: 1.05em;
  color: inherit;
}
.msg__att-chip .msg__att-prev .att-code-preview {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
}
.msg__att-chip .msg__att-prev .att-plain-preview {
  font-family: inherit;
  font-size: 12px;
}
.msg__user-text {
  white-space: pre-wrap;
  word-break: break-word;
}
.msg--ai { align-self: flex-start; max-width: 92%; }
.msg--ai .msg__model {
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px;
  letter-spacing: .09em; text-transform: uppercase; color: var(--mb-faint);
  margin: 5px 0 0 4px; display: flex; align-items: center; gap: 6px; order: 2;
}
.msg--ai .msg__model::before { content: "✦"; color: var(--mb-accent); text-transform: none; letter-spacing: 0; }
.msg--ai { display: flex; flex-direction: column; }
.msg__footer {
  order: 2;
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0 0 4px;
}
.msg__footer .msg__model { order: initial; flex: 1; margin: 0; }
.msg__tools { display: flex; align-items: center; gap: 2px; flex: none; }
.msg__tool {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  color: var(--mb-faint);
  transition: color .16s var(--ease), background .16s var(--ease), transform .16s var(--ease);
}
.msg__tool:active { transform: scale(.92); background: var(--mb-mint); color: var(--mb-accent); }
.msg__tool:focus-visible { outline: 2px solid var(--mb-accent); outline-offset: 1px; }
.msg__tool.is-done { color: var(--mb-accent); background: var(--mb-mint); }
.msg__tool svg, .lemma-speech svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.lemma-speech .speech-fill { fill: currentColor; stroke: none; }
.lemma-speech[data-speech-state="loading"] svg { animation: mb-speech-pulse .8s var(--ease) infinite alternate; }
.lemma-speech[data-speech-state="playing"] { color: var(--mb-accent); background: var(--mb-mint); }
@keyframes mb-speech-pulse { to { opacity: .35; transform: scale(.9); } }
.msg__body {
  order: 1;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  border-radius: 18px 18px 18px 6px;
  padding: 11px 14px;
  font-size: 14.5px; line-height: 1.6;
  overflow-x: auto;
  box-shadow: 0 1px 2px rgba(16,40,28,.05), 0 6px 18px -14px rgba(16,40,28,.5);
}
.msg__body p { margin: 0 0 8px; }
.msg__body p:last-child { margin-bottom: 0; }
.msg__body ul { margin: 4px 0 8px; padding-left: 20px; }
.msg__body h4 { margin: 10px 0 6px; font-size: .98rem; }
.msg__body .lm-code {
  background: rgba(22,32,26,.06); border-radius: 10px; padding: 10px 12px;
  font-family: 'IBM Plex Mono', monospace; font-size: .82rem; overflow-x: auto; margin: 8px 0;
}
body.dark .msg__body .lm-code { background: rgba(255,255,255,.07); }
.msg__body .lm-inline {
  background: rgba(22,32,26,.07); border-radius: 5px; padding: 1px 5px;
  font-family: 'IBM Plex Mono', monospace; font-size: .84em;
}
body.dark .msg__body .lm-inline { background: rgba(255,255,255,.09); }
.msg__body .katex-display { margin: 8px 0; overflow-x: auto; overflow-y: hidden; }
.msg__imgs { display: flex; gap: 6px; margin-bottom: 6px; flex-wrap: wrap; justify-content: flex-end; }
.msg__imgs img { width: 72px; height: 72px; object-fit: cover; border-radius: 10px; border: 1px solid var(--mb-line); }
.msg__status {
  font-size: .78rem; color: var(--mb-faint);
  margin: 4px 0 0 2px; display: flex; align-items: center; gap: 6px;
}
.msg__status::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  border: 2px solid var(--mb-accent); border-top-color: transparent;
  animation: mbspin .8s linear infinite;
}
@keyframes mbspin { to { transform: rotate(360deg); } }
.lm-caret {
  display: inline-block; width: 7px; height: 15px;
  background: var(--mb-accent); border-radius: 2px;
  vertical-align: text-bottom; margin-left: 2px;
  animation: mbblink 1s steps(2) infinite;
}
@keyframes mbblink { 50% { opacity: 0; } }

/* ---- a turn that is still running ----
   Persisted into the thread, so this is what the user finds when they come
   back to a note (or reopen the app) while Lemma is still writing. */
.lm-working {
  min-width: min(64vw, 280px);
  display: flex;
  align-items: center;
  gap: 12px;
}
.lm-working__mark {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  border: 1px solid var(--mb-mint-line);
  border-radius: 12px;
  background: var(--mb-mint);
}
.lm-working__mark i {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--mb-accent);
  animation: mbpulse 1.5s var(--ease) infinite;
}
@keyframes mbpulse {
  0%, 100% { transform: scale(.62); opacity: .45; }
  50%      { transform: scale(1);   opacity: 1; }
}
.lm-working__copy { display: grid; min-width: 0; }
.lm-working__copy b { font-size: 13.5px; }
.lm-working__copy small { margin-top: 2px; color: var(--mb-faint); font-size: 11px; }
.msg--working .msg__status { font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) {
  .lm-working__mark i { animation: none; opacity: .8; }
  .lemma-speech[data-speech-state="loading"] svg { animation: none; opacity: .55; }
}

/* ============ interactive quiz in chat ============
   A quiz is a full learning surface rather than another text bubble. It stays
   inside the thread, but grows to the available width on tablets and desktop.
   Every control keeps a 44px+ target and every state is conveyed by words or
   icons as well as colour. */
.msg--ai.msg--quiz {
  width: min(100%, 720px);
  max-width: 100%;
}
.msg__quiz {
  order: 1;
  width: 100%;
  min-width: 0;
}
.msg--quiz .msg__model { margin-top: 7px; }
/* The padding and the two bottom corners are variables because the sticky
   control bar has to bleed out to the card's own edges, and both change with
   the viewport (see the media queries at the end of this section). NOTE the
   deliberate absence of `overflow: hidden`: it would make this card the
   nearest scroll container and the sticky bar would stop sticking. The rounded
   ::before highlight keeps its corners with border-radius: inherit instead. */
.quiz-card {
  --quiz-pad: 17px;
  --quiz-br: 22px;
  --quiz-bl: 7px;
  position: relative;
  isolation: isolate;
  width: 100%;
  min-width: 0;
  padding: var(--quiz-pad) var(--quiz-pad) 0;
  border: 1px solid color-mix(in srgb, var(--mb-accent) 22%, var(--mb-line));
  border-radius: 22px 22px var(--quiz-br) var(--quiz-bl);
  background:
    radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--mb-accent) 12%, transparent), transparent 35%),
    var(--mb-card);
  box-shadow: 0 18px 45px -32px rgba(16,40,28,.62), var(--sh-card);
}
.quiz-card::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(120deg, rgba(255,255,255,.3), transparent 32%);
}
.quiz-top {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.quiz-top__identity { flex: 1; min-width: 0; }
.quiz-kicker,
.quiz-type,
.quiz-model-answer__label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .11em;
  text-transform: uppercase;
}
.quiz-kicker { display: block; margin-bottom: 4px; color: var(--mb-accent); }
.quiz-top h3 {
  margin: 0;
  font-family: Spectral, Georgia, serif;
  font-size: clamp(19px, 5.4vw, 24px);
  line-height: 1.1;
  letter-spacing: -.025em;
  overflow-wrap: anywhere;
}
.quiz-tally {
  flex: none;
  min-width: 48px;
  min-height: 34px;
  padding: 0 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--mb-mint-line);
  border-radius: 999px;
  background: var(--mb-mint);
  color: var(--mb-deep);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10px;
  font-weight: 600;
}
.quiz-progress__meta {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 18px 1px 7px;
  color: var(--mb-faint);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9px;
  letter-spacing: .045em;
  text-transform: uppercase;
}
.quiz-progress {
  height: 5px;
  overflow: hidden;
  border-radius: 99px;
  background: color-mix(in srgb, var(--mb-line) 70%, transparent);
}
.quiz-progress i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--mb-flow);
  box-shadow: 0 0 12px color-mix(in srgb, var(--mb-accent) 45%, transparent);
  transition: width .55s var(--ease);
}
.quiz-question {
  margin-top: 17px;
  padding: 16px;
  border: 1px solid var(--mb-line-soft);
  border-radius: 16px;
  background: color-mix(in srgb, var(--mb-card-2) 88%, transparent);
}
.quiz-type {
  display: inline-flex;
  align-items: center;
  min-height: 23px;
  padding: 0 8px;
  border: 1px solid var(--mb-mint-line);
  border-radius: 999px;
  background: var(--mb-mint);
  color: var(--mb-deep);
}
.quiz-question__prompt {
  margin-top: 10px;
  font-family: Spectral, Georgia, serif;
  font-size: clamp(17px, 4.5vw, 20px);
  font-weight: 500;
  line-height: 1.42;
  letter-spacing: -.01em;
  overflow-wrap: anywhere;
}
.quiz-question__prompt p,
.quiz-option__text p,
.quiz-feedback__copy p,
.quiz-model-answer__copy p,
.quiz-model-answer li p { margin: 0; }
.quiz-question__prompt .katex,
.quiz-option__text .katex { font-size: 1em; }
.quiz-answer { margin-top: 12px; }
.quiz-options { display: grid; gap: 9px; }
.quiz-option {
  width: 100%;
  min-height: 52px;
  padding: 8px 10px;
  display: grid;
  grid-template-columns: 32px minmax(0,1fr) 24px;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--mb-line);
  border-radius: 14px;
  background: var(--mb-card);
  color: var(--mb-ink);
  text-align: left;
  box-shadow: 0 2px 8px -7px rgba(16,40,28,.5);
  transition: transform .18s var(--ease), border-color .2s var(--ease), background .2s var(--ease), box-shadow .2s var(--ease);
}
.quiz-option:not(:disabled):active { transform: scale(.985); }
.quiz-option:focus-visible,
.quiz-btn:focus-visible,
.quiz-assess__btn:focus-visible,
.quiz-written textarea:focus-visible {
  outline: 2px solid var(--mb-accent);
  outline-offset: 2px;
}
.quiz-option__letter {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--mb-line);
  border-radius: 10px;
  background: var(--mb-card-2);
  color: var(--mb-soft);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10px;
  font-weight: 600;
  transition: inherit;
}
.quiz-option__text {
  min-width: 0;
  font-size: 13.5px;
  line-height: 1.38;
  overflow-wrap: anywhere;
}
.quiz-option__mark {
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 18px;
  font-weight: 700;
}
.quiz-option__mark svg { width: 14px; height: 14px; }
.quiz-option.is-selected {
  border-color: var(--mb-accent);
  background: var(--mb-mint);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--mb-accent) 11%, transparent);
}
.quiz-option.is-selected .quiz-option__letter {
  border-color: var(--mb-accent);
  background: var(--mb-accent);
  color: #fff;
}
.quiz-option.is-correct {
  border-color: var(--mb-accent);
  background: var(--mb-mint);
}
.quiz-option.is-correct .quiz-option__letter,
.quiz-option.is-correct .quiz-option__mark {
  border-color: var(--mb-accent);
  background: var(--mb-accent);
  color: #fff;
}
.quiz-option.is-wrong {
  border-color: color-mix(in srgb, var(--mb-danger) 65%, var(--mb-line));
  background: color-mix(in srgb, var(--mb-danger) 8%, var(--mb-card));
}
.quiz-option.is-wrong .quiz-option__letter,
.quiz-option.is-wrong .quiz-option__mark {
  border-color: var(--mb-danger);
  background: var(--mb-danger);
  color: #fff;
}
.quiz-option:disabled { opacity: 1; cursor: default; }
/* Submitting an answer scrolls the marking into view (quiz.js). The control
   bar is pinned over the bottom of the thread, so the scroll has to stop
   short of it or it would park the explanation underneath the buttons. */
.quiz-feedback,
.quiz-model-answer {
  margin-top: 11px;
  scroll-margin-bottom: 104px;
  border-radius: 14px;
  color: var(--mb-soft);
  font-size: 13px;
  line-height: 1.48;
}
.quiz-feedback {
  padding: 12px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  border: 1px solid var(--mb-mint-line);
  background: var(--mb-mint);
}
.quiz-feedback.is-review {
  border-color: color-mix(in srgb, var(--mb-danger) 35%, var(--mb-line));
  background: color-mix(in srgb, var(--mb-danger) 7%, var(--mb-card));
}
.quiz-feedback b { display: block; margin-bottom: 2px; color: var(--mb-ink); }
.quiz-feedback__icon {
  width: 25px;
  height: 25px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--mb-accent);
  color: #fff;
  font-weight: 700;
}
.quiz-feedback.is-review .quiz-feedback__icon { background: var(--mb-danger); }
.quiz-feedback__icon svg { width: 14px; height: 14px; }
.quiz-written { display: grid; gap: 7px; }
.quiz-written > span {
  color: var(--mb-soft);
  font-size: 11px;
  font-weight: 600;
}
.quiz-written textarea {
  width: 100%;
  min-height: 122px;
  resize: vertical;
  padding: 12px 13px;
  border: 1px solid var(--mb-line);
  border-radius: 14px;
  background: var(--mb-card);
  color: var(--mb-ink);
  font: 400 16px/1.45 'Hanken Grotesk', -apple-system, system-ui, sans-serif;
  caret-color: var(--mb-accent);
  -webkit-appearance: none;
  appearance: none;
}
.quiz-written textarea::placeholder { color: var(--mb-faint); }
.quiz-written textarea:disabled { opacity: .8; background: var(--mb-card-2); }
.quiz-model-answer {
  padding: 13px 14px;
  border: 1px solid var(--mb-mint-line);
  background: var(--mb-mint);
}
.quiz-model-answer__label { display: block; margin-bottom: 7px; color: var(--mb-deep); }
.quiz-model-answer__copy { color: var(--mb-ink); }
.quiz-model-answer ul { margin: 9px 0 0; padding: 9px 0 0 18px; border-top: 1px solid var(--mb-mint-line); }
.quiz-model-answer li + li { margin-top: 4px; }
.quiz-assess {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 9px;
}
.quiz-assess__btn {
  min-height: 46px;
  padding: 8px 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 1px solid var(--mb-line);
  border-radius: 12px;
  background: var(--mb-card);
  color: var(--mb-soft);
  font-size: 12px;
  font-weight: 600;
}
.quiz-assess__btn svg { width: 15px; height: 15px; }
.quiz-assess__btn.is-active {
  border-color: var(--mb-accent);
  background: var(--mb-mint);
  color: var(--mb-deep);
}
/* Pinned to the bottom of the thread for as long as the card is on screen.
   A ten-question quiz is far taller than a phone, and checking an answer
   grows it again — Back and Next used to disappear under the fold exactly
   when they were needed. The bar bleeds out to the card's edges (the card
   carries no bottom padding of its own) so it reads as the card's floor. */
.quiz-controls {
  position: sticky;
  /* Pulled down by the thread's bottom padding, which the browser treats as
     part of the sticky inset, and handed straight back as padding inside the
     bar. Without it the card keeps scrolling through the gap underneath. */
  bottom: calc(var(--thread-pad-b, 0px) * -1);
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 14px calc(var(--quiz-pad) * -1) 0;
  padding: 11px var(--quiz-pad) calc(var(--quiz-pad) + var(--thread-pad-b, 0px));
  border-top: 1px solid var(--mb-line-soft);
  border-radius: 0 0 var(--quiz-br) var(--quiz-bl);
  background: var(--mb-card);
}
.quiz-controls__hint {
  flex: 1 0 100%;
  order: -1;
  margin: 0;
  color: var(--mb-faint);
  font-size: 11.5px;
}
.quiz-btn {
  min-height: 46px;
  padding: 0 15px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border-radius: 13px;
  font-size: 12.5px;
  font-weight: 650;
  transition: transform .18s var(--ease), opacity .18s var(--ease), background .18s var(--ease);
}
.quiz-btn:not(:disabled):active { transform: scale(.97); }
.quiz-btn svg { width: 16px; height: 16px; }
.quiz-btn--primary {
  margin-left: auto;
  background: var(--mb-flow);
  color: #fff;
  box-shadow: 0 9px 20px -13px var(--mb-accent);
}
body.dark .quiz-btn--primary,
body.dark .quiz-option.is-selected .quiz-option__letter,
body.dark .quiz-option.is-correct .quiz-option__letter,
body.dark .quiz-option.is-correct .quiz-option__mark,
body.dark .quiz-feedback__icon { color: #07130d; }
.quiz-btn--secondary,
.quiz-btn--ghost {
  border: 1px solid var(--mb-line);
  background: var(--mb-card);
  color: var(--mb-soft);
}
.quiz-btn--ghost { padding-left: 10px; padding-right: 10px; }
.quiz-btn:disabled { opacity: .38; cursor: not-allowed; }

/* completion */
/* No sticky bar here, so the summary puts the card's bottom padding back. */
.quiz-card--summary {
  padding: calc(var(--quiz-pad) + 6px) var(--quiz-pad) var(--quiz-pad);
  text-align: center;
}
.quiz-score {
  --quiz-score: 0deg;
  width: 112px;
  height: 112px;
  margin: 0 auto;
  padding: 8px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: conic-gradient(var(--mb-accent) var(--quiz-score), var(--mb-line-soft) 0);
  box-shadow: 0 14px 34px -24px var(--mb-accent);
}
.quiz-score::before {
  content: "";
  grid-area: 1/1;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--mb-card);
}
.quiz-score span { position: relative; grid-area: 1/1; display: grid; }
.quiz-score b { font-family: Spectral, Georgia, serif; font-size: 38px; line-height: .9; }
.quiz-score small { margin-top: 5px; color: var(--mb-faint); font-family: 'IBM Plex Mono', monospace; font-size: 9px; text-transform: uppercase; }
.quiz-summary__copy h3 { margin: 16px 0 0; font-family: Spectral, Georgia, serif; font-size: 24px; }
.quiz-summary__copy p { max-width: 42ch; margin: 7px auto 0; color: var(--mb-soft); font-size: 13px; line-height: 1.5; }
.quiz-summary__stats {
  margin-top: 16px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--mb-line-soft);
  border-radius: 14px;
  background: var(--mb-card-2);
}
.quiz-summary__stats span { min-width: 0; padding: 11px 5px; display: grid; gap: 2px; }
.quiz-summary__stats span + span { border-left: 1px solid var(--mb-line-soft); }
.quiz-summary__stats b { font-family: Spectral, Georgia, serif; font-size: 19px; }
.quiz-summary__stats small { overflow: hidden; text-overflow: ellipsis; color: var(--mb-faint); font-size: 8px; text-transform: uppercase; letter-spacing: .04em; }
.quiz-summary__actions { margin-top: 13px; display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.quiz-summary__actions .quiz-btn { width: 100%; }

/* streamed placeholder */
.quiz-loading {
  min-width: min(68vw, 300px);
  display: flex;
  align-items: center;
  gap: 12px;
}
.quiz-loading__mark {
  width: 42px;
  height: 42px;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid var(--mb-mint-line);
  border-radius: 13px;
  background: var(--mb-mint);
  color: var(--mb-deep);
  font-family: Spectral, Georgia, serif;
  font-size: 20px;
  font-weight: 600;
}
.quiz-loading span:last-child { display: grid; }
.quiz-loading b { font-size: 13.5px; }
.quiz-loading small { margin-top: 2px; color: var(--mb-faint); font-size: 11px; }

@media (max-width: 359px) {
  .thread { padding-left: 10px; padding-right: 10px; }
  .quiz-card { --quiz-pad: 13px; --quiz-br: 18px; --quiz-bl: 6px; border-top-left-radius: 18px; border-top-right-radius: 18px; }
  .quiz-question { padding: 13px; }
  .quiz-option { grid-template-columns: 29px minmax(0,1fr) 20px; gap: 8px; padding-left: 8px; padding-right: 8px; }
  .quiz-option__letter { width: 29px; height: 29px; }
  .quiz-btn { padding-left: 11px; padding-right: 11px; }
  .quiz-assess { grid-template-columns: 1fr; }
  .quiz-summary__actions { grid-template-columns: 1fr; }
}

@media (min-width: 760px) {
  .thread { padding-left: max(24px, calc((100vw - 920px) / 2)); padding-right: max(24px, calc((100vw - 920px) / 2)); }
  .quiz-card { --quiz-pad: 21px; }
  .quiz-question { padding: 18px; }
  .quiz-top h3 { font-size: 25px; }
  .quiz-question__prompt { font-size: 20px; }
  .quiz-option__text { font-size: 14px; }
}
.msg__action {
  order: 3; align-self: flex-start;
  margin-top: 8px;
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
  color: var(--mb-deep); border-radius: 12px;
  padding: 9px 12px;
  font-size: 11px; font-weight: 500;
  font-family: 'IBM Plex Mono', monospace;
}

/* jump to created/updated notebox */
.msg__jumps {
  order: 3;
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
  width: 100%;
  max-width: 100%;
}
.msg__jumps-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
  width: fit-content;
  max-width: 100%;
}
.msg__jumps-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 0 10px;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  border-radius: 13px;
  color: var(--mb-deep);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(16,40,28,.04);
  transition: background 0.28s cubic-bezier(.16,1,.3,1), border-color 0.28s cubic-bezier(.16,1,.3,1), color 0.28s cubic-bezier(.16,1,.3,1), box-shadow 0.28s cubic-bezier(.16,1,.3,1), transform 0.28s cubic-bezier(.16,1,.3,1);
  flex: none;
  animation: lm-box-spawn .52s cubic-bezier(.22,1.2,.36,1) backwards;
  backface-visibility: hidden;
}
body.dark .msg__jumps-badge {
  background: var(--mb-card);
  border-color: var(--mb-line);
  color: var(--mb-accent);
}
.msg__jumps-badge:active {
  background: var(--mb-mint);
  border-color: var(--mb-mint-line);
  transform: scale(0.975);
}
.msg__jumps-badge.is-open {
  background: var(--mb-mint);
  border-color: var(--mb-mint-line);
}
.msg__jumps-badge-ic {
  width: 13px;
  height: 13px;
  transition: transform .28s cubic-bezier(.22,1,.36,1);
}
.msg__jumps-badge.is-open .msg__jumps-badge-ic {
  transform: rotate(180deg);
}

/* Accordion open & close animated wrapper */
.msg__jumps-wrap {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transform: translateY(-6px) scale(0.98);
  transition: grid-template-rows 0.3s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s var(--ease), transform 0.28s cubic-bezier(0.16, 1, 0.3, 1), margin-top 0.3s var(--ease);
  margin-top: 0;
}
.msg__jumps-wrap.is-open {
  grid-template-rows: 1fr;
  opacity: 1;
  transform: none;
  margin-top: 6px;
}
.msg__jumps-wrap.is-closing {
  grid-template-rows: 0fr;
  opacity: 0;
  transform: translateY(-6px) scale(0.98);
  transition: grid-template-rows 0.25s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s var(--ease), transform 0.22s var(--ease), margin-top 0.25s var(--ease);
  margin-top: 0;
}
.msg__jumps-drop {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: fit-content;
  max-width: 100%;
}
.msg__jumps-wrap.is-open .msg__jump-btn {
  animation: jumpItemIn 0.32s cubic-bezier(0.16, 1, 0.3, 1) backwards;
  animation-delay: calc(var(--item-idx, 0) * 35ms);
}
@keyframes jumpItemIn {
  from {
    opacity: 0;
    transform: translateY(-8px) scale(0.96);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.msg__jumps-wrap.is-closing .msg__jump-btn {
  animation: jumpItemOut 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@keyframes jumpItemOut {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateY(-6px) scale(0.96);
  }
}
.msg__jump-btn {
  display: flex;
  align-items: center;
  gap: 9px;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  border-radius: 13px;
  padding: 8px 11px;
  color: var(--mb-ink);
  text-align: left;
  box-shadow: 0 1px 2px rgba(16,40,28,.04);
  transition: background 0.28s cubic-bezier(.16,1,.3,1), border-color 0.28s cubic-bezier(.16,1,.3,1), box-shadow 0.28s cubic-bezier(.16,1,.3,1), transform 0.28s cubic-bezier(.16,1,.3,1);
  width: fit-content;
  max-width: 100%;
  box-sizing: border-box;
  flex: 1;
  min-width: 0;
  backface-visibility: hidden;
}
body.dark .msg__jump-btn {
  background: var(--mb-card);
  border-color: var(--mb-line);
}
.msg__jump-btn:active {
  background: var(--mb-mint);
  border-color: var(--mb-mint-line);
  transform: scale(0.985);
}
/* Spawn animation + desktop green outline UI bloom signature */
.msg__jump-btn--flash {
  position: relative;
  animation: lm-box-spawn .52s cubic-bezier(.22,1.2,.36,1) backwards, lm-ai-bloom 3s var(--ease) forwards;
}
body.dark .msg__jump-btn--flash {
  animation: lm-box-spawn .52s cubic-bezier(.22,1.2,.36,1) backwards, lm-ai-bloom-dark 3s var(--ease) forwards;
}
@keyframes lm-box-spawn {
  from { opacity: 0; transform: scale(0.92) translateY(6px); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@keyframes lm-ai-bloom {
  0%   { box-shadow: 0 0 0 0 rgba(28, 124, 84, 0), 0 1px 2px rgba(16,40,28,.04); }
  12%  { box-shadow: 0 0 22px 3px rgba(28, 124, 84, 0.42), 0 1px 2px rgba(16,40,28,.04); }
  68%  { box-shadow: 0 0 14px 2px rgba(28, 124, 84, 0.24), 0 1px 2px rgba(16,40,28,.04); }
  100% { box-shadow: 0 1px 2px rgba(16,40,28,.04); }
}
@keyframes lm-ai-bloom-dark {
  0%   { box-shadow: 0 0 0 0 rgba(63, 167, 118, 0), 0 1px 2px rgba(0,0,0,.2); }
  12%  { box-shadow: 0 0 22px 3px rgba(63, 167, 118, 0.46), 0 1px 2px rgba(0,0,0,.2); }
  68%  { box-shadow: 0 0 14px 2px rgba(63, 167, 118, 0.26), 0 1px 2px rgba(0,0,0,.2); }
  100% { box-shadow: 0 1px 2px rgba(0,0,0,.2); }
}
.msg__jump-btn--flash::before {
  content: "";
  position: absolute;
  inset: -2.5px;
  border-radius: 15.5px;
  padding: 2.5px;
  background: linear-gradient(
    115deg,
    var(--mb-accent) 0%,
    #25b083 20%,
    #5ad7ad 38%,
    #34c2cf 56%,
    #25b083 76%,
    var(--mb-accent) 100%
  );
  background-size: 200% 100%;
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
          mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  z-index: 4;
  animation: lm-ai-ring 3s var(--ease) forwards, lm-ai-flow 1.5s linear infinite;
}
@keyframes lm-ai-ring {
  0%   { opacity: 0; transform: scale(1.04); }
  14%  { opacity: 1; transform: scale(1); }
  68%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1); }
}
@keyframes lm-ai-flow {
  from { background-position: 0% 50%; }
  to   { background-position: 200% 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .msg__jump-btn--flash::before { animation: lm-ai-ring 3s var(--ease) forwards; }
}
.msg__jump-ic {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--mb-mint);
  border: 1px solid var(--mb-mint-line);
  color: var(--mb-accent);
}
.msg__jump-ic svg {
  width: 14px;
  height: 14px;
}
.msg__jump-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.msg__jump-tag {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--mb-accent);
  line-height: 1.2;
}
.msg__jump-prev {
  font-size: 12px;
  color: var(--mb-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 230px;
  line-height: 1.35;
  margin-top: 1px;
}
.msg__jump-prev .att-math-rendered .katex {
  font-size: 0.95em;
}
.msg__jump-arrow {
  display: grid;
  place-items: center;
  flex: none;
  color: var(--mb-faint);
  margin-left: 2px;
  transition: color 0.28s cubic-bezier(.16,1,.3,1), transform 0.28s cubic-bezier(.16,1,.3,1);
}
.msg__jump-arrow svg {
  width: 14px;
  height: 14px;
}
.msg__jump-btn:active .msg__jump-arrow {
  color: var(--mb-accent);
  transform: translate(1px, -1px);
}

/* ============ floating scroll to bottom button ============
   Anchored to the top edge of the composer it sits inside, not to a fixed
   distance from the bottom of the screen — the composer's height changes with
   what is staged in it, and the old 72px landed square on the card. */
.scroll-bottom-btn {
  position: absolute;
  right: 14px;
  bottom: calc(100% + 6px);
  z-index: 25;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  color: var(--mb-accent);
  display: grid;
  place-items: center;
  box-shadow: 0 4px 14px rgba(16, 40, 28, 0.14), 0 1px 3px rgba(16, 40, 28, 0.08);
  cursor: pointer;
  transition: background 0.28s cubic-bezier(.16,1,.3,1), border-color 0.28s cubic-bezier(.16,1,.3,1), transform 0.28s cubic-bezier(.16,1,.3,1), box-shadow 0.28s cubic-bezier(.16,1,.3,1);
  backface-visibility: hidden;
}
body.dark .scroll-bottom-btn {
  background: var(--mb-card);
  border-color: var(--mb-line);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
}
.scroll-bottom-btn:active {
  background: var(--mb-mint);
  border-color: var(--mb-mint-line);
  transform: scale(0.94);
}
.scroll-bottom-btn svg {
  width: 17px;
  height: 17px;
}
.scroll-bottom-btn.is-showing {
  animation: scrollBtnIn .22s cubic-bezier(.22, 1.2, .36, 1) forwards;
}
.scroll-bottom-btn.is-hiding {
  animation: scrollBtnOut .18s var(--ease) forwards;
  pointer-events: none;
}
@keyframes scrollBtnIn {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.82);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes scrollBtnOut {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateY(12px) scale(0.82);
  }
}

/* empty-state hero */
.hello {
  margin: auto;
  text-align: center;
  padding: 24px 6px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* MathematiX Icon (Stationary with signature outline effect) */
.hello__icon {
  position: relative;
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  margin-bottom: 12px;
  border-radius: 18px;
  background: var(--mb-card);
  border: 1.5px solid color-mix(in srgb, var(--mb-accent) 42%, var(--mb-mint-line));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--mb-accent) 12%, transparent),
              0 6px 18px -4px color-mix(in srgb, var(--mb-accent) 18%, transparent);
  overflow: hidden;
}
.hello__icon-glow {
  display: none;
}
.hello__icon-img {
  width: 38px;
  height: 38px;
  object-fit: contain;
  display: block;
  transform: scale(1.7);
}

/* Headline with animated gradient wave & typewriter */
.hello h2 {
  font-family: Spectral, Georgia, serif;
  font-weight: 500;
  font-size: 24px;
  letter-spacing: -.02em;
  margin: 10px 0 0;
  line-height: 1.25;
  display: flex;
  align-items: baseline;
  justify-content: center;
  flex-wrap: wrap;
  column-gap: 5px;
}
.hello__lead {
  color: var(--mb-ink);
}
.hello__phrase {
  font-style: italic;
  color: var(--mb-accent);
  position: relative;
  white-space: nowrap;
  background-image: var(--mb-flow, linear-gradient(90deg, #124d34, #1c7c54, #6fbb96, #145c3d, #124d34));
  background-size: 200% 100%;
  background-position: 0% 50%;
  animation: helloWave 7s linear infinite;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  display: inline-block;
  min-width: 0.5ch;
  text-shadow: 0 0 10px color-mix(in srgb, var(--mb-accent) 15%, transparent);
}
.hello__phrase::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: 0.82em;
  margin-left: 3px;
  background: var(--mb-accent);
  animation: helloCaret 0.9s steps(1) infinite;
  vertical-align: -0.03em;
  -webkit-text-fill-color: initial;
}

@keyframes helloCaret {
  50% { opacity: 0; }
}

@keyframes helloWave {
  from { background-position: 0% 50%; }
  to { background-position: 200% 50%; }
}

.hello p {
  color: var(--mb-soft);
  font-size: 14px;
  line-height: 1.55;
  margin: 8px 0 0;
  max-width: 29ch;
}

.hello__chips {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  margin-top: 22px;
}

/* Suggestion cards in Lemma chat */
.chip {
  width: 100%;
  height: 48px;
  padding: 0 16px;
  display: flex;
  align-items: center;
  position: relative;
  border-radius: 14px;
  font-size: 14.5px;
  color: var(--mb-ink);
  text-align: left;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  box-shadow: var(--sh-card);
  cursor: pointer;
  transition: transform 0.15s var(--ease), border-color 0.15s var(--ease), box-shadow 0.15s var(--ease), background 0.15s var(--ease);
}
.chip:hover {
  border-color: color-mix(in srgb, var(--mb-line) 60%, var(--mb-accent));
  box-shadow: 0 2px 8px rgba(16, 40, 28, 0.06);
}
.chip:active {
  transform: scale(0.985);
  background: var(--mb-card-2);
  border-color: var(--mb-line);
}

/* ============ composer ============ */
/* No translateY here: the body is already sized to the visible app height, so
   the keyboard shrinks the app and the composer rides up on its own — the
   --kb-inset main.js folds into --app-h is what makes that true in an in-app
   WebView too, where the visual viewport never moves. */
/* The composer SHRINKS rather than pushing the app off the bottom.
   `flex: none` meant a tall attachment — a four-line `aligned` equation makes
   the chip ~120px on its own — grew the card until the field and the send
   button sat below the fold, under the keyboard, with the thread crushed to a
   sliver. Now it is a shrinkable column: the strip inside it gives way first
   (it scrolls), the input and the button row never do, and the thread keeps a
   floor of its own so neither can eat the other. */
.composer {
  /* Shrinkable, but reluctantly: the thread below carries a shrink factor two
     hundred times larger, so it gives up its space first and the composer only
     starts yielding once the thread has hit its own floor. And because
     min-height stays `auto` — min-content — the part that yields is the
     attachment strip (which scrolls), never the field or the send button. */
  flex: 0 1 auto;
  display: flex; flex-direction: column;
  position: relative; z-index: 2;
  padding: 8px 14px calc(10px + var(--safe-b));
  padding-left: max(14px, calc(var(--safe-l) + 8px));
  padding-right: max(14px, calc(var(--safe-r) + 8px));
  background: color-mix(in srgb, var(--mb-bg) 86%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--mb-line-soft);
}
/* The on-screen keyboard already reserves the space, so the resting safe-area
   inset must not remain as a blank shelf above it. keyboard-intent covers the
   short interval before slower in-app browsers publish kb-open. */
body.kb-open .composer,
body.keyboard-intent .composer { padding-bottom: 8px; }
/* Keep the input card directly above the keys. The allowance returns after
   dismissal; it must not add a second footer between the card and the IME. */
body.kb-open .cmp-guest,
body.keyboard-intent .cmp-guest { display: none; }
.cmp-card {
  flex: 0 1 auto;
  width: 100%;
  max-width: 920px;
  margin-inline: auto;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  border-radius: var(--r-lg);
  padding: 10px 11px 9px;
  display: flex; flex-direction: column; gap: 6px;
  box-shadow: 0 8px 24px rgba(31,79,55,.05);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.cmp-card:focus-within {
  border-color: color-mix(in srgb, var(--mb-line) 50%, var(--mb-accent));
  box-shadow: 0 10px 28px rgba(31,79,55,.08), 0 0 0 3px color-mix(in srgb, var(--mb-accent) 10%, transparent);
}
/* min-height is a floor the autosize script cannot undercut: if the textarea
   is ever measured while its view is display:none it reports scrollHeight 0,
   and a collapsed field is invisible and untappable. */
.cmp-input {
  display: block;
  flex: none;
  width: 100%; box-sizing: border-box;
  border: 0; outline: none; background: none; resize: none;
  color: var(--mb-ink);
  font-family: inherit;
  font-size: 16px;                  /* ≥16px: prevents iOS focus zoom */
  line-height: 1.5;
  padding: 6px 4px 2px;
  min-height: 32px;
  /* chat.js clamps its autosize at 120px; on a short viewport — a small phone
     with the keyboard up — 120px is a third of everything there is, so the cap
     follows the app instead of ignoring it. max-height beats the inline height
     the autosize sets, so this holds either way. */
  max-height: min(120px, max(32px, calc(var(--app-h, 100dvh) * 0.16)));
  overflow-y: auto;
}
.cmp-input::placeholder { color: var(--mb-faint); }
/* signed-out allowance — the phone has no composer footer, so the line sits
   under the card. chat.js hides it the moment an account is attached. */
.cmp-guest {
  width: min(calc(100% - 12px), 908px); align-self: center;
  margin: 7px auto 0;
  font-size: 11.5px; line-height: 1.45;
  text-align: center;
  color: var(--mb-faint);
}
.cmp-guest b { color: var(--mb-deep); font-weight: 700; }
.cmp-guest button {
  font-size: inherit; font-weight: 700;
  color: var(--mb-deep);
  padding: 0;
  text-decoration: underline; text-underline-offset: 2px;
}
.cmp-row { flex: none; display: flex; align-items: center; gap: 4px; }
.cmp-btn {
  width: 44px; height: 44px; flex: none;
  border-radius: 9px; display: grid; place-items: center;
  color: var(--mb-faint);
  transition: background 0.28s cubic-bezier(.16,1,.3,1), color 0.28s cubic-bezier(.16,1,.3,1), transform 0.28s cubic-bezier(.16,1,.3,1);
}
.cmp-btn:active { background: var(--mb-mint); color: var(--mb-deep); transform: scale(0.96); }
.cmp-btn svg { width: 18px; height: 18px; }
.cmp-mode {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  height: 44px; padding: 0 6px;
  border-radius: 8px; border: 1px solid var(--mb-line);
  color: var(--mb-soft); font-size: 12.5px;
  transition: background 0.28s cubic-bezier(.16,1,.3,1), border-color 0.28s cubic-bezier(.16,1,.3,1), color 0.28s cubic-bezier(.16,1,.3,1);
}
.cmp-mode:active, .cmp-mode[aria-expanded="true"] { background: var(--mb-mint); border-color: var(--mb-mint-line); color: var(--mb-deep); }
.cmp-mode svg { width: 13px; height: 13px; }
/* the intent picker — replaced the Review chip, so the two things you actually
   change per message sit next to each other. It always shows the live choice
   so the composer states what Lemma is about to build. */
.cmp-intent {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  height: 44px; padding: 0 5px;
  border-radius: 8px;
  border: 1px solid var(--mb-mint-line);
  background: var(--mb-mint);
  color: var(--mb-deep);
  font-size: 12.5px; font-weight: 600;
  max-width: 42vw; white-space: nowrap;
  transition: background 0.28s cubic-bezier(.16,1,.3,1), border-color 0.28s cubic-bezier(.16,1,.3,1), transform 0.28s cubic-bezier(.16,1,.3,1);
}
.cmp-intent:active { transform: scale(.97); }
.cmp-intent[aria-expanded="true"] { background: var(--mb-accent); border-color: transparent; color: #fff; }
body.dark .cmp-intent[aria-expanded="true"] { color: #06120c; }
.cmp-intent__ic { display: grid; place-items: center; flex: none; }
.cmp-intent__ic svg { width: 14px; height: 14px; display: block; }
.cmp-intent__chev { width: 12px; height: 12px; flex: none; opacity: .7; }
.cmp-intent span:not(.cmp-intent__ic) { overflow: hidden; text-overflow: ellipsis; }
.cmp-send {
  width: 44px; height: 44px; flex: none;
  border-radius: 10px; display: grid; place-items: center;
  border: 1px solid transparent;
  background: var(--mb-accent); color: #fff;
  transition: background 0.28s cubic-bezier(.16,1,.3,1), transform 0.28s cubic-bezier(.16,1,.3,1), opacity 0.28s;
}
body.dark .cmp-send { color: #06120c; }
.cmp-send:active { transform: scale(.92); }
.cmp-send:disabled { opacity: .38; }
.cmp-send svg { width: 17px; height: 17px; }
.cmp-send--stop { background: var(--mb-danger); color: #fff; }
/* Everything staged for the next message. It is the one part of the card that
   may be given up when there is no room: min-height 0 plus its own scroller
   means the field and the send row are never the thing that goes. */
.cmp-attach {
  flex: 0 1 auto; min-height: 0;
  /* Two ceilings, whichever is lower. The first is a share of the app so the
     strip never dominates a tall screen; the second is what is actually left
     once the header, the conversation's floor and the field-plus-buttons have
     taken their part, so on a short viewport it reaches zero and the strip
     simply scrolls instead of pushing the send button off the bottom. */
  max-height: min(
    calc(var(--app-h, 100dvh) * 0.24),
    max(0px, calc(var(--app-h, 100dvh) - 360px))
  );
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: none;
  display: flex; flex-direction: column; gap: 7px; padding: 2px 2px 4px;
}
.cmp-attach::-webkit-scrollbar { display: none; }
.cmp-att-images { display: flex; gap: 7px; flex-wrap: wrap; }
.cmp-att-images img { width: 56px; height: 56px; object-fit: cover; border-radius: 10px; border: 1px solid var(--mb-line); }
.cmp-attach img { width: 56px; height: 56px; object-fit: cover; border-radius: 10px; border: 1px solid var(--mb-line); }
.cmp-attach > span {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px; border-radius: 9px;
  background: var(--mb-card-2); border: 1px solid var(--mb-line-soft);
  font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: var(--mb-soft);
}

/* ============ composer attached block chip ============ */
.cmp-att-box {
  display: flex;
  align-items: center;
  gap: 9px;
  background: color-mix(in srgb, var(--mb-mint) 75%, var(--mb-card));
  border: 1px solid var(--mb-mint-line);
  border-radius: 12px;
  padding: 7px 10px 7px 8px;
  margin-bottom: 3px;
  animation: attSlideIn .18s var(--ease);
}
body.dark .cmp-att-box {
  background: color-mix(in srgb, var(--mb-mint) 22%, var(--mb-card));
  border-color: rgba(255, 255, 255, 0.12);
}
@keyframes attSlideIn {
  from { opacity: 0; transform: translateY(-4px) scale(.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
.cmp-att-box__ic {
  width: 28px;
  height: 28px;
  flex: none;
  border-radius: 8px;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  display: grid;
  place-items: center;
  color: var(--mb-accent);
  box-shadow: 0 1px 3px rgba(0,0,0,.04);
}
body.dark .cmp-att-box__ic {
  background: var(--mb-card-2);
  border-color: var(--mb-line);
  color: var(--mb-accent);
}
.cmp-att-box__ic svg {
  width: 15px;
  height: 15px;
}
.cmp-att-box__info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.cmp-att-box__meta {
  display: flex;
  align-items: center;
  gap: 6px;
}
.cmp-att-box__tag {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--mb-accent);
}
/* A preview, not the block itself. `white-space: nowrap` keeps prose to one
   line, but a KaTeX `aligned` environment is a grid — it lays itself out four
   rows deep whatever the white-space is — so the height is capped here too.
   Past the cap it scrolls in place; the whole block is a tap away in the note.
   Without the cap the chip alone reached 120px and took the composer with it. */
.cmp-att-box__preview {
  font-size: 13.5px;
  color: var(--mb-ink);
  max-height: 46px;
  overflow: auto;
  overscroll-behavior: contain;
  white-space: nowrap;
  line-height: 1.35;
  scrollbar-width: none;
}
.cmp-att-box__preview::-webkit-scrollbar { display: none; }
.cmp-att-box__preview .att-math-rendered,
.cmp-att-box__preview .att-math-text {
  font-family: KaTeX_Main, Spectral, Georgia, serif;
  font-size: 13.5px;
  color: var(--mb-ink);
  display: inline-block;
  vertical-align: middle;
}
.cmp-att-box__preview .att-code-preview {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 12px;
  color: var(--mb-soft);
}
.cmp-att-box__preview .att-plain-preview {
  font-family: inherit;
  font-size: 13px;
  color: var(--mb-soft);
}
body.dark .cmp-att-box__preview {
  color: var(--mb-ink);
}
body.dark .cmp-att-box__preview .att-math-rendered,
body.dark .cmp-att-box__preview .att-math-text {
  color: var(--mb-ink);
}
body.dark .cmp-att-box__preview .att-code-preview,
body.dark .cmp-att-box__preview .att-plain-preview {
  color: #b5c2ba;
}
.cmp-att-box__del {
  width: 24px;
  height: 24px;
  flex: none;
  border-radius: 6px;
  display: grid;
  place-items: center;
  color: var(--mb-faint);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.cmp-att-box__del:active {
  background: rgba(0, 0, 0, 0.08);
  color: var(--mb-ink);
}
body.dark .cmp-att-box__del:active {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}
.cmp-att-box__del svg {
  width: 14px;
  height: 14px;
}

/* ============ a short app box ============
   main.js sets this class whenever the VISIBLE app drops under ~430px — a
   small phone with the keyboard up, or any phone held sideways. At that height
   the header, a readable conversation and a composer carrying an attachment
   genuinely do not all fit, and something has to give. What gives is
   decoration: the class line above the note name, the padding around the
   segment control, the signed-out footnote. The field and the send button are
   never negotiable — losing those is the bug this whole section exists to
   prevent. */
body.app-short .ch-top { padding-top: calc(var(--safe-t) + 6px); padding-bottom: 5px; }
body.app-short .ch-id__cls { display: none; }
body.app-short #note-seg { margin-top: 5px; margin-bottom: 0; padding: 3px; }
body.app-short #note-seg .seg__btn { height: 30px; }
body.app-short .cmp-guest { display: none; }
body.app-short .cmp-att-box { padding-top: 5px; padding-bottom: 5px; }
body.app-short .cmp-att-box__preview { max-height: 22px; }
/* The strip's own ceiling is written for the full-height header; once that
   header has been trimmed there is more room to give back, and an attachment
   you cannot see is barely better than one that pushed the send button off the
   screen. */
body.app-short .cmp-attach { max-height: max(0px, calc(var(--app-h, 100dvh) - 275px)); }
/* Under 300px there is nothing left to trim but content: a small phone held
   sideways with the keyboard open has about 160px of app. The attachment keeps
   its name and its remove button — you can still see what is staged and take
   it off — and gives up the formula preview, which is the one thing here you
   can read in the note instead. */
body.app-tiny .ch-top { padding-top: calc(var(--safe-t) + 3px); padding-bottom: 3px; }
body.app-tiny #note-seg { display: none; }
body.app-tiny .thread,
body.app-tiny .reader {
  min-height: 0;
  /* Their normal vertical padding alone is 26–40px. At keyboard heights below
     300px that padding was the last invisible flex floor keeping Send below
     the real viewport even after the reader itself was allowed to shrink. */
  padding-top: 0;
  padding-bottom: 0;
}
body.app-tiny .cmp-att-box__preview { display: none; }
body.app-tiny .cmp-att-box { padding: 4px 8px 4px 6px; }
body.app-tiny .cmp-att-box__ic { width: 22px; height: 22px; }
body.app-tiny .composer { padding-top: 5px; padding-bottom: 6px; }
body.app-tiny .cmp-card { padding: 6px 9px 6px; gap: 4px; }
body.app-tiny .cmp-attach { max-height: max(0px, calc(var(--app-h, 100dvh) - 235px)); }

/* A visible phone keyboard is its own short-layout signal even on tall Pro/XL
   devices. Compress secondary chrome so the conversation, not decoration,
   receives the space the keyboard leaves behind. */
body.kb-open .ch-top { padding-top: calc(var(--safe-t) + 6px); padding-bottom: 5px; }
body.kb-open .ch-id__cls { display: none; }
body.kb-open #note-seg { margin-top: 5px; margin-bottom: 0; padding: 3px; }
body.kb-open #note-seg .seg__btn { height: 34px; }

@media (max-width: 374px) {
  .composer {
    padding-left: max(9px, calc(var(--safe-l) + 6px));
    padding-right: max(9px, calc(var(--safe-r) + 6px));
  }
  .cmp-card { padding-left: 9px; padding-right: 9px; }
  .cmp-row { gap: 3px; }
  .cmp-mode { padding-left: 5px; padding-right: 5px; }
  .cmp-intent { gap: 4px; padding-left: 4px; padding-right: 4px; }
}

/* ============ composer popovers (effort · intent) ============
   One mechanic for both. They rise from the button they belong to and fall
   back into it, so the composer never appears to jump. Rows are full-width
   and 48px+ tall — these are thumb targets, not a desktop menu. */
.pop {
  position: absolute; bottom: calc(100% - 6px); z-index: 30;
  padding: 6px;
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: 15px; box-shadow: var(--sh-pop);
  animation: popIn .2s var(--ease);
  transform-origin: bottom left;
  /* on a short keyboard viewport the list can be taller than what's left
     above the composer — scroll inside rather than run off the top */
  max-height: calc(var(--app-h, 100dvh) - 130px);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.pop--mode   { left: 18px; min-width: 236px; max-width: calc(100vw - 36px); }
.pop--intent { left: 18px; right: 18px; }
.pop.is-closing { animation: popOut .14s ease forwards; pointer-events: none; }
@keyframes popIn  { from { opacity: 0; transform: translateY(8px) scale(.97); } }
@keyframes popOut { to   { opacity: 0; transform: translateY(6px) scale(.98); } }
.pop__label {
  margin: 5px 8px 6px;
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; color: var(--mb-faint);
}
.pop__list { display: flex; flex-direction: column; }
.pop__row {
  display: flex; align-items: center; gap: 11px;
  width: 100%; min-height: 48px; padding: 8px 9px;
  border-radius: 11px; text-align: left;
  transition: background .15s var(--ease);
}
.pop__row:active { background: var(--mb-mint); }
.pop__ic {
  width: 30px; height: 30px; flex: none;
  border-radius: 9px; display: grid; place-items: center;
  background: var(--mb-card-2); border: 1px solid var(--mb-line-soft);
  color: var(--mb-faint);
  transition: background .15s var(--ease), color .15s var(--ease), border-color .15s var(--ease);
}
.pop__ic svg { width: 15px; height: 15px; display: block; }
.pop__tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pop__tx b { font-size: 14px; font-weight: 600; color: var(--mb-ink); }
/* --mb-soft, not --mb-faint: these lines are the whole point of the menu, and
   faint-on-white lands at 3.6:1 which is below AA at this size */
.pop__tx small { font-size: 11.5px; line-height: 1.35; color: var(--mb-soft); }
.pop__tick {
  width: 18px; height: 18px; flex: none;
  border-radius: 50%; border: 1.5px solid var(--mb-line);
  position: relative;
  transition: background .18s var(--ease), border-color .18s var(--ease);
}
.pop__tick::after {
  content: ""; position: absolute; left: 5px; top: 3.5px;
  width: 4px; height: 8px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0);
  transition: transform .18s var(--ease);
}
body.dark .pop__tick::after { border-color: #06120c; }
/* mode rows use .is-active, intent rows use aria-checked — both land here */
.pop__row.is-active .pop__tx b,
.pop__row[aria-checked="true"] .pop__tx b { color: var(--mb-deep); }
.pop__row.is-active .pop__ic,
.pop__row[aria-checked="true"] .pop__ic {
  background: var(--mb-mint); border-color: var(--mb-mint-line); color: var(--mb-deep);
}
.pop__row.is-active .pop__tick,
.pop__row[aria-checked="true"] .pop__tick { background: var(--mb-accent); border-color: var(--mb-accent); }
.pop__row.is-active .pop__tick::after,
.pop__row[aria-checked="true"] .pop__tick::after { transform: rotate(45deg) scale(1); }
.pop__row:focus-visible { outline: 2px solid var(--mb-accent); outline-offset: -2px; }

/* ============ inline capture panels (inside the composer card) ============ */
/* Both of these carry their own primary action — "Make notes", "Stop &
   transcribe" — so unlike the attachment strip they are never the thing that
   gives way when the composer is squeezed. */
.shots, .rec {
  flex: none;
  background: var(--mb-card-2); border: 1px solid var(--mb-line-soft);
  border-radius: 12px; padding: 10px;
}
.shots__strip {
  display: flex; gap: 8px; overflow-x: auto; padding: 1px 1px 9px;
  scroll-snap-type: x proximity; scrollbar-width: thin;
}
.shot-file {
  position: relative; width: min(210px, 74vw); height: 64px; flex: none;
  display: flex; align-items: center; gap: 10px; padding: 7px 34px 7px 7px;
  border: 1px solid var(--mb-line); border-radius: 11px;
  background: var(--mb-card); scroll-snap-align: start; overflow: hidden;
}
.shot-file > img {
  width: 48px; height: 48px; flex: none; object-fit: cover;
  border-radius: 8px; border: 1px solid var(--mb-line-soft);
}
.shot-file__icon {
  width: 48px; height: 48px; flex: none; display: grid; place-items: center;
  border-radius: 8px; background: var(--mb-mint); color: var(--mb-deep);
  border: 1px solid var(--mb-mint-line);
  font-family: 'IBM Plex Mono', monospace; font-size: 10px; font-weight: 600; letter-spacing: .06em;
}
.shot-file__info { min-width: 0; display: flex; flex-direction: column; gap: 3px; text-align: left; }
.shot-file__info b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 600; }
.shot-file__info small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--mb-faint); font-size: 10.5px; }
.shot-file__remove {
  position: absolute; top: 4px; right: 4px; width: 28px; height: 28px;
  display: grid; place-items: center; border-radius: 50%; color: var(--mb-faint);
  font-size: 21px; line-height: 1;
}
.shot-file__remove:active { background: var(--mb-mint); color: var(--mb-ink); }
.shot-file.is-error { border-color: color-mix(in srgb, var(--mb-danger) 48%, var(--mb-line)); }
.shot-file.is-error .shot-file__icon { color: var(--mb-danger); background: color-mix(in srgb, var(--mb-danger) 10%, var(--mb-card)); border-color: color-mix(in srgb, var(--mb-danger) 28%, var(--mb-line)); }
.shot-file.is-error .shot-file__info small { color: var(--mb-danger); }
.shots__row, .rec__row { display: flex; gap: 8px; }
.shots__row > *, .rec__row > * { flex: 1; }
.rec__head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.rec__dot { width: 11px; height: 11px; border-radius: 50%; background: #c14a33; animation: mbblink 1.4s steps(2) infinite; }
.rec__head b { font-family: 'IBM Plex Mono', monospace; font-size: 1.1rem; }
.rec__hint { font-size: .72rem; color: var(--mb-faint); margin-left: auto; text-align: right; }

/* ============ queue (home) ============ */
.queue { margin-top: 22px; }
.queue__title { font-size: .85rem; color: var(--mb-soft); margin: 0 0 8px; display: flex; align-items: center; gap: 8px; }
.q-badge {
  min-width: 18px; height: 18px; border-radius: 999px;
  background: var(--c-amber); color: #fff;
  font-size: .66rem; line-height: 18px; text-align: center; padding: 0 5px;
}
.qitem {
  display: flex; align-items: center; gap: 10px;
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: var(--r-sm);
  padding: 11px 12px; margin-bottom: 8px;
  font-size: .86rem;
}
.qitem__kind { color: var(--mb-soft); }
.qitem__state { margin-left: auto; font-size: .76rem; color: var(--mb-faint); font-family: 'IBM Plex Mono', monospace; }
.qitem__state.err { color: var(--mb-danger); }

/* ============================================================
   SIGNED OUT
   ============================================================ */
.out {
  flex: 1; min-height: 0; position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0 34px; text-align: center;
  background-image: linear-gradient(rgba(22,32,26,.045) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(22,32,26,.045) 1px, transparent 1px);
  background-size: 26px 26px;
}
body.dark .out {
  background-image: linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px);
}
.out__mark {
  width: 58px; height: 58px; border-radius: 18px;
  background: var(--mb-card); border: 1px solid var(--mb-line);
  display: grid; place-items: center;
  box-shadow: 0 10px 30px -12px rgba(16,40,28,.18);
}
.out__mark img { width: 34px; height: 34px; object-fit: contain; }
.out h3 {
  margin: 20px 0 0; font-family: Spectral, Georgia, serif;
  font-size: 26px; font-weight: 500; letter-spacing: -.02em;
}
.out p { margin: 10px 0 0; font-size: 14.5px; line-height: 1.6; color: var(--mb-soft); max-width: 30ch; }
.out .btn-flow { margin-top: 26px; height: 52px; }
.out .linkish { margin-top: 14px; font-weight: 500; font-size: 13.5px; }
.out__meta {
  margin: 34px 0 0 !important;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--mb-faint);
}

/* ============================================================
   DRAWER
   ============================================================ */
.scrim {
  position: absolute; inset: 0; z-index: 80;
  background: rgba(16,32,26,.42); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  animation: scrimIn .22s ease;
}
@keyframes scrimIn { from { opacity: 0; } }
.drawer { position: fixed; left: 0; right: 0; top: var(--app-top, 0px); height: var(--app-h, 100dvh); z-index: 80; }
.drawer__panel {
  position: absolute; top: 0; left: 0; bottom: 0; z-index: 81;
  width: min(calc(312px + var(--safe-l)), 86vw);
  padding-left: var(--safe-l);
  background: var(--mb-card-2);
  border-right: 1px solid var(--mb-line);
  box-shadow: var(--sh-pop);
  display: flex; flex-direction: column;
  animation: drawerIn .28s var(--ease);
}
@keyframes drawerIn { from { transform: translateX(-100%); } }
.drawer__top { flex: none; padding: calc(var(--safe-t) + 12px) 14px 10px; display: flex; align-items: center; gap: 8px; }
.tag {
  font-family: 'IBM Plex Mono', monospace; font-size: 10px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--mb-deep); background: var(--mb-mint);
  padding: 6px 10px; border-radius: 9px;
}
.drawer__list {
  flex: 1; min-height: 0; overflow-y: auto; padding: 2px 8px 18px;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
}
.drawer__foot { flex: none; padding: 8px 12px calc(14px + var(--safe-b)); border-top: 1px solid var(--mb-line-soft); }
.btn-dashed {
  width: 100%; height: 44px;
  border-radius: 12px; border: 1px dashed var(--mb-mint-line);
  color: var(--mb-deep);
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 600; font-size: 13.5px;
}
.btn-dashed:active { background: var(--mb-mint); }
.btn-dashed svg { width: 16px; height: 16px; }
/* drawer tree rows */
.dw-cls { margin-bottom: 3px; }
.dw-cls__head {
  position: relative; display: flex; align-items: center; gap: 8px;
  height: 44px; padding: 0 8px; border-radius: 10px;
  transition: background .16s var(--ease), box-shadow .16s var(--ease);
}
.dw-cls__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.dw-cls__name { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dw-cls__code { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .08em; color: var(--mb-faint); flex: none; }
.dw-note {
  position: relative; width: 100%; height: 47px;
  display: flex; align-items: center; border-radius: 11px;
  color: var(--mb-soft); padding-left: var(--indent, 12px);
  transition: background .16s var(--ease), color .16s var(--ease), opacity .16s ease, transform .18s var(--ease), box-shadow .18s var(--ease);
}
.dw-note__open {
  min-width: 0; height: 100%; flex: 1; display: flex; align-items: center; gap: 9px;
  padding: 0 2px 0 8px; border-radius: inherit; color: inherit; text-align: left;
  touch-action: pan-y; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.dw-note__open > svg { width: 16px; height: 16px; flex: none; color: var(--mb-faint); }
.dw-note__text { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; }
.dw-note__text b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; font-weight: 500; }
.dw-note__text small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--mb-faint); font: 9px/1.2 'IBM Plex Mono', monospace; letter-spacing: .07em; text-transform: uppercase; }
.dw-note__more {
  width: 38px; height: 38px; margin-right: 1px; flex: none; border-radius: 10px;
  display: grid; place-items: center; color: var(--mb-faint);
  transition: background .15s var(--ease), color .15s var(--ease), opacity .15s ease;
}
.dw-note__more svg { width: 17px; height: 17px; }
.dw-note__more:active, .dw-note__more:focus-visible { background: var(--mb-card); color: var(--mb-deep); outline: none; }
.dw-note:active { background: var(--mb-mint); }
.dw-note.is-active { background: var(--mb-mint); color: var(--mb-deep); }
.dw-note.is-active .dw-note__text b { font-weight: 650; }
.dw-note.is-active .dw-note__open > svg { color: var(--mb-accent); }

.dw-folder {
  position: relative; width: 100%; height: 43px; display: flex; align-items: center; gap: 7px;
  padding: 0 8px 0 var(--indent, 5px); border-radius: 10px;
  color: var(--mb-soft); text-align: left;
  transition: background .16s var(--ease), box-shadow .16s var(--ease);
}
.dw-folder:active { background: color-mix(in srgb, var(--mb-mint) 70%, transparent); }
.dw-folder__chev { width: 18px; height: 18px; display: grid; place-items: center; color: var(--mb-faint); transition: transform .2s var(--ease); }
.dw-folder__chev svg { width: 13px; height: 13px; }
.dw-folder.is-open .dw-folder__chev { transform: rotate(90deg); }
.dw-folder__icon { width: 17px; height: 17px; color: var(--mb-accent); flex: none; }
.dw-folder__icon svg { width: 100%; height: 100%; }
.dw-folder__name { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; }
.dw-folder__count { min-width: 14px; color: var(--mb-faint); font: 9.5px/1 'IBM Plex Mono', monospace; text-align: right; }
.dw-folder__children { position: relative; }
.dw-folder__children::before {
  content: ""; position: absolute; top: 1px; bottom: 4px;
  left: var(--guide-left, 23px); width: 1px; background: var(--mb-line-soft);
}
.dw-folder__empty { margin: 0; padding: 5px 8px 8px 48px; color: var(--mb-faint); font-size: 10.5px; }

.dw-archive { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--mb-line-soft); }
.dw-archive__head {
  position: relative; min-height: 48px; display: flex; align-items: center; gap: 10px;
  padding: 5px 9px; border-radius: 11px; color: var(--mb-soft);
  transition: background .16s var(--ease), box-shadow .16s var(--ease);
}
.dw-archive__icon { width: 20px; height: 20px; display: grid; place-items: center; color: var(--mb-faint); }
.dw-archive__icon svg { width: 19px; height: 19px; }
.dw-archive__head > span:nth-child(2) { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; }
.dw-archive__head b { font-size: 13px; font-weight: 650; }
.dw-archive__head small { color: var(--mb-faint); font-size: 10.5px; }
.dw-archive__head > i { min-width: 18px; color: var(--mb-faint); font: normal 10px/1 'IBM Plex Mono', monospace; text-align: right; }
.dw-archive__empty { margin: 0; padding: 3px 12px 9px 39px; color: var(--mb-faint); font-size: 10.5px; line-height: 1.4; }
.dw-search-empty { margin: 5px 5px 9px; padding: 12px; border: 1px solid var(--mb-line-soft); border-radius: 11px; }

/* Hold, drag, and drop states. Home and the drawer share these exact states so
   a gesture never changes character when the user moves between surfaces. */
.dw-note.is-hold-ready, .lib__note.is-hold-ready {
  background: var(--mb-card); color: var(--mb-deep); transform: scale(.985);
  box-shadow: 0 0 0 2px var(--mb-mint-line), 0 8px 22px -15px rgba(16,40,28,.42);
}
.dw-note.is-drag-source, .lib__note.is-drag-source { opacity: .28; }
.note-drag-ghost {
  position: fixed; z-index: 118; margin: 0; pointer-events: none;
  display: flex; align-items: center; border-radius: 12px;
  color: var(--mb-deep);
  background: color-mix(in srgb, var(--mb-card) 82%, transparent);
  border: 1px solid color-mix(in srgb, var(--mb-mint-line) 78%, transparent);
  box-shadow: 0 20px 42px -18px rgba(11,34,23,.5), 0 7px 16px -12px rgba(11,34,23,.45), inset 0 1px rgba(255,255,255,.5);
  -webkit-backdrop-filter: blur(12px) saturate(1.15); backdrop-filter: blur(12px) saturate(1.15);
  opacity: .76; transform: scale(1.025) rotate(.35deg); overflow: hidden;
}
.note-drag-ghost--drawer { padding-left: 12px; }
.note-drag-ghost--home .lib__note-open, .note-drag-ghost--drawer .dw-note__open { pointer-events: none; }
.note-drag-ghost .lib__note-more, .note-drag-ghost .dw-note__more { opacity: .32; }
body.note-is-dragging, body.note-is-dragging .drawer__list, body.note-is-dragging .hm-body { cursor: grabbing; }
body.note-is-dragging { -webkit-user-select: none; user-select: none; }
.dw-note.is-drop-before::before, .dw-note.is-drop-after::after,
.lib__note.is-drop-before::before, .lib__note.is-drop-after::after {
  content: ""; position: absolute; z-index: 3; left: 10px; right: 9px; height: 3px;
  border-radius: 99px; background: var(--mb-accent); box-shadow: 0 0 0 3px var(--mb-mint);
}
.dw-note.is-drop-before::before, .lib__note.is-drop-before::before { top: -2px; }
.dw-note.is-drop-after::after, .lib__note.is-drop-after::after { bottom: -2px; }
.dw-cls__head.is-drop-inside, .dw-folder.is-drop-inside, .dw-archive__head.is-drop-inside,
.lib__head.is-drop-inside, .note-move-target.is-drop-inside {
  background: var(--mb-mint); box-shadow: inset 0 0 0 2px var(--mb-mint-line), 0 7px 18px -15px rgba(16,40,28,.35);
}
.dw-cls__head.is-drop-inside::after, .dw-folder.is-drop-inside::after, .dw-archive__head.is-drop-inside::after,
.lib__head.is-drop-inside::after, .note-move-target.is-drop-inside::after {
  content: "+"; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center;
  color: #fff; background: var(--mb-accent); font: 600 15px/1 sans-serif; box-shadow: 0 3px 10px rgba(16,40,28,.22);
}

/* Home drag destination tray. It stays out of the way until a real drag has
   started, then exposes nested folders without making Home permanently dense. */
.note-move-tray { position: fixed; inset: 0; z-index: 108; pointer-events: none; }
.note-move-tray__panel {
  position: absolute; left: max(10px, var(--safe-l)); right: max(10px, var(--safe-r));
  bottom: calc(var(--safe-b) + 82px); max-height: min(46dvh, 390px);
  display: flex; flex-direction: column; overflow: hidden; pointer-events: auto;
  border-radius: 22px; color: var(--mb-ink);
  background: color-mix(in srgb, var(--mb-card-2) 91%, transparent);
  border: 1px solid color-mix(in srgb, var(--mb-line) 78%, transparent);
  box-shadow: 0 30px 66px -24px rgba(7,25,16,.56), 0 12px 28px -20px rgba(7,25,16,.42), inset 0 1px rgba(255,255,255,.58);
  -webkit-backdrop-filter: blur(24px) saturate(1.18); backdrop-filter: blur(24px) saturate(1.18);
  opacity: 0; transform: translateY(20px) scale(.985);
  transition: opacity .18s ease, transform .24s var(--ease);
}
.note-move-tray.is-open .note-move-tray__panel { opacity: 1; transform: none; }
.note-move-tray.is-leaving .note-move-tray__panel { opacity: 0; transform: translateY(12px) scale(.99); }
.note-move-tray__head {
  flex: none; min-height: 67px; padding: 11px 13px; display: flex; align-items: center; gap: 10px;
  border-bottom: 1px solid var(--mb-line-soft);
}
.note-move-tray__mark {
  width: 39px; height: 39px; flex: none; border-radius: 12px; display: grid; place-items: center;
  color: var(--mb-deep); background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
}
.note-move-tray__mark svg { width: 19px; height: 19px; }
.note-move-tray__head > span:nth-child(2) { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.note-move-tray__head small { color: var(--mb-faint); font: 10px/1.15 'IBM Plex Mono', monospace; letter-spacing: .11em; text-transform: uppercase; }
.note-move-tray__head b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14.5px; font-weight: 650; }
.note-move-tray__head > i { color: var(--mb-faint); font: normal 10.5px/1.25 sans-serif; text-align: right; }
.note-move-tray__list { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 7px; }
.note-move-target {
  position: relative; min-height: 53px; padding: 6px 9px 6px calc(10px + var(--move-depth, 0) * 15px);
  display: flex; align-items: center; gap: 10px; border-radius: 13px;
  transition: background .14s var(--ease), box-shadow .14s var(--ease), transform .14s var(--ease);
}
.note-move-target + .note-move-target { margin-top: 2px; }
.note-move-target__icon { width: 30px; height: 30px; flex: none; display: grid; place-items: center; border-radius: 9px; color: var(--mb-deep); background: var(--mb-mint); }
.note-move-target__icon svg { width: 17px; height: 17px; }
.note-move-target__dot { width: 10px; height: 10px; margin: 0 10px; border-radius: 50%; box-shadow: 0 0 0 5px color-mix(in srgb, currentColor 8%, transparent); }
.note-move-target__text { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; }
.note-move-target__text b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; font-weight: 650; }
.note-move-target__text small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--mb-faint); font-size: 10.5px; }
.note-move-target > i { color: var(--mb-faint); font: normal 9px/1 'IBM Plex Mono', monospace; letter-spacing: .09em; text-transform: uppercase; }
.note-move-target--archive { margin-top: 7px; border-top: 1px solid var(--mb-line-soft); border-radius: 0 0 13px 13px; }
.note-move-target.is-drop-inside { transform: scale(.99); }

/* Contextual note menu */
.note-actions { position: fixed; inset: 0; z-index: 86; }
.note-actions__wash {
  position: absolute; inset: 0; background: rgba(12,27,20,.14);
  -webkit-backdrop-filter: blur(1.5px); backdrop-filter: blur(1.5px);
  animation: noteWashIn .16s ease both;
}
.note-actions__menu {
  position: fixed; z-index: 1; padding: 10px; border-radius: 20px;
  max-height: calc(100dvh - var(--safe-t) - var(--safe-b) - 20px); overflow-y: auto; overscroll-behavior: contain;
  background: color-mix(in srgb, var(--mb-card-2) 92%, transparent);
  border: 1px solid color-mix(in srgb, var(--mb-line) 82%, transparent);
  box-shadow: 0 30px 60px -25px rgba(9,28,18,.48), 0 10px 25px -16px rgba(9,28,18,.32), inset 0 1px rgba(255,255,255,.55);
  -webkit-backdrop-filter: blur(22px) saturate(1.2); backdrop-filter: blur(22px) saturate(1.2);
  transform-origin: 26px top; animation: noteMenuIn .2s var(--ease) both;
}
.note-actions__menu[data-placement="above"] { transform-origin: 26px bottom; }
.note-actions.is-closing .note-actions__wash { animation: noteWashOut .14s ease both; }
.note-actions.is-closing .note-actions__menu { animation: noteMenuOut .14s ease both; }
@keyframes noteWashIn { from { opacity: 0; } }
@keyframes noteWashOut { to { opacity: 0; } }
@keyframes noteMenuIn { from { opacity: 0; transform: translateY(-7px) scale(.965); } }
@keyframes noteMenuOut { to { opacity: 0; transform: translateY(-4px) scale(.98); } }
.note-actions__head { min-width: 0; display: flex; align-items: center; gap: 12px; padding: 8px 8px 13px; }
.note-actions__glyph {
  width: 41px; height: 41px; flex: none; border-radius: 13px; display: grid; place-items: center;
  color: var(--mb-deep); background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
}
.note-actions__glyph svg { width: 20px; height: 20px; }
.note-actions__head > span:last-child { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.note-actions__head small { color: var(--mb-faint); font: 10.5px/1.2 'IBM Plex Mono', monospace; letter-spacing: .1em; text-transform: uppercase; }
.note-actions__head b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--mb-ink); font-size: 15.5px; font-weight: 650; }
.note-actions__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.note-actions__grid > button {
  min-width: 0; min-height: 94px; padding: 10px; border-radius: 14px;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 7px; color: var(--mb-soft); text-align: left;
  border: 1px solid transparent; transition: background .14s var(--ease), border-color .14s var(--ease), transform .12s var(--ease), opacity .15s ease;
}
.note-actions__grid > button:active { transform: scale(.975); }
.note-actions__grid > button:focus-visible { outline: none; background: var(--mb-mint); border-color: var(--mb-mint-line); }
.note-actions__grid > button:disabled { opacity: .52; }
.note-actions__grid > button.is-busy .note-actions__icon { animation: noteBusy .8s linear infinite; }
@keyframes noteBusy { to { transform: rotate(360deg); } }
.note-actions__icon {
  width: 36px; height: 36px; flex: none; border-radius: 11px; display: grid; place-items: center;
  color: var(--mb-deep); background: var(--mb-mint);
}
.note-actions__icon svg { width: 18px; height: 18px; }
.note-actions__grid > button > span:last-child { min-width: 0; width: 100%; display: flex; flex-direction: column; gap: 2px; }
.note-actions__grid b { font-size: 15px; line-height: 1.2; font-weight: 650; }
.note-actions__grid small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--mb-faint); font-size: 11px; line-height: 1.3; }
.note-actions__grid .is-danger { color: var(--mb-danger); }
.note-actions__grid .is-danger .note-actions__icon { color: var(--mb-danger); background: color-mix(in srgb, var(--mb-danger) 10%, transparent); }
@media (hover:hover) {
  .dw-note__more, .lib__note-more { opacity: .58; }
  .dw-note:hover .dw-note__more, .dw-note__more:focus-visible,
  .lib__note:hover .lib__note-more, .lib__note-more:focus-visible { opacity: 1; }
  .note-actions__grid > button:hover { background: var(--mb-mint); border-color: var(--mb-mint-line); }
}
@media (max-width: 350px) {
  .note-actions__grid > button { min-height: 88px; padding: 9px; }
  .note-actions__grid b { font-size: 14.5px; }
  .note-actions__grid small { font-size: 10.5px; }
  .note-move-tray__head > i { display: none; }
}
@media (max-height: 420px) {
  .note-actions__head { padding-top: 5px; padding-bottom: 9px; }
  .note-actions__glyph { width: 36px; height: 36px; }
  .note-actions__grid > button { min-height: 74px; flex-direction: row; align-items: center; padding: 8px; gap: 8px; }
  .note-actions__icon { width: 32px; height: 32px; }
  .note-actions__grid b { font-size: 14.5px; }
  .note-actions__grid small { font-size: 10.5px; }
}

/* Rename/delete sheets */
.note-edit-sheet { text-align: center; }
.note-edit-sheet__mark {
  width: 44px; height: 44px; margin: 2px auto 12px; border-radius: 14px;
  display: grid; place-items: center; color: var(--mb-deep);
  background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
  box-shadow: 0 9px 24px -17px rgba(16,40,28,.4);
}
.note-edit-sheet__mark svg { width: 20px; height: 20px; }
.note-edit-sheet__mark--danger { color: var(--mb-danger); background: color-mix(in srgb, var(--mb-danger) 9%, var(--mb-card)); border-color: color-mix(in srgb, var(--mb-danger) 23%, var(--mb-line)); }
.note-edit-sheet .sheet__label { display: block; text-align: left; }
.note-edit-sheet .field { text-align: left; }
.note-edit-sheet__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-top: 8px; }
.note-edit-sheet__actions > button { width: 100%; height: 46px; }
.btn-danger {
  border-radius: 12px; color: #fff; background: var(--mb-danger); font-size: 14px; font-weight: 650;
  box-shadow: 0 8px 20px -13px color-mix(in srgb, var(--mb-danger) 75%, transparent);
  transition: transform .12s var(--ease), filter .15s ease;
}
.btn-danger:active { transform: scale(.98); filter: brightness(.94); }

/* ============ confirmations ============ */
.confirm {
  position: fixed; inset: 0; z-index: 180;
  display: grid; place-items: center;
  padding: calc(18px + var(--safe-t)) 18px calc(18px + var(--safe-b));
  box-sizing: border-box;
  background: rgba(11, 24, 18, .46);
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
}
.confirm__box {
  width: min(100%, 410px); box-sizing: border-box;
  padding: 22px 20px 18px;
  border: 1px solid var(--mb-line); border-radius: 20px;
  background: var(--mb-card-2); color: var(--mb-ink);
  box-shadow: 0 24px 70px -28px rgba(5, 20, 13, .62);
  animation: mb-confirm-in .24s var(--ease);
}
@keyframes mb-confirm-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }
.confirm__mark {
  width: 42px; height: 42px; display: grid; place-items: center;
  border-radius: 13px; color: var(--mb-deep);
  background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
}
.confirm__mark svg { width: 21px; height: 21px; }
.confirm__box h3 { margin: 15px 0 0; font: 500 23px/1.15 Spectral, Georgia, serif; letter-spacing: -.02em; }
.confirm__box p { margin: 8px 0 0; color: var(--mb-soft); font-size: 14px; line-height: 1.5; }
.confirm__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-top: 20px; }
.confirm__btn {
  min-height: 48px; padding: 0 14px;
  border: 1px solid var(--mb-line); border-radius: 13px;
  background: var(--mb-card); color: var(--mb-soft);
  font: 650 14px/1 'Hanken Grotesk', sans-serif;
}
.confirm__btn:active { transform: scale(.98); }
.confirm__btn:last-child { border-color: var(--mb-mint-line); background: var(--mb-accent); color: #fff; }
.confirm__btn--danger:last-child { border-color: var(--mb-danger); background: var(--mb-danger); }
body.dark .confirm__btn:last-child { color: #06120c; }
@media (prefers-reduced-motion: reduce) { .confirm__box { animation: none; } }

/* ============================================================
   SHEETS
   ============================================================ */
.sheet { position: fixed; left: 0; right: 0; top: var(--app-top, 0px); height: var(--app-h, 100dvh); z-index: 90; }
.sheet__card {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 91;
  box-sizing: border-box;
  max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;   /* a drag at the top belongs to the sheet */
  background: var(--mb-card-2);
  border-top: 1px solid var(--mb-line);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  padding: 10px 20px calc(34px + var(--safe-b));
  box-shadow: 0 -20px 60px -30px rgba(16,40,28,.4);
  animation: sheetIn .3s var(--ease);
}
@keyframes sheetIn { from { transform: translateY(100%); } }

/* ---- dismissal ----
   Overlays leave the way they arrived. main.js adds .is-closing and only sets
   [hidden] on animationend, so nothing ever vanishes mid-gesture. */
.sheet.is-closing, .drawer.is-closing { pointer-events: none; }
.sheet.is-closing .scrim, .drawer.is-closing .scrim { animation: scrimOut .22s ease forwards; }
.sheet.is-closing .sheet__card { animation: sheetOut .26s cubic-bezier(.36,0,.66,-.06) forwards; }
.drawer.is-closing .drawer__panel { animation: drawerOut .24s cubic-bezier(.36,0,.66,-.06) forwards; }
@keyframes scrimOut  { to { opacity: 0; } }
@keyframes sheetOut  { to { transform: translateY(100%); } }
@keyframes drawerOut { to { transform: translateX(-100%); } }
/* boxedit builds its sheets in JS with no .scrim child — dim from the container */
.bx-sheet { background: rgba(16,32,26,.42); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); animation: scrimIn .22s ease; }
.bx-sheet.is-closing { animation: scrimOut .22s ease forwards; }
/* The handle is both the drag affordance and a close button (overlay.js),
   so the 4px bar carries a finger-sized hit area around it. */
.sheet__grab {
  position: relative; width: 38px; height: 4px; border-radius: 99px;
  background: var(--mb-line); margin: 0 auto 16px; cursor: pointer;
  touch-action: none;
}
.sheet__grab::after { content: ""; position: absolute; inset: -14px -70px; }
.sheet__card h3 {
  margin: 0 2px; font-family: Spectral, Georgia, serif;
  font-size: 22px; font-weight: 500; letter-spacing: -.02em;
}
.sheet__sub { margin: 6px 2px 0; font-size: 13.5px; line-height: 1.5; color: var(--mb-soft); }
.sheet__sub a { color: var(--mb-deep); }
.sheet__sub--foot { margin-top: 14px; }
.sheet__label {
  margin: 20px 2px 7px;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--mb-faint);
}
.sheet__hint { margin: 6px 2px 0; font-size: 12px; line-height: 1.45; color: var(--mb-faint); }
.sheet__meta {
  margin: 16px 2px 0;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--mb-faint);
}
.sheet__actions { display: flex; gap: 10px; margin-top: 24px; }
.sheet__close { width: 100%; margin-top: 18px; }

/* attach options */
.opts { display: flex; flex-direction: column; gap: 9px; margin-top: 16px; }
.opt {
  display: flex; align-items: center; gap: 13px; width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--mb-line); border-radius: var(--r-md);
  background: var(--mb-card); text-align: left;
  box-shadow: 0 1px 2px rgba(16,40,28,.05);
  transition: background .15s var(--ease), border-color .15s var(--ease), transform .12s var(--ease);
}
.opt:active { border-color: var(--mb-mint-line); background: var(--mb-mint); transform: scale(.99); }
.opt__ic {
  width: 38px; height: 38px; flex: none;
  border-radius: var(--r-sm);
  background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
  color: var(--mb-deep); display: grid; place-items: center;
}
.opt__ic svg { width: 19px; height: 19px; }
.opt__tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.opt__tx b { font-size: 14.5px; font-weight: 600; }
.opt__tx small { font-size: 12px; color: var(--mb-faint); }
.opt__chev { color: var(--mb-faint); font-size: 17px; }

/* colour swatches */
.swatches { display: flex; gap: 10px; flex-wrap: wrap; }
.swatch {
  width: 44px; height: 44px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--mb-card); border: 1px solid var(--mb-line);
  transition: box-shadow .15s var(--ease);
}
.swatch i { width: 14px; height: 14px; border-radius: 50%; display: block; }
.swatch.is-active { box-shadow: 0 0 0 3px var(--mb-mint), 0 0 0 4px var(--mb-mint-line); }

/* segmented controls */
.seg { display: flex; gap: 5px; }
.seg--boxed { padding: 4px; background: var(--mb-card); border: 1px solid var(--mb-line); border-radius: 13px; }
.seg--wrap { flex-wrap: wrap; }
.seg--wrap .seg__btn { flex: 1 1 28%; }
.seg__btn {
  flex: 1; height: 44px; border-radius: 10px;
  display: grid; place-items: center;
  font-size: 13.5px; font-weight: 500;
  color: var(--mb-soft);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.seg__btn.is-active { background: var(--mb-mint); color: var(--mb-deep); }

/* switch row — a preference, not a per-message control (Review lives here) */
.sw-stack { display: flex; flex-direction: column; gap: 8px; }
.sw-row {
  display: flex; align-items: center; gap: 14px; width: 100%;
  padding: 13px 14px;
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: 13px; text-align: left;
  transition: border-color .18s var(--ease);
}
.sw-row[aria-pressed="true"] { border-color: var(--mb-mint-line); }
.sw-row__tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sw-row__tx b { font-size: 14.5px; font-weight: 600; }
.sw-row__tx small { font-size: 12px; line-height: 1.4; color: var(--mb-faint); }
.sw-track {
  width: 46px; height: 28px; flex: none; border-radius: 999px;
  background: var(--mb-line); position: relative; display: block;
  transition: background .22s var(--ease);
}
.sw-track b {
  position: absolute; top: 3px; left: 3px;
  width: 22px; height: 22px; border-radius: 50%;
  background: #fff; display: block;
  box-shadow: 0 1px 3px rgba(16,40,28,.32);
  transition: left .24s var(--ease);
}
.sw-row[aria-pressed="true"] .sw-track { background: var(--mb-accent); }
.sw-row[aria-pressed="true"] .sw-track b { left: 21px; }
/* the Note|Chat segment sits inline in the chat view */
#note-seg { flex: none; margin: 10px 16px 2px; position: relative; z-index: 2; padding: 4px; background: var(--mb-card); border: 1px solid var(--mb-line); border-radius: 13px; }

/* fields */
.field {
  width: 100%; box-sizing: border-box; height: 50px;
  font-size: 16px; font-family: inherit; color: var(--mb-ink);
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: 13px; padding: 0 14px; margin-bottom: 10px;
  outline: none;
}
.field--focusring { border-color: var(--mb-mint-line); box-shadow: 0 0 0 4px var(--mb-mint); }
/* 16px for the same reason as .searchbar input: anything smaller and iOS
   zooms the page the moment the field takes focus. */
.field--mono { height: 46px; font-family: 'IBM Plex Mono', monospace; font-size: 16px; letter-spacing: .06em; }
.field:focus { border-color: var(--mb-accent); }
.auth-err { color: var(--mb-danger); font-size: .85rem; margin: 0 0 10px; }
.linkish { color: var(--mb-deep); font-size: inherit; font-family: inherit; padding: 0; font-weight: 500; }
.linkish--block { display: block; margin: 16px 2px 0; font-size: 13.5px; }

/* account row inside settings */
.acct {
  display: flex; align-items: center; gap: 12px;
  margin-top: 18px; padding: 12px 13px;
  background: var(--mb-card); border: 1px solid var(--mb-line); border-radius: var(--r-md);
}
.acct__avatar {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  background: var(--mb-accent); color: #fff;
  display: grid; place-items: center; font-weight: 600; font-size: 14px;
}
body.dark .acct__avatar { color: #06120c; }
.acct__who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.acct__who b { font-size: 14.5px; font-weight: 600; }
.acct__who small { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: var(--mb-faint); overflow: hidden; text-overflow: ellipsis; }

/* ============ buttons ============ */
.btn-soft {
  background: var(--mb-card); color: var(--mb-soft);
  border: 1px solid var(--mb-line); border-radius: var(--r-md);
  height: 50px; padding: 0 20px;
  display: grid; place-items: center;
  font-weight: 600; font-size: 15px;
  transition: transform .12s var(--ease), background .15s var(--ease);
}
.btn-soft:active { transform: scale(.98); background: var(--mb-mint); }
.btn-soft--wide { flex: none; width: 100px; }

/* ============ note reader ============ */
.reader {
  /* same floor as .thread: the note stays readable no matter how much the
     composer has staged below it */
  flex: 1 200 auto; min-height: min(72px, 16%); position: relative; z-index: 1;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 16px 18px 24px;
}
.rd-block { margin: 0 0 16px; }
/* Native paint/layout skipping, but only on notes reader.js is NOT already
   virtualizing (it takes over past 90 blocks and adds .is-virtual). Running
   both at once had them fighting: a block the browser had stopped rendering
   measures as its intrinsic size, so the observer stored 72px as the "real"
   height, released it, watched it grow back, and scrolled the note out from
   under the reader on every pass. One mechanism per note. */
.reader:not(.is-virtual) .rd-block {
  content-visibility: auto;
  contain-intrinsic-size: auto 72px;
}
.rd-block--pending {
  box-sizing: border-box;
  contain: strict;
  pointer-events: none;
}
.rd-text { font-size: .97rem; line-height: 1.6; }
.rd-text h1, .rd-text h2, .rd-text h3, .rd-text h4 { font-family: Spectral, Georgia, serif; font-weight: 600; margin: 0 0 6px; }
.rd-text ul, .rd-text ol { padding-left: 22px; margin: 6px 0; }
.rd-math {
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: var(--r-sm); padding: 12px 14px;
  overflow-x: auto; overflow-y: hidden;
}
.rd-math .katex-display { margin: 0; }
/* KaTeX only reports an error by colouring the source red; a formula that
   somehow still fails should read as a quiet fallback, not an alarm */
.rd-math .katex-error, .rd-flow .katex-error {
  color: var(--mb-faint); font-family: 'IBM Plex Mono', monospace;
  font-size: .82rem; border-bottom: 1px dotted var(--mb-line);
}

/* ---- re-joined sentence: prose with its formulas set inline ---- */
.rd-flow {
  margin: 0; font-size: .97rem; line-height: 1.75;
  /* a long formula scrolls inside the line instead of widening the page */
  overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
}
.rd-flow__part { display: inline; }
.rd-flow__part--math {
  display: inline-block; vertical-align: -.18em;
  padding: 1px 5px; margin: 0 1px;
  border-radius: 6px; background: var(--mb-mint);
}
.rd-flow__part--math .katex { font-size: 1.02em; }
.rd-block--flow.rd-block--live.is-press .rd-flow__part--math { background: var(--mb-card); }

/* ---- graphs render for real on the phone ---- */
.rd-graph {
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: var(--r-sm); padding: 10px 10px 8px;
}
.rd-graph__cv { display: block; width: 100%; border-radius: 8px; }
.rd-graph__cap {
  display: block; margin-top: 8px;
  font-family: 'IBM Plex Mono', monospace; font-size: .74rem;
  color: var(--mb-faint); word-break: break-word;
}

/* ---- ink strokes, drawn rather than described ---- */
.rd-ink {
  background: var(--mb-card); border: 1px solid var(--mb-line);
  border-radius: var(--r-sm); padding: 10px;
  color: var(--mb-ink, currentColor);
}
.rd-ink__svg { display: block; width: 100%; height: auto; }

/* wide tables scroll in their own lane; the page never does */
.rd-tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border-radius: var(--r-sm); }
.rd-code {
  background: #10231a; color: #dff0e4;
  border-radius: var(--r-sm); padding: 12px 14px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: .8rem; line-height: 1.55;
  overflow-x: auto; white-space: pre;
}
.rd-code__lang { display: block; font-size: .68rem; color: #8fb59d; margin-bottom: 6px; text-transform: uppercase; letter-spacing: .08em; }
.rd-table { width: 100%; border-collapse: collapse; font-size: .86rem; background: var(--mb-card); border-radius: var(--r-sm); overflow: hidden; }
.rd-table th, .rd-table td { border: 1px solid var(--mb-line); padding: 8px 10px; text-align: left; }
.rd-table th { background: var(--mb-mint); font-weight: 600; }
.rd-img { max-width: 100%; border-radius: var(--r-sm); border: 1px solid var(--mb-line); }
.rd-chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--mb-card); border: 1px dashed var(--mb-line);
  border-radius: var(--r-sm); padding: 12px 16px;
  color: var(--mb-faint); font-size: .85rem;
}
.rd-block--live { position: relative; border-radius: var(--r-sm); transition: background .15s var(--ease); padding: 2px; margin-left: -2px; margin-right: -2px; }
.rd-block--live.is-press { background: rgba(28,124,84,.08); }
body.dark .rd-block--live.is-press { background: rgba(63,167,118,.12); }
.rd-block.rd-block--highlight {
  animation: rdBlockPulse 2.2s var(--ease) forwards;
  border-radius: 12px;
}
@keyframes rdBlockPulse {
  0% {
    box-shadow: 0 0 0 0 rgba(28, 124, 84, 0);
    background: transparent;
  }
  20% {
    box-shadow: 0 0 0 4px var(--mb-mint-line), 0 4px 16px rgba(28, 124, 84, 0.18);
    background: var(--mb-mint);
  }
  70% {
    box-shadow: 0 0 0 4px var(--mb-mint-line), 0 4px 16px rgba(28, 124, 84, 0.12);
    background: var(--mb-mint);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(28, 124, 84, 0);
    background: transparent;
  }
}
body.dark .rd-block.rd-block--highlight {
  animation-name: rdBlockPulseDark;
}
@keyframes rdBlockPulseDark {
  0% {
    box-shadow: 0 0 0 0 rgba(63, 167, 118, 0);
    background: transparent;
  }
  20% {
    box-shadow: 0 0 0 4px var(--mb-mint-line), 0 4px 16px rgba(63, 167, 118, 0.25);
    background: var(--mb-mint);
  }
  70% {
    box-shadow: 0 0 0 4px var(--mb-mint-line), 0 4px 16px rgba(63, 167, 118, 0.18);
    background: var(--mb-mint);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(63, 167, 118, 0);
    background: transparent;
  }
}
.rd-empty { text-align: center; color: var(--mb-faint); padding: 48px 20px; font-size: .92rem; }
.rd-loading {
  min-height: 52vh; padding: 44px 24px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; color: var(--mb-faint);
}
.rd-loading__mark { height: 32px; display: flex; align-items: center; gap: 5px; margin-bottom: 16px; }
.rd-loading__mark i {
  width: 7px; height: 7px; border-radius: 50%; background: var(--mb-accent);
  animation: rdLoading 1s ease-in-out infinite;
}
.rd-loading__mark i:nth-child(2) { animation-delay: .13s; }
.rd-loading__mark i:nth-child(3) { animation-delay: .26s; }
.rd-loading b { color: var(--mb-ink); font: 600 18px/1.2 Spectral, Georgia, serif; }
.rd-loading small { max-width: 270px; margin-top: 7px; font-size: 12.5px; line-height: 1.45; }
@keyframes rdLoading { 0%, 70%, 100% { transform: translateY(0); opacity: .35; } 35% { transform: translateY(-7px); opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .lib__note.is-opening .lib__note-open > svg,
  .dw-note.is-opening .dw-note__open > svg,
  .rd-loading__mark i { animation: none; opacity: .7; }
}

/* ============ box action sheet + editor ============ */
.bx-menu__label { font-size: .78rem; font-weight: 600; color: var(--mb-faint); text-transform: uppercase; letter-spacing: .06em; margin: 0 0 10px; }
.bx-menu__list { display: flex; flex-direction: column; gap: 2px; margin-bottom: 12px; }
.bx-act {
  display: flex; align-items: center; gap: 14px;
  width: 100%; padding: 13px 8px;
  border-radius: 12px;
  font-size: .98rem; color: var(--mb-ink); text-align: left;
}
.bx-act:active { background: var(--mb-mint); }
.bx-act__ic { width: 34px; height: 34px; border-radius: 10px; background: var(--mb-mint); border: 1px solid var(--mb-mint-line); color: var(--mb-deep); display: grid; place-items: center; flex: none; }
.bx-act__ic svg { width: 19px; height: 19px; }
.bx-act--danger { color: var(--mb-danger); }
.bx-act--danger .bx-act__ic { background: rgba(180,85,63,.12); border-color: rgba(180,85,63,.25); color: var(--mb-danger); }
/* the sheet already lives inside the visual viewport — no keyboard inset needed */
.bx-editor { max-height: 100%; display: flex; flex-direction: column; padding-bottom: calc(16px + var(--safe-b)); }
body.kb-open .bx-editor { padding-bottom: 16px; }
.bx-editor__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.bx-editor__head b { font-size: .98rem; }
.bx-ed-save { background: var(--mb-accent); color: #fff; border-radius: 999px; padding: 8px 18px; font-weight: 600; font-size: .9rem; }
body.dark .bx-ed-save { color: #06120c; }
.bx-editor__body { overflow-y: auto; -webkit-overflow-scrolling: touch; }
.bx-fmt { display: flex; gap: 6px; margin-bottom: 10px; }
.bx-fmt button { width: 40px; height: 36px; border-radius: 10px; border: 1px solid var(--mb-line); background: var(--mb-card); color: var(--mb-ink); font-size: 1rem; }
.bx-fmt button:active { background: var(--mb-mint); }
.bx-ce {
  min-height: 120px; font-size: 16px; line-height: 1.6;
  background: var(--mb-card); border: 1px solid var(--mb-line); border-radius: var(--r-sm);
  padding: 12px 14px; outline: none; color: var(--mb-ink);
}
.bx-ce:focus { border-color: var(--mb-accent); }
.bx-ta { width: 100%; box-sizing: border-box; min-height: 120px; height: auto; resize: vertical; padding: 12px 14px; }
/* 16px, like every other field: below that iOS zooms the page on focus and
   the fixed shell starts re-measuring on every pan. */
.bx-mono { font-family: 'IBM Plex Mono', monospace; font-size: 16px; }
.bx-langsel { width: auto; height: 44px; margin-bottom: 10px; }
.bx-hint { font-size: .8rem; color: var(--mb-faint); margin: 0 0 8px; }
.bx-mathprev {
  background: var(--mb-card); border: 1px solid var(--mb-line); border-radius: var(--r-sm);
  padding: 14px; margin-bottom: 10px; min-height: 54px;
  display: grid; place-items: center; overflow-x: auto;
}
.bx-mathprev .katex-display { margin: 0; }

/* ============ note builder (notegen-ui.js) ============
   The surface you watch while Lemma writes a note. Pinned to the app box
   (--app-top/--app-h) like every other overlay, so the keyboard can't leave
   it stranded behind the composer. z-index sits above the sheets and below
   the toasts, because a toast about the finished note has to clear it. */
.ngen {
  position: fixed; left: 0; right: 0;
  top: var(--app-top, 0px); height: var(--app-h, 100dvh);
  z-index: 94;
  display: flex; align-items: flex-end; justify-content: center;
}
.ngen__scrim {
  position: absolute; inset: 0;
  background: rgba(16, 32, 26, .44);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  animation: scrimIn .22s ease;
}
body.dark .ngen__scrim { background: rgba(0, 0, 0, .58); }
.ngen__card {
  position: relative; z-index: 1;
  width: 100%; box-sizing: border-box;
  max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;   /* a drag at the top belongs to the sheet */
  background: var(--mb-card-2);
  border-top: 1px solid var(--mb-line);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  padding: 22px 20px calc(22px + var(--safe-b));
  box-shadow: 0 -20px 60px -30px rgba(16, 40, 28, .4);
  animation: sheetIn .3s var(--ease);
}
.ngen.is-closing { pointer-events: none; }
.ngen.is-closing .ngen__scrim { animation: scrimOut .22s ease forwards; }
.ngen.is-closing .ngen__card { animation: sheetOut .26s cubic-bezier(.36,0,.66,-.06) forwards; }

.ngen__head { display: flex; align-items: center; gap: 14px; }
.ngen__id { min-width: 0; flex: 1; }
.ngen__eyebrow {
  margin: 0; font-size: 11px; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--mb-faint);
}
.ngen__title {
  margin: 4px 0 0;
  font-family: Spectral, Georgia, serif; font-size: 21px; font-weight: 500;
  letter-spacing: -.02em; line-height: 1.25; color: var(--mb-ink);
  /* the title is swapped for the note's real name mid-run — two lines, then
     ellipsis, so a long name can never push the buttons off a short screen */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* the orb: two counter-rotating rings around a spark, the same visual
   language as the tour's orbit — it stops the moment the work does */
.ngen__orb {
  position: relative; flex: none;
  width: 46px; height: 46px; display: grid; place-items: center;
  border-radius: 50%;
  background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
}
.ngen__orb i {
  position: absolute; inset: 4px;
  border-radius: 50%; border: 1.5px solid transparent;
  border-top-color: var(--mb-accent);
}
.ngen__orb i:last-child {
  inset: 10px; border-top-color: transparent;
  border-bottom-color: color-mix(in srgb, var(--mb-accent) 55%, transparent);
}
.ngen__orb b { font-size: 13px; color: var(--mb-deep); line-height: 1; }
/* the rings stop and the spark becomes a verdict when the run ends */
.ngen__card[data-phase="done"] .ngen__orb i,
.ngen__card[data-phase="error"] .ngen__orb i { display: none; }
.ngen__card[data-phase="done"] .ngen__orb b,
.ngen__card[data-phase="error"] .ngen__orb b { font-size: 19px; font-weight: 700; }
.ngen__card[data-phase="error"] .ngen__orb {
  background: color-mix(in srgb, var(--mb-danger) 12%, var(--mb-card));
  border-color: color-mix(in srgb, var(--mb-danger) 34%, var(--mb-line));
}
.ngen__card[data-phase="error"] .ngen__orb b { color: var(--mb-danger); }

/* progress bar — the fill is driven from JS, the sheen is decoration and is
   removed the instant the run ends so a finished bar looks finished */
.ngen__bar {
  position: relative; overflow: hidden;
  margin: 18px 0 4px; height: 6px; border-radius: 99px;
  background: var(--mb-line-soft);
}
.ngen__bar > i {
  display: block; height: 100%; width: 4%;
  border-radius: 99px;
  background-image: var(--mb-flow);
  background-size: 220% 100%;
  transition: width .45s var(--ease);
}
.ngen__card[data-phase="error"] .ngen__bar > i { background-image: none; background-color: var(--mb-danger); }

.ngen__steps { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 9px; }
.ngen__step {
  display: flex; align-items: center; gap: 11px;
  font-size: 13.5px; color: var(--mb-faint);
  transition: color .2s var(--ease);
}
.ngen__dot {
  flex: none; width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--mb-line);
  background: var(--mb-card);
  display: grid; place-items: center;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.ngen__step-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ngen__step-note {
  margin-left: auto; flex: none;
  font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 500;
  color: var(--mb-deep);
}
.ngen__step[data-state="active"] { color: var(--mb-ink); font-weight: 600; }
.ngen__step[data-state="active"] .ngen__dot {
  border-color: var(--mb-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--mb-accent) 16%, transparent);
}
.ngen__step[data-state="active"] .ngen__dot::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--mb-accent);
}
.ngen__step[data-state="done"] { color: var(--mb-soft); }
.ngen__step[data-state="done"] .ngen__dot { border-color: var(--mb-accent); background: var(--mb-accent); }
.ngen__step[data-state="done"] .ngen__dot::after {
  content: ""; width: 4px; height: 7px; margin-top: -2px;
  border: solid #fff; border-width: 0 1.7px 1.7px 0; transform: rotate(45deg);
}
body.dark .ngen__step[data-state="done"] .ngen__dot::after { border-color: #06120c; }
.ngen__step[data-state="error"] { color: var(--mb-danger); font-weight: 600; }
.ngen__step[data-state="error"] .ngen__dot { border-color: var(--mb-danger); background: var(--mb-danger); }

.ngen__meta {
  margin: 14px 0 0; min-height: 16px;
  font-size: 12px; color: var(--mb-faint);
}
.ngen__card[data-phase="error"] .ngen__meta { color: var(--mb-soft); }
.ngen__row { display: flex; gap: 8px; margin-top: 16px; }
.ngen__row > * { flex: 1; }
.ngen__row .btn-soft { height: 44px; font-size: 14.5px; }
.ngen__row .btn-soft:disabled { opacity: .55; }

@media (prefers-reduced-motion: no-preference) {
  .ngen__orb i { animation: mbspin 2.6s linear infinite; }
  .ngen__orb i:last-child { animation: mbspin 1.9s linear infinite reverse; }
  .ngen__card[data-phase="running"] .ngen__bar::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent);
    transform: translateX(-100%);
    animation: ngenSheen 1.5s ease-in-out infinite;
  }
  body.dark .ngen__card[data-phase="running"] .ngen__bar::after {
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.16), transparent);
  }
  @keyframes ngenSheen { to { transform: translateX(100%); } }
}
/* a very short phone still has to show the buttons */
@media (max-height: 620px) {
  .ngen__card { padding-top: 16px; }
  .ngen__title { font-size: 19px; -webkit-line-clamp: 1; }
  .ngen__steps { gap: 7px; }
  .ngen__bar { margin-top: 14px; }
}

/* ============ toasts ============ */
/* Anchored to the app box, not the layout viewport: `bottom` alone resolves
   against the full page, so with the keyboard open toasts land behind it. */
#toasts {
  position: fixed; left: 0; right: 0;
  top: var(--app-top, 0px); height: var(--app-h, 100dvh);
  z-index: 95;
  display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
  gap: 8px; padding-bottom: calc(104px + var(--safe-b));
  pointer-events: none;
}
body.kb-open #toasts { padding-bottom: 104px; }
.toast {
  pointer-events: auto;
  max-width: 92vw;
  background: var(--mb-ink); color: var(--mb-bg);
  border-radius: 999px; padding: 10px 18px;
  font-size: .86rem;
  display: flex; align-items: center; gap: 12px;
  box-shadow: var(--sh-pop);
  transition: opacity .2s;
  animation: toastIn .28s var(--ease);
}
@keyframes toastIn { from { opacity: 0; transform: translateY(10px) scale(.96); } }
body.dark .toast { background: var(--mb-card); color: var(--mb-ink); border: 1px solid var(--mb-line); }
.toast button { color: var(--mb-accent); font-weight: 700; font-size: .86rem; padding: 0; }

/* ============ colour theme picker ============ */
.theme-palette {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
}
.theme-choice {
  min-width: 0; padding: 10px 5px 9px;
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  border-radius: 13px; border: 1px solid var(--mb-line);
  background: var(--mb-card); color: var(--mb-faint);
  font-size: 10.5px; font-weight: 600;
  transition: border-color .18s var(--ease), background .18s var(--ease), transform .16s var(--ease);
}
.theme-choice:active { transform: scale(.96); }
.theme-choice i {
  position: relative; width: 24px; height: 24px; border-radius: 50%; display: block;
  background: var(--choice); box-shadow: inset 0 0 0 1px rgba(255,255,255,.35), 0 3px 9px color-mix(in srgb, var(--choice) 28%, transparent);
}
.theme-choice i::after {
  content: ""; position: absolute; inset: -5px; border-radius: inherit;
  border: 2px solid transparent; transition: border-color .18s var(--ease), transform .18s var(--ease);
}
.theme-choice[data-accent-choice="forest"] { --choice: #1c7c54; }
.theme-choice[data-accent-choice="ocean"] { --choice: #256f92; }
.theme-choice[data-accent-choice="violet"] { --choice: #7657a6; }
.theme-choice[data-accent-choice="sunset"] { --choice: #bd5a3d; }
.theme-choice[aria-checked="true"] { color: var(--mb-ink); border-color: var(--mb-mint-line); background: var(--mb-mint); }
.theme-choice[aria-checked="true"] i::after { border-color: var(--choice); transform: scale(1.02); }
.settings-tour-row { margin-top: 12px; }
.settings-tour-row .sw-row__tx b::before { content: "✦"; color: var(--mb-accent); margin-right: 7px; }

/* ============================================================
   FIRST-RUN TOUR — live spotlight + premium guided cards
   ============================================================ */
body.mb-tour-open { touch-action: none; }
.mb-tour {
  position: fixed; left: 0; right: 0; top: var(--app-top, 0px); height: var(--app-h, 100dvh);
  z-index: 120; opacity: 0; pointer-events: none;
  transition: opacity .32s ease;
}
.mb-tour.is-open { opacity: 1; pointer-events: auto; }
.mb-tour__wash {
  position: absolute; inset: 0;
  background:
    radial-gradient(circle at 82% 14%, color-mix(in srgb, var(--mb-accent) 24%, transparent), transparent 30%),
    linear-gradient(160deg, rgba(4,13,9,.18), rgba(4,13,9,.42));
  transition: background .4s ease;
}
.mb-tour.is-celebrating .mb-tour__wash {
  background: radial-gradient(circle at 50% 48%, color-mix(in srgb, var(--mb-accent) 42%, transparent), rgba(4,13,9,.28) 58%);
}
.mb-tour__hole {
  position: fixed; z-index: 1;
  box-shadow: 0 0 0 200vmax rgba(5,12,9,.69), 0 0 0 1px color-mix(in srgb, var(--mb-accent) 76%, white),
    0 0 30px color-mix(in srgb, var(--mb-accent) 35%, transparent);
  transition: left .48s var(--ease), top .48s var(--ease), width .48s var(--ease), height .48s var(--ease), border-radius .3s var(--ease);
  pointer-events: none;
}
.mb-tour__hole::after {
  content: ""; position: absolute; inset: -7px; border-radius: inherit;
  border: 1px solid color-mix(in srgb, var(--mb-accent) 72%, white);
  opacity: .7; animation: mbTourPulse 2.2s ease-in-out infinite;
}
.mb-tour__hole.is-closed { left: 50% !important; top: 42% !important; width: 0 !important; height: 0 !important; box-shadow: 0 0 0 200vmax rgba(5,12,9,.72); }
.mb-tour__hole.is-closed::after { display: none; }
@keyframes mbTourPulse { 50% { opacity: .16; transform: scale(1.035); } }

.mb-tour__card {
  --card-shift: 22px;
  --tour-card-y: 14px;
  position: absolute; z-index: 2; left: 14px; right: 14px; top: 0; bottom: auto;
  width: min(430px, calc(100% - 28px)); max-height: calc(100% - 28px - var(--safe-t) - var(--safe-b));
  margin: 0 auto; overflow: hidden;
  display: flex; flex-direction: column;
  border-radius: 27px; border: 1px solid color-mix(in srgb, var(--mb-line) 74%, white);
  background: color-mix(in srgb, var(--mb-card-2) 96%, transparent);
  color: var(--mb-ink);
  box-shadow: 0 40px 100px -30px rgba(2,9,6,.76), 0 10px 34px -18px rgba(2,9,6,.48), inset 0 1px rgba(255,255,255,.52);
  backdrop-filter: blur(24px) saturate(1.3);
  -webkit-backdrop-filter: blur(24px) saturate(1.3);
  opacity: 0; transform: translate3d(0, calc(var(--tour-card-y) + var(--card-shift)), 0) scale(.975);
  transition: opacity .34s ease, transform .52s var(--ease), height .44s var(--ease);
  will-change: transform, height;
}
.mb-tour.is-open .mb-tour__card { opacity: 1; transform: translate3d(0, var(--tour-card-y), 0) scale(1); }
.mb-tour__progress { height: 3px; background: var(--mb-line-soft); }
.mb-tour__progress i {
  display: block; height: 100%; width: var(--tour-progress, 0%);
  background: var(--mb-flow); border-radius: 0 99px 99px 0;
  transition: width .5s var(--ease);
}
.mb-tour__progress, .mb-tour__meta, .mb-tour__actions { flex: none; }
.mb-tour__meta { height: 46px; padding: 0 19px; display: flex; align-items: center; justify-content: space-between; }
.mb-tour__count {
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; color: var(--mb-faint);
}
.mb-tour__skip { min-width: 44px; min-height: 44px; margin-right: -8px; color: var(--mb-faint); font-size: 12.5px; }
.mb-tour__skip:active { color: var(--mb-ink); }
.mb-tour__body {
  min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0 20px 2px;
}
.mb-tour__body::-webkit-scrollbar { width: 0; height: 0; }
.mb-tour__body.is-changing { animation: mbTourCopy .38s var(--ease) both; }
@keyframes mbTourCopy { from { opacity: 0; transform: translateY(9px); } }
.mb-tour__stepicon {
  width: 42px; height: 42px; margin: 0 0 13px; border-radius: 13px;
  display: grid; place-items: center;
  color: var(--mb-deep); background: var(--mb-mint); border: 1px solid var(--mb-mint-line);
  box-shadow: 0 8px 22px -15px color-mix(in srgb, var(--mb-accent) 65%, transparent);
}
.mb-tour__stepicon svg { width: 21px; height: 21px; }
.mb-tour__eyebrow {
  margin: 0 0 7px; font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; font-weight: 600;
  letter-spacing: .15em; text-transform: uppercase; color: var(--mb-deep);
}
.mb-tour__title {
  margin: 0; font-family: Spectral, Georgia, serif; font-size: clamp(24px, 7vw, 30px); line-height: 1.06;
  letter-spacing: -.035em; font-weight: 500; text-wrap: balance;
}
.mb-tour__text { margin: 12px 0 0; color: var(--mb-soft); font-size: 14px; line-height: 1.53; }
.mb-tour__hint {
  margin: 13px 0 0; padding: 10px 11px; border-radius: 11px;
  background: var(--mb-mint); color: var(--mb-deep); border: 1px solid var(--mb-mint-line);
  font-size: 11.5px; line-height: 1.4;
}
.mb-tour__hint::before { content: "✦"; margin-right: 7px; }
.mb-tour__actions { padding: 18px 19px 19px; display: flex; align-items: center; gap: 10px; }
.mb-tour__back { height: 48px; min-width: 66px; border-radius: 14px; color: var(--mb-faint); font-size: 13.5px; font-weight: 600; }
.mb-tour__back:active { background: var(--mb-mint); color: var(--mb-deep); }
.mb-tour__next {
  flex: 1; height: 50px; padding: 0 9px 0 18px; border-radius: 15px;
  display: flex; align-items: center; justify-content: space-between;
  color: #fff; background: var(--mb-flow); background-size: 180% 100%;
  font-size: 14.5px; font-weight: 650; letter-spacing: -.01em;
  box-shadow: 0 12px 28px -15px color-mix(in srgb, var(--mb-accent) 82%, transparent);
  animation: mbTourFlow 6s ease-in-out infinite alternate;
}
.mb-tour__next i {
  width: 34px; height: 34px; display: grid; place-items: center; border-radius: 11px;
  background: rgba(255,255,255,.16); font-style: normal; font-size: 17px;
}
.mb-tour__next:active { transform: scale(.985); }
@keyframes mbTourFlow { to { background-position: 100% 0; } }

/* Welcome illustration: one Lemma core with capture/note/chat satellites. */
.mb-tour__visual { margin-bottom: 16px; }
.mb-tour__orbit { position: relative; height: 152px; display: grid; place-items: center; overflow: hidden; }
.mb-tour__ring { position: absolute; border-radius: 50%; border: 1px solid var(--mb-mint-line); }
.mb-tour__ring--one { width: 118px; height: 118px; animation: mbOrbit 13s linear infinite; }
.mb-tour__ring--two { width: 176px; height: 176px; border-style: dashed; opacity: .65; animation: mbOrbit 19s linear infinite reverse; }
.mb-tour__core {
  position: relative; z-index: 2; width: 68px; height: 68px; border-radius: 22px;
  display: grid; place-items: center; overflow: hidden;
  background: var(--mb-card); border: 1px solid color-mix(in srgb, var(--mb-accent) 24%, var(--mb-line));
  box-shadow: 0 20px 40px -20px var(--mb-accent), 0 5px 16px -10px rgba(2,9,6,.46), inset 0 1px rgba(255,255,255,.65);
  animation: mbCoreFloat 3.4s ease-in-out infinite;
}
.mb-tour__core img { width: 100%; height: 100%; display: block; object-fit: cover; }
.mb-tour__core::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(135deg, rgba(255,255,255,.2), transparent 42%);
}
.mb-tour__sat {
  position: absolute; z-index: 3; width: 36px; height: 36px; border-radius: 12px;
  display: grid; place-items: center; color: var(--mb-deep);
  background: var(--mb-card); border: 1px solid var(--mb-line); box-shadow: var(--sh-card);
}
.mb-tour__sat svg { width: 17px; height: 17px; }
.mb-tour__sat--camera { left: 9%; top: 22%; animation: mbSat 4s .1s ease-in-out infinite; }
.mb-tour__sat--note { right: 9%; top: 18%; animation: mbSat 4.6s .7s ease-in-out infinite; }
.mb-tour__sat--chat { right: 18%; bottom: 4%; animation: mbSat 4.2s .35s ease-in-out infinite; }
@keyframes mbOrbit { to { transform: rotate(360deg); } }
@keyframes mbCoreFloat { 50% { transform: translateY(-5px) rotate(2deg); } }
@keyframes mbSat { 50% { transform: translateY(-5px) rotate(-3deg); } }

.mb-tour__palette { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.mb-tour__palette button {
  --tour-choice: #1c7c54;
  height: 52px; padding: 0 11px; display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--mb-line); border-radius: 14px; background: var(--mb-card);
  color: var(--mb-soft); font-size: 12.5px; font-weight: 600; text-align: left;
  transition: border-color .18s var(--ease), background .18s var(--ease), transform .15s var(--ease);
}
.mb-tour__palette button:active { transform: scale(.97); }
.mb-tour__palette button[data-tour-theme="ocean"] { --tour-choice: #256f92; }
.mb-tour__palette button[data-tour-theme="violet"] { --tour-choice: #7657a6; }
.mb-tour__palette button[data-tour-theme="sunset"] { --tour-choice: #bd5a3d; }
.mb-tour__palette i { width: 22px; height: 22px; flex: none; border-radius: 50%; background: var(--tour-choice); box-shadow: inset 0 0 0 1px rgba(255,255,255,.35); }
.mb-tour__palette button[aria-checked="true"] { background: color-mix(in srgb, var(--tour-choice) 10%, var(--mb-card)); border-color: var(--tour-choice); color: var(--mb-ink); }
.mb-tour__palette button[aria-checked="true"] i { box-shadow: 0 0 0 3px var(--mb-card), 0 0 0 5px var(--tour-choice); }

/* The final beat is a handoff, not another instruction. It previews the real
   Tutorial note before the overlay gives way to the reader, so the arrival
   feels intentional and the user knows exactly what was left for them. */
.mb-tour[data-beat="gift"] .mb-tour__wash {
  background:
    radial-gradient(circle at 50% 34%, color-mix(in srgb, var(--mb-accent) 42%, transparent), transparent 42%),
    linear-gradient(160deg, rgba(4,13,9,.14), rgba(4,13,9,.43));
}
.mb-tour__gift {
  position: relative; height: 184px; padding: 4px 10px 0;
  display: grid; place-items: center; perspective: 900px;
}
.mb-tour__gift::before {
  content: ""; position: absolute; left: 12%; right: 12%; bottom: 1px; height: 42px;
  border-radius: 50%; background: color-mix(in srgb, var(--mb-accent) 28%, transparent);
  filter: blur(22px); opacity: .68;
}
.mb-tour__note-preview {
  position: relative; width: min(100%, 348px); padding: 14px 14px 13px;
  border: 1px solid color-mix(in srgb, var(--mb-accent) 22%, var(--mb-line));
  border-radius: 18px; overflow: hidden;
  background:
    radial-gradient(circle at 84% 0, color-mix(in srgb, var(--mb-accent) 13%, transparent), transparent 35%),
    var(--mb-card);
  box-shadow: 0 28px 46px -28px rgba(2,9,6,.72), 0 8px 18px -12px rgba(2,9,6,.34), inset 0 1px rgba(255,255,255,.72);
  transform: rotateX(2deg) rotateZ(-.65deg);
  animation: mbGiftIn .72s cubic-bezier(.18,.88,.3,1.12) both;
}
.mb-tour__note-preview::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(118deg, rgba(255,255,255,.22), transparent 29%);
}
.mb-tour__note-preview header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.mb-tour__note-preview header span {
  padding: 4px 7px; border-radius: 7px; background: var(--mb-mint); color: var(--mb-deep);
  font-family: 'IBM Plex Mono', monospace; font-size: 8px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
}
.mb-tour__note-preview header i { color: var(--mb-faint); font-size: 9.5px; font-style: normal; }
.mb-tour__preview-title {
  margin-top: 9px; color: var(--mb-ink); font-family: Spectral, Georgia, serif;
  font-size: 17px; line-height: 1.08; font-weight: 550; letter-spacing: -.025em;
}
.mb-tour__preview-work {
  height: 58px; margin-top: 8px; padding: 7px 8px 6px 10px;
  display: grid; grid-template-columns: minmax(0, 1fr) 116px; align-items: center; gap: 9px;
  border: 1px solid var(--mb-line-soft); border-radius: 11px; background: color-mix(in srgb, var(--mb-mint) 48%, var(--mb-card));
}
.mb-tour__preview-work strong {
  color: var(--mb-deep); font-family: Spectral, Georgia, serif; font-size: clamp(14px, 4.2vw, 17px);
  line-height: 1; font-weight: 500; white-space: nowrap;
}
.mb-tour__preview-work sup { font-size: .62em; line-height: 0; }
.mb-tour__preview-work svg { width: 100%; height: 44px; overflow: visible; }
.mb-tour__preview-work path { fill: none; vector-effect: non-scaling-stroke; }
.mb-tour__preview-work .grid { stroke: var(--mb-line); stroke-width: .65; }
.mb-tour__preview-work .axis { stroke: var(--mb-faint); stroke-width: .75; opacity: .7; }
.mb-tour__preview-work .curve {
  stroke: var(--mb-accent); stroke-width: 2; stroke-linecap: round;
  stroke-dasharray: 180; stroke-dashoffset: 180;
  animation: mbGiftCurve 1.15s .38s cubic-bezier(.22,.8,.3,1) forwards;
}
.mb-tour__note-preview footer { margin-top: 9px; display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; }
.mb-tour__note-preview footer span {
  min-width: 0; padding: 5px 3px; border: 1px solid var(--mb-line); border-radius: 7px;
  color: var(--mb-soft); background: var(--mb-card-2); text-align: center;
  font-family: 'IBM Plex Mono', monospace; font-size: 7.8px; white-space: nowrap;
}
.mb-tour__gift-spark {
  position: absolute; z-index: 2; color: color-mix(in srgb, var(--mb-accent) 72%, white);
  font-style: normal; line-height: 1; filter: drop-shadow(0 4px 7px color-mix(in srgb, var(--mb-accent) 38%, transparent));
  animation: mbGiftSpark 2.3s ease-in-out infinite;
}
.mb-tour__gift-spark--one { top: 1px; right: 5px; font-size: 17px; }
.mb-tour__gift-spark--two { left: 1px; bottom: 15px; font-size: 10px; animation-delay: .7s; }
@keyframes mbGiftIn { from { opacity: 0; transform: translateY(18px) rotateX(8deg) rotateZ(-2deg) scale(.95); } }
@keyframes mbGiftCurve { to { stroke-dashoffset: 0; } }
@keyframes mbGiftSpark { 50% { opacity: .35; transform: translateY(-5px) rotate(20deg) scale(.82); } }

body.dark .mb-tour__card { border-color: var(--mb-line); box-shadow: 0 40px 100px -30px rgba(0,0,0,.94), inset 0 1px rgba(255,255,255,.06); }
body.dark .mb-tour__next { color: #fff; }
body.dark .mb-tour__wash { background: radial-gradient(circle at 82% 14%, color-mix(in srgb, var(--mb-accent) 22%, transparent), transparent 32%), rgba(0,0,0,.28); }
body.dark .mb-tour__note-preview { box-shadow: 0 28px 50px -24px rgba(0,0,0,.92), inset 0 1px rgba(255,255,255,.05); }

@media (max-height: 700px) {
  .mb-tour__meta { height: 40px; }
  .mb-tour__orbit { height: 112px; }
  .mb-tour__ring--two { width: 142px; height: 142px; }
  .mb-tour__body { padding-left: 18px; padding-right: 18px; }
  .mb-tour__gift { height: 150px; }
  .mb-tour__note-preview { padding-top: 11px; padding-bottom: 10px; }
  .mb-tour__preview-work { height: 48px; margin-top: 6px; }
  .mb-tour__preview-work svg { height: 36px; }
  .mb-tour__note-preview footer { margin-top: 6px; }
  .mb-tour__title { font-size: 23px; }
  .mb-tour__text { margin-top: 8px; font-size: 13px; }
  .mb-tour__hint { margin-top: 9px; padding: 8px 10px; }
  .mb-tour__actions { padding: 13px 17px 16px; }
}
@media (max-width: 340px) {
  .mb-tour__actions { gap: 6px; padding-left: 14px; padding-right: 14px; }
  .mb-tour__back { min-width: 54px; font-size: 12.5px; }
  .mb-tour__next { padding-left: 12px; font-size: 13px; }
  .mb-tour__next span { white-space: nowrap; }
}

/* ============ motion polish ============ */
@media (prefers-reduced-motion: no-preference) {
  /* Views cross-fade only. A translate here shifts the whole surface — header,
     thread and composer together — which reads as the layout jumping every
     time you open a chat, and leaves the view offset if the animation is
     ever interrupted or throttled. Opacity can't mis-position anything. */
  .mb-view.view-in { animation: viewIn .26s var(--ease); }
  @keyframes viewIn { from { opacity: 0; } }
  .msg { animation: bubbleIn .34s var(--ease) both; }
  @keyframes bubbleIn { from { opacity: 0; transform: translateY(8px) scale(.97); } }
  /* The library re-renders on every sync; its arrival stagger belongs to the
     first paint only, or the whole list flickers each time a note is saved.
     Same for the assistant bubble that gets swapped in when a stream ends —
     it is already on screen, so re-animating it reads as a jump. */
  .classes:not(.no-anim) .lib__class { animation: viewIn .3s var(--ease) backwards; }
  .classes:not(.no-anim) .lib__class:nth-child(2) { animation-delay: .03s; }
  .classes:not(.no-anim) .lib__class:nth-child(3) { animation-delay: .06s; }
  .classes:not(.no-anim) .lib__class:nth-child(4) { animation-delay: .09s; }
  .msg.no-anim { animation: none; }
  /* Scoped to the arrival, and deliberately so. A short note's blocks carry
     content-visibility: auto, and a block the browser had stopped rendering
     replays its animations the moment it is rendered again — so an unscoped
     entrance re-fired on every block that crossed the viewport edge, and
     scrolling a note strobed. reader.js takes .is-arriving off a beat after
     the render that earned it. */
  .reader.is-arriving .rd-block { animation: rdIn .3s var(--ease) backwards; }
  @keyframes rdIn { from { opacity: 0; transform: translateY(10px); } }
  /* A note being handed over for the first time — the Tutorial the tour ends
     on — cascades in instead of appearing all at once. reader.js stamps --rd-i
     on the blocks near the top of the note and takes .is-revealing off again
     once the cascade has played, so this is an arrival and nothing else. */
  .reader.is-revealing .rd-block {
    animation: rdReveal .62s cubic-bezier(.22,.92,.3,1) backwards;
    animation-delay: calc(var(--rd-i, 0) * 62ms);
  }
  @keyframes rdReveal { from { opacity: 0; transform: translateY(18px) scale(.985); } }
  .opt { animation: viewIn .34s var(--ease) backwards; }
  .opt:nth-child(2) { animation-delay: .04s; }
  .opt:nth-child(3) { animation-delay: .08s; }
  .opt:nth-child(4) { animation-delay: .12s; }
}
@media (prefers-reduced-motion: reduce) {
  /* Looping decoration goes entirely — including the blinking caret and the
     record dot, which are the two this setting is really about. */
  .aura i, .btn-flow, .lm-caret, .rec__dot, .hello::before, .hello__icon-glow, .hello__icon-img, .hello__phrase, .hello__phrase::after, .chip, .chip::before { animation: none !important; }
  /* Overlays are shortened rather than removed: overlay.js sets [hidden] on
     animationend, and an animation that never runs never fires one. !important
     beats the .is-closing rules' animation shorthand regardless of specificity,
     so the exits collapse too. */
  .scrim, .sheet__card, .drawer__panel, .pop, .toast, .bx-sheet, .note-actions__wash, .note-actions__menu { animation-duration: .01ms !important; }
  .note-drag-ghost, .note-move-tray__panel { transition-duration: .01ms !important; }
  /* the drag-dismiss spring-back is set inline by overlay.js — collapse it too */
  .sheet__card, .sheet .scrim { transition-duration: .01ms !important; }
  .mb-tour, .mb-tour__card, .mb-tour__hole, .mb-tour__progress i { transition-duration: .01ms !important; }
  .mb-tour__hole::after, .mb-tour__body, .mb-tour__next, .mb-tour__ring, .mb-tour__core, .mb-tour__sat,
  .mb-tour__note-preview, .mb-tour__preview-work .curve, .mb-tour__gift-spark { animation: none !important; }
  .mb-tour__preview-work .curve { stroke-dashoffset: 0; }
}

/* ============================================================
   Role badge + beta welcome card (mobile)
   Desktop twins live in app/app.css.
   ============================================================ */
.mb-rolechip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px 3px 7px;
  border-radius: 999px;
  background: var(--mb-mint);
  border: 1px solid var(--mb-mint-line);
  color: var(--mb-deep);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 9.5px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  line-height: 1; white-space: nowrap;
}
.mb-rolechip i { flex: none; display: grid; place-items: center; width: 11px; height: 11px; color: var(--mb-accent); }
.mb-rolechip svg { width: 100%; height: 100%; }
/* Light and dark both come out of the accent tokens above, so the badge
   follows Forest / Ocean / Violet / Sunset instead of pinning one green. */
.mb-rolechip > span { font: inherit; color: inherit; letter-spacing: inherit; }
.acct__who .mb-rolechip { align-self: flex-start; margin-bottom: 3px; }

/* header variant — smaller, and wordless on very narrow phones */
.mb-rolechip--mini { gap: 4px; padding: 3px 8px 3px 6px; font-size: 8.5px; }
.mb-rolechip--mini i { width: 10px; height: 10px; }

.hm-role {
  flex: none; padding: 0;
  display: inline-flex; align-items: center;
  border-radius: 999px;
  transition: transform .14s var(--ease), opacity .14s var(--ease);
}
.hm-role:active { transform: scale(.94); opacity: .78; }
.hm-role[hidden] { display: none; }

/* the avatar picks up a ring once the account carries a role, so badge and
   initial read as one identity rather than two unrelated marks */
.hm-avatar.is-role { box-shadow: 0 0 0 2px var(--mb-card-2), 0 0 0 3px var(--mb-mint-line); }

@media (max-width: 359px) {
  /* brand + badge + two controls stop fitting: keep the flask, drop the word */
  .hm-role .mb-rolechip { padding: 5px; }
  .hm-role .mb-rolechip > span { display: none; }
}

@media (max-width: 319px) {
  /* A foldable cover display can expose less than 300 CSS px. Keep all four
     composer actions instead of pushing Send outside the fixed shell; their
     live choices remain in the buttons' aria-labels and in the opened menus. */
  #mode-label, #intent-label { display: none; }
}

/* Settings > Your access — the phone's twin of the desktop Subscription pane */
.mb-access {
  padding: 15px 15px 14px;
  background: var(--mb-card);
  border: 1px solid var(--mb-line);
  border-radius: var(--r-md);
  box-shadow: var(--sh-card);
}
.mb-access__top { display: flex; align-items: center; gap: 12px; }
.mb-access__crest {
  width: 38px; height: 38px; flex: none;
  border-radius: 12px;
  background: var(--mb-flow); color: #fff;
  display: grid; place-items: center;
  box-shadow: 0 8px 18px -12px var(--mb-accent);
}
.mb-access__crest svg { width: 19px; height: 19px; }
.mb-access__id {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
}
.mb-access__id small { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: var(--mb-faint); }
.mb-access__text { margin: 12px 0 0; font-size: 13px; line-height: 1.55; color: var(--mb-soft); }
.mb-access__perks {
  margin: 13px 0 0; padding: 13px 0 0;
  list-style: none;
  border-top: 1px solid var(--mb-line-soft);
  display: grid; gap: 9px;
}
.mb-access__perks li {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: 13px; line-height: 1.4; color: var(--mb-ink);
}
.mb-access__perks i { flex: none; display: grid; place-items: center; width: 13px; height: 13px; margin-top: 1px; color: var(--mb-accent); }
.mb-access__perks svg { width: 100%; height: 100%; }
.mb-access__meta {
  margin: 13px 0 0;
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--mb-faint);
}
/* opened from the header badge: one soft pulse so the tap lands somewhere */
.mb-access.is-flash { animation: accessFlash 1.5s var(--ease); }
@keyframes accessFlash {
  0%   { border-color: var(--mb-line); box-shadow: var(--sh-card); }
  20%  { border-color: var(--mb-accent); box-shadow: 0 0 0 4px var(--mb-mint); }
  100% { border-color: var(--mb-line); box-shadow: var(--sh-card); }
}
@media (prefers-reduced-motion: reduce) { .mb-access.is-flash { animation: none; } }

.mb-welcome {
  position: fixed; left: 0; right: 0;
  top: var(--app-top, 0px); height: var(--app-h, 100dvh);
  z-index: 95;                          /* above sheets (90), below the tour */
  display: flex; align-items: flex-end; justify-content: center;
  opacity: 0; pointer-events: none;
  transition: opacity .26s var(--ease);
}
.mb-welcome.is-open { opacity: 1; pointer-events: auto; }
.mb-welcome__scrim { position: absolute; inset: 0; background: rgba(14,26,20,.44); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.mb-welcome__card {
  position: relative;
  width: 100%; max-height: 100%;
  overflow-y: auto;
  padding: 24px 22px calc(22px + var(--safe-b));
  background: var(--mb-card);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  box-shadow: var(--sh-pop);
  text-align: center;
  transform: translateY(24px);
  transition: transform .34s var(--ease);
}
.mb-welcome.is-open .mb-welcome__card { transform: none; }

.mb-welcome__crest {
  width: 52px; height: 52px; margin: 2px auto 15px;
  border-radius: 17px;
  background: var(--mb-flow);
  display: grid; place-items: center; color: #fff;
  box-shadow: 0 10px 24px -12px var(--mb-accent);
}
.mb-welcome__crest svg { width: 24px; height: 24px; }
.mb-welcome__eyebrow {
  display: block;
  font-family: 'IBM Plex Mono', monospace; font-size: 10px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--mb-faint);
}
.mb-welcome__title {
  margin-top: 6px;
  font-family: 'Spectral', Georgia, serif; font-size: 25px; font-weight: 500;
  letter-spacing: -.015em; line-height: 1.15; color: var(--mb-ink);
  overflow-wrap: anywhere;
}
.mb-welcome__rolerow {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 8px; margin-top: 13px;
}
.mb-welcome__roletag { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: var(--mb-faint); }
.mb-welcome__text { margin-top: 11px; font-size: 14px; line-height: 1.6; color: var(--mb-soft); }
.mb-welcome__perks {
  margin-top: 18px; padding: 15px 16px;
  list-style: none; text-align: left;
  background: var(--mb-card-2);
  border: 1px solid var(--mb-line-soft);
  border-radius: var(--r-md);
  display: grid; gap: 10px;
}
.mb-welcome__perks li {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: 13.5px; line-height: 1.4; color: var(--mb-ink);
}
.mb-welcome__perks i { flex: none; display: grid; place-items: center; width: 14px; height: 14px; margin-top: 1px; color: var(--mb-accent); }
.mb-welcome__perks svg { width: 100%; height: 100%; }
.mb-welcome__go { width: 100%; margin-top: 20px; }
.mb-welcome__skip { text-align: center; width: 100%; color: var(--mb-faint); }

@media (prefers-reduced-motion: reduce) {
  .mb-welcome, .mb-welcome__card { transition: none; }
}
