:root {
  /* iOS system backgrounds, following the phone's light / dark setting */
  --bg: #ffffff;
  --fg: #000000;
  --text: #000;
  --muted: rgba(0, 0, 0, 0.5);
  --accent: #5eb1ff;
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease: cubic-bezier(0.25, 0.8, 0.25, 1);
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  color-scheme: light dark;
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) { --bg: #121214; --fg: #ffffff; --text: #fff; --muted: rgba(255, 255, 255, 0.55); }
}
/* (chosen in Settings → Appearance) */
:root[data-theme="dark"] { --bg: #121214; --fg: #ffffff; --text: #fff; --muted: rgba(255, 255, 255, 0.55); }

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

/* No native rubber-band: it moves the page without telling the glass. app.js bounces instead. */
/* Safari doesn't scroll this page at all: app.js does (so the glass stays in sync) */
html, body { overflow: hidden; overscroll-behavior: none; height: var(--app-h, 100%); }
html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

button { font: inherit; color: inherit; border: 0; background: none; padding: 0; cursor: pointer; }

/* WebGL layers (created by glass.js) */
/* Page glass + wallpaper: reaches 320px past the page top and bottom so the bounce never shows a blank edge */
#gl-content { position: absolute; top: -320px; left: 0; width: 100%; height: calc(100% + 640px); z-index: -1; pointer-events: none; }
/* Small strip around the tab bar (bar is 64px tall, 10px above the safe area; 40px margin for shadow/wobble) */
#gl-chrome { position: fixed; left: -40px; width: calc(100% + 80px); z-index: 9; pointer-events: none;
  top: calc(var(--app-h, 100vh) - var(--safe-bottom) - 118px); height: 164px; }
/* Text sitting on glass gets a faint shadow for legibility, like iOS vibrancy */
[data-glass] { text-shadow: 0 1px 3px rgba(0, 0, 0, 0.22); }

/* ---------- Layout ---------- */
main { position: relative; z-index: 1; }
#content {
  position: relative; z-index: 0; /* own stacking context so the glass canvas sits behind the text */
  min-height: var(--app-h, 100vh);
  padding: calc(var(--safe-top) + 12px) 16px calc(var(--safe-bottom) + 110px);
}
#content.switching { animation: pageIn 0.16s var(--ease); }
@keyframes pageIn { from { opacity: 0.35; } to { opacity: 1; } }
.page { display: none; }
/* flow-root: a page lays out identically whether it's the current page or the neighbour
   sliding in beside it (otherwise its title's top margin collapses differently and it
   jumps a few pixels the moment it becomes the current page) */
.page.active { display: flow-root; }
.page.peek { display: flow-root; position: absolute; margin: 0; } /* the neighbour shown beside it mid-swipe */

.large-title { padding: 18px 4px 14px; text-shadow: 0 1px 8px rgba(0,0,0,0.18); }
.large-title h1 { margin: 0; font-size: 40px; font-weight: 800; letter-spacing: -0.5px; }
.eyebrow { margin: 0 0 2px; font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; }

.section { padding: 4px 4px 18px; text-shadow: 0 1px 6px rgba(0,0,0,0.25); }
.section h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
.card { border-radius: 30px; padding: 18px; margin-bottom: 14px; }
.card h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
.sub { margin: 0 0 14px; color: var(--muted); font-size: 15px; line-height: 1.4; }
.row { display: flex; gap: 10px; margin-bottom: 10px; }
.row > * { flex: 1; }

/* ---------- Buttons (glass drawn by glass.js) ---------- */
.btn {
  height: 52px; border-radius: 999px; font-size: 17px; font-weight: 600;
  transition: transform 0.45s var(--spring);
}
.btn.wide { width: 100%; }
.btn:disabled { color: rgba(255,255,255,0.55); }

.icon-row { display: flex; justify-content: space-between; }
.round {
  width: 62px; height: 62px; border-radius: 50%;
  display: grid; place-items: center;
  transition: transform 0.45s var(--spring);
}
.round svg { width: 26px; height: 26px; fill: #fff; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.25)); }

/* iOS 26 press: glass swells under your finger */
[data-glass="control"].pressed { transform: scale(1.08); transition-duration: 0.3s; }

/* ---------- Slider ---------- */
.slider { position: relative; height: 44px; touch-action: none; --v: 0.6; }
.slider-track { position: absolute; left: 0; right: 0; top: 50%; height: 6px; margin-top: -3px; border-radius: 99px; }
.slider-thumb {
  position: absolute; top: 50%; left: calc(var(--v) * (100% - 38px));
  width: 38px; height: 24px; margin-top: -12px; border-radius: 99px;
  transition: transform 0.4s var(--spring);
}
.slider.dragging .slider-thumb { transform: scale(1.7, 1.6); }

/* ---------- Tab bar ---------- */
.tabbar {
  position: fixed; z-index: 10;
  left: max(16px, calc(50% - 220px)); right: max(16px, calc(50% - 220px)); top: calc(var(--app-h, 100vh) - var(--safe-bottom) - 68px);
  height: 64px; border-radius: 999px; padding: 4px;
  transform-origin: 50% 100%; /* shrinks toward the bottom when compact */
  display: flex; touch-action: none; text-shadow: none;
  will-change: transform; /* app.js wobbles the whole bar like jelly */
}
/* Outline icons; app.js cuts a pill-shaped hole in this layer every frame so the
   filled icons' cut-outs (play button, fold line, sun and hills) are truly see-through */
.tabs { flex: 1; display: flex; position: relative; z-index: 2; }
.tab {
  flex: 1; position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font-size: 10.5px; font-weight: 600; color: var(--fg);
  transition: color 0.25s;
}
/* Icons: soft, rounded strokes. Unselected tabs show the outline (.o); the filled
   versions (.f) live inside the pill, so the fill is masked to wherever the pill is,
   even mid-drag, like native iOS tab bars. */
.tab svg, .lens-icons svg { width: 26px; height: 26px; overflow: visible; }
.tab svg *, .lens-icons svg * { vector-effect: non-scaling-stroke; }
.tab .o, .lens-icons .o { fill: none; stroke: currentColor; stroke-width: 1.85; stroke-linecap: round; stroke-linejoin: round; }
.tab .f, .lens-icons .f { fill: currentColor; stroke: currentColor; stroke-width: 1.85; stroke-linecap: round; stroke-linejoin: round; }

/* Profile tab: the user's own picture. Selected = white ring cut into the edge of the photo */
.pfp {
  display: block; width: 27px; height: 27px; border-radius: 50%; flex: none;
  background: var(--pfp, linear-gradient(135deg, #ff6fa8, #8a5cff)) center / cover no-repeat;
  box-shadow: inset 0 0 0 0.5px rgba(255,255,255,0.35);
}
.lens-icons .pfp { box-shadow: inset 0 0 0 2px var(--fg); } /* ring sits on the edge, inside the photo: no gap, no extra size */
.tab .f { display: none; }
.lens-icons .o { display: none; }
.lens-icons {
  position: absolute; top: 0; bottom: 0; left: 0; width: var(--row, 100%);
  display: flex; pointer-events: none;
  transform-origin: 0 0; /* app.js cancels the pill's movement and squash so icons stay put */
}
.lens-icons > span { flex: 1; display: flex; align-items: center; justify-content: center; color: var(--fg); }

.lens {
  position: absolute; z-index: 1; top: 4px; bottom: 4px; left: 0;
  width: var(--w, 80px); border-radius: 999px; overflow: hidden;
  transform-origin: 0 0; /* moved, stretched and squashed every frame by app.js */
  will-change: transform;
}

/* ---------- Test text ---------- */
.title { font-size: 34px; font-weight: 800; margin: 6px 0 10px; }
.page h2 { font-size: 20px; font-weight: 700; margin: 22px 0 6px; }
.page p { font-size: 15px; line-height: 1.45; margin: 0 0 12px; color: var(--fg); }
.page p.lead { font-size: 17px; font-weight: 500; }
.page p.small { font-size: 12px; color: var(--muted); }
.accent { color: #0a84ff; font-weight: 600; }

/* ---------- Landscape ---------- */
/* Keep clear of the notch / rounded corners on whichever side they end up */
#content {
  padding-left: max(16px, env(safe-area-inset-left));
  padding-right: max(16px, env(safe-area-inset-right));
}
/* Text stays a comfortable reading width on wide screens */
.page { max-width: 640px; margin: 0 auto; }

/* ---------- Other pages ---------- */
.reels { grid-template-columns: 1fr 1fr; }
.reel { aspect-ratio: 9 / 16; border-radius: 26px; display: grid; place-items: center; }
.play { width: 0; height: 0; border-style: solid; border-width: 13px 0 13px 22px; border-color: transparent transparent transparent rgba(255,255,255,0.9); margin-left: 6px; filter: drop-shadow(0 2px 6px rgba(0,0,0,0.25)); }
.profile-card { display: flex; align-items: center; gap: 16px; }
.profile-card h2 { margin: 0 0 2px; }
.profile-card .sub { margin: 0; }
.avatar.pfp { width: 72px; height: 72px; position: relative; overflow: hidden; cursor: pointer; box-shadow: inset 0 1px 1px rgba(255,255,255,0.5); }
.avatar-edit { position: absolute; left: 0; right: 0; bottom: 0; padding: 3px 0 5px; text-align: center; font-size: 11px; font-weight: 700;
  background: rgba(0,0,0,0.35); text-shadow: none; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.tile { aspect-ratio: 1; border-radius: 26px; }

.bubble { max-width: 75%; padding: 12px 16px; border-radius: 22px; margin-bottom: 10px; font-size: 16px; width: fit-content; }
.bubble.me { margin-left: auto; }

.list { padding: 4px 18px; }
.list-row { display: flex; justify-content: space-between; padding: 14px 0; font-size: 17px; }
.list-row + .list-row { border-top: 0.5px solid rgba(255,255,255,0.25); }
.muted { color: var(--muted); }

/* Status bar scrim (plain gradient: no blur, so it costs nothing while scrolling) */
.edge-top { position: fixed; top: 0; left: 0; right: 0; z-index: 5; pointer-events: none;
  height: calc(var(--safe-top) + 20px); background: linear-gradient(rgba(22, 8, 44, 0.6), rgba(22, 8, 44, 0)); }

/* ---------- Toast ---------- */
.toast {
  position: fixed; z-index: 1000; /* above every screen and sheet */ left: 50%; top: calc(var(--safe-top) + 10px);
  transform: translate(-50%, calc(-100% - 80px)); padding: 13px 22px; border-radius: 999px; /* fully off-screen */
  font-size: 15px; font-weight: 600; white-space: nowrap; color: var(--fg);
  background: transparent; /* the glass itself is drawn by glass.js, behind the text */
  transition: transform 0.55s var(--spring);
}
/* While a toast is on screen, the glass layer reaches up to cover it too */
/* Over a full-screen view or sheet the glass layer is underneath, so the toast carries
   its own glass look, tinted like the tab bar */
.toast.solid { background: rgba(0, 0, 0, 0.85); -webkit-backdrop-filter: blur(20px) saturate(160%); backdrop-filter: blur(20px) saturate(160%);
  box-shadow: inset 0 0.5px 0 rgba(255, 255, 255, 0.45), inset 0 0 0 0.5px rgba(255, 255, 255, 0.18); }
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) .toast.solid { background: rgba(255, 255, 255, 0.92); box-shadow: inset 0 0.5px 0 rgba(255, 255, 255, 0.9), inset 0 0 0 0.5px rgba(0, 0, 0, 0.12); }
}
/* (chosen in Settings → Appearance) */
:root[data-theme="light"] .toast.solid { background: rgba(255, 255, 255, 0.92); box-shadow: inset 0 0.5px 0 rgba(255, 255, 255, 0.9), inset 0 0 0 0.5px rgba(0, 0, 0, 0.12); }
.glass-tall #gl-chrome { top: 0; height: calc(var(--app-h, 100vh) - var(--safe-bottom) + 46px); }
.no-gl .toast { background: rgba(120, 120, 128, 0.35); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); }
.toast.show { transform: translate(-50%, 0); }

/* ---------- Fallback if WebGL2 is unavailable ---------- */
.no-gl body { background: linear-gradient(160deg, #ff6fa8, #8a5cff 50%, #2fb8ff); }
.no-gl [data-glass] {
  background: rgba(255,255,255,0.16);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  backdrop-filter: blur(18px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 8px 24px rgba(0,0,0,0.2);
}
.no-gl .slider-thumb { background: #fff; }

/* ---------- Accounts ---------- */
:root {
  --field: rgba(0, 0, 0, 0.05); --line: rgba(0, 0, 0, 0.1); --accent: #0a84ff; --danger: #ff3b30;
  --solid: #ececf0; /* iOS-style solid fill for buttons, fields and groups */
  --bg-deep: #f2f2f5; /* a shade darker than the page background */
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
    --field: rgba(255, 255, 255, 0.08); --line: rgba(255, 255, 255, 0.12); --danger: #ff453a;
    --solid: #232326;
    --bg-deep: #0a0a0c;
  }
}
/* (chosen in Settings → Appearance) */
:root[data-theme="dark"] {
    --field: rgba(255, 255, 255, 0.08); --line: rgba(255, 255, 255, 0.12); --danger: #ff453a;
    --solid: #232326;
    --bg-deep: #0a0a0c;
  }
button { -webkit-user-select: none; user-select: none; }
input { -webkit-user-select: text; user-select: text; }

/* Buttons: matte capsules. Pressing one makes it swell, lean toward your finger and
   brighten; letting go springs it back with a little jiggle (app.js drives the motion). */
.btn-fill, .btn-plain {
  height: 50px; padding: 0 22px; border: 0; border-radius: 999px; font-size: 17px; font-weight: 600;
  background: var(--solid); color: var(--fg);
  will-change: transform; -webkit-tap-highlight-color: transparent;
}
.btn-fill { background: var(--accent); color: #fff; }
.btn-plain.danger, .row-item.danger { color: var(--danger); }
button:disabled { opacity: 0.5; }
.wide { width: 100%; }

/* Sign-in screens */
.signed-out .tabbar, .signed-out #gl-chrome { visibility: hidden; }
.auth {
  position: fixed; inset: 0; z-index: 200; background: var(--bg); color: var(--fg);
  display: flex; align-items: center; justify-content: center; overflow-y: auto;
  padding: calc(var(--safe-top) + 24px) 24px calc(var(--safe-bottom) + 24px);
}
.auth[hidden] { display: none; }
.auth-card { width: 100%; max-width: 380px; }
.auth-card[hidden] { display: none; }
.auth-view { display: flex; flex-direction: column; gap: 12px; }
.auth-view[hidden] { display: none; }
.auth-view h1 { font-size: 26px; font-weight: 700; margin: 0 0 4px; text-align: center; }
.auth-view .small { margin: 0 0 6px; text-align: center; color: var(--muted); font-size: 14px; line-height: 1.4; }
.auth-view input {
  height: 50px; border: 0; border-radius: 999px; padding: 0 20px; font: inherit; font-size: 17px;
  background: var(--solid); color: var(--fg); outline: none;
  transition: box-shadow 0.2s;
}
.auth-view input::placeholder { color: var(--muted); }
.auth-view input:focus { box-shadow: 0 0 0 3px rgba(10, 132, 255, 0.45); }
/* Who's this? Two pages, Mia and Eric; swiping up or down flips to the other one */
.who { position: absolute; inset: 0; overflow: hidden; touch-action: none; }
.who[hidden] { display: none; }
.who-panel {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: stretch; justify-content: center; gap: 12px;
  width: 100%; max-width: 428px; margin: 0 auto; padding: calc(var(--safe-top) + 24px) 24px calc(var(--safe-bottom) + 24px);
  will-change: transform, opacity;
}
.who-panel h1 { font-size: 28px; line-height: 34px; font-weight: 700; margin: 0 0 14px; text-align: center; }
.who-panel .small { margin: 0 0 10px; text-align: center; color: var(--muted); font-size: 15px; }
.who-panel .auth-error { margin: 2px 0 0; }
.avatar {
  align-self: center; width: 92px; height: 92px; border-radius: 50%; margin-bottom: 10px;
  display: grid; place-items: center; font-size: 40px; font-weight: 700; color: #fff;
  background: linear-gradient(145deg, #ff7aa8, #a855f7);
}
.avatar.small { width: 72px; height: 72px; font-size: 30px; margin-bottom: 4px; }
/* The recovery screen matches the sign-in pages */
/* The recovery screen is the sign-in page with the code box in place of "Continue with
   Face ID" and Cancel in place of "Use recovery code", so nothing moves between them */
.auth-view[data-view="recover"] h1 { font-size: 28px; line-height: 34px; margin: 0 0 14px; }
.avatar.eric { background: linear-gradient(145deg, #5ac8fa, #0a5bd8); }
.avatar.photo { background: var(--photo) center / cover no-repeat; color: transparent; }

/* Recovery code */
.key { width: 22px; height: 22px; fill: currentColor; }
.key-btn { display: flex; align-items: center; justify-content: center; gap: 8px; }
.key-btn .key { width: 19px; height: 19px; }
.key-badge {
  align-self: center; width: 72px; height: 72px; border-radius: 24px; display: grid; place-items: center; margin-bottom: 6px;
  background: linear-gradient(145deg, #ffd25a, #ff9f0a); color: #fff;
}
.key-badge .key { width: 38px; height: 38px; }
.code-field { position: relative; }
.auth-view .code-input {
  width: 100%; padding: 0 20px; text-align: center; text-transform: uppercase;
  font: 600 16px ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: 0.5px;
}
.auth-view .code-input:focus { box-shadow: none; }
.auth-view .code-input::placeholder { font: 500 17px -apple-system, system-ui, sans-serif; letter-spacing: 0; text-transform: none; color: var(--muted); }
.code-chunks { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 4px 0 6px; -webkit-user-select: all; user-select: all; }
.code-chunks span {
  padding: 14px 0; border-radius: 16px; background: var(--solid); text-align: center;
  font: 600 20px ui-monospace, Menlo, monospace; letter-spacing: 2px;
}
.sheet-row { display: flex; gap: 8px; }
.sheet-row button { flex: 1; }
.sheet-card .key-badge { margin-top: 4px; }

.link { border: 0; background: none; color: var(--accent); font: inherit; font-size: 15px; padding: 10px; }
.link:active { opacity: 0.5; }
.auth-error { min-height: 22px; margin: 14px 0 0; text-align: center; color: var(--danger); font-size: 15px; }

/* Bottom sheet offering Face ID */
.sheet { position: fixed; inset: 0; z-index: 170; background: rgba(0, 0, 0, 0.35); display: flex; align-items: flex-end; }
.sheet[hidden] { display: none; }
.sheet-card {
  width: 100%; background: var(--bg); color: var(--fg); border-radius: 28px 28px 0 0;
  padding: 24px 20px calc(var(--safe-bottom) + 20px); display: flex; flex-direction: column; gap: 10px;
  animation: sheetIn 0.35s var(--spring);
}
.sheet-card h2 { margin: 0; font-size: 22px; text-align: center; }
.sheet-card .small { margin: 0 0 8px; text-align: center; color: var(--muted); font-size: 15px; }
@keyframes sheetIn { from { transform: translateY(100%); } to { transform: none; } }

/* Profile: account section */
/* Profile header, like Instagram: picture on the left, name and counts beside it */
/* Top row, where the page title used to be: + on the left, menu lines on the right */
.profile-top { display: flex; align-items: center; justify-content: space-between; height: 44px; margin: 0 -10px 6px; }
.icon-btn {
  width: 44px; height: 44px; padding: 0; border: 0; background: none; color: var(--fg);
  display: grid; place-items: center; -webkit-tap-highlight-color: transparent; transition: opacity 0.15s;
}
.icon-btn:active { opacity: 0.4; }
.icon-btn svg { width: 27px; height: 27px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.profile-head { display: flex; align-items: center; gap: 22px; margin: 4px 0 12px; }
/* Bio under the header, like Instagram; tap to edit */
.bio {
  display: block; width: 100%; margin: 0 0 14px; padding: 0; border: 0; background: none; text-align: left;
  font: 400 14px/1.4 -apple-system, system-ui, sans-serif; color: var(--fg); white-space: pre-line; overflow-wrap: anywhere;
  -webkit-tap-highlight-color: transparent;
}
.bio.empty { color: var(--accent); font-weight: 500; }
.bio:active { opacity: 0.5; }
/* Edit Profile / Timeline: two equal capsules side by side, like Instagram's */
.profile-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0 0 24px; }
.profile-actions button { height: 36px; padding: 0 12px; border-radius: 11px; font-size: 14px; font-weight: 600; }
.field-label { margin: 4px 6px -4px; font-size: 13px; font-weight: 600; color: var(--muted); }
/* (sheet inputs) */
.sheet-input {
  height: 48px; border: 0; border-radius: 999px; padding: 0 18px; outline: none;
  font: 400 16px -apple-system, system-ui, sans-serif; background: var(--solid); color: var(--fg);
}
.sheet-input::placeholder { color: var(--muted); }
/* Edit profile screen */
.edit-top { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; height: 44px; margin: 0 -4px 10px; }
.edit-top h2 { margin: 0; font-size: 17px; font-weight: 700; }
.text-btn { justify-self: start; border: 0; background: none; padding: 10px 6px; font: 400 17px -apple-system, system-ui, sans-serif; color: var(--fg); -webkit-tap-highlight-color: transparent; }
/* Round liquid-glass back button: see-through body, a sharp shine round the rim
   (brightest top-left and bottom-right) and a soft highlight across the top */
.glass-circle {
  position: relative; justify-self: start; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%;
  display: grid; place-items: center; color: var(--fg); -webkit-tap-highlight-color: transparent;
  /* Liquid glass: clear in the middle with a slight lens blur and richer colour behind it,
     a thick bright edge (strongest top-left, softer bottom-right), a glow inside the rim
     and a little lift off the page */
  background: radial-gradient(90% 90% at 28% 18%, rgba(255, 255, 255, 0.2), transparent 55%), rgba(255, 255, 255, 0.04);
  -webkit-backdrop-filter: blur(3px) saturate(190%) brightness(1.1); backdrop-filter: blur(3px) saturate(190%) brightness(1.1);
  box-shadow:
    inset 1.5px 1.5px 1px -0.5px rgba(255, 255, 255, 0.8), inset -1.5px -1.5px 1px -0.5px rgba(255, 255, 255, 0.45),
    inset 0 0 10px rgba(255, 255, 255, 0.14), inset 0 -7px 10px -7px rgba(0, 0, 0, 0.3),
    0 6px 18px rgba(0, 0, 0, 0.25);
}
/* With WebGL, a real lens draws the glass (lens.js); the CSS look above is the fallback */
.glass-circle.lens, :root .glass-circle.lens:not(.tinted), .glass-circle.tinted.lens {
  background: none; -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.16);
}
.glass-circle.lens::before { opacity: 0.4; z-index: 1; }
.glass-circle.lens { isolation: isolate; }
.lens-canvas { z-index: 0; }
.glass-circle.lens svg { position: relative; z-index: 2; transform: translateZ(0); will-change: transform; } /* its own layer, always above the lens */
.lens-canvas { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%; pointer-events: none; }
.glass-circle::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; pointer-events: none;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.08) 30%, rgba(255, 255, 255, 0.05) 70%, rgba(255, 255, 255, 0.5));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude;
}
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) .glass-circle:not(.tinted) { background: radial-gradient(90% 90% at 28% 18%, rgba(255, 255, 255, 0.75), transparent 60%), rgba(255, 255, 255, 0.18);
  box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.1), inset 1.5px 1.5px 1px -0.5px #fff, inset -1.5px -1.5px 1px -0.5px rgba(0, 0, 0, 0.1),
    inset 0 0 10px rgba(0, 0, 0, 0.05), inset 0 -7px 10px -7px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.12); }
:root:not([data-theme="dark"]) .glass-circle:not(.tinted)::before { background: linear-gradient(135deg, rgba(255, 255, 255, 1), rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.08) 70%, rgba(0, 0, 0, 0.16)); }
}
/* (chosen in Settings → Appearance) */
:root[data-theme="light"] .glass-circle:not(.tinted) { background: radial-gradient(90% 90% at 28% 18%, rgba(255, 255, 255, 0.75), transparent 60%), rgba(255, 255, 255, 0.18);
  box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.1), inset 1.5px 1.5px 1px -0.5px #fff, inset -1.5px -1.5px 1px -0.5px rgba(0, 0, 0, 0.1),
    inset 0 0 10px rgba(0, 0, 0, 0.05), inset 0 -7px 10px -7px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.12); }
:root[data-theme="light"] .glass-circle:not(.tinted)::before { background: linear-gradient(135deg, rgba(255, 255, 255, 1), rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.08) 70%, rgba(0, 0, 0, 0.16)); }
/* Blue-tinted version (Done): blue glass, white check */
.glass-circle.tinted { justify-self: end; color: #fff;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.32), rgba(255, 255, 255, 0.04) 60%), rgba(10, 132, 255, 0.88); }
.glass-circle.tinted::before { background: linear-gradient(135deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.2) 30%, rgba(255, 255, 255, 0.12) 70%, rgba(255, 255, 255, 0.65)); }
.glass-circle.tinted svg { margin-left: 0; stroke-width: 2.5; }
.glass-circle:disabled { opacity: 0.5; }
.glass-circle svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; margin-left: -2px; }
.text-btn.done { justify-self: end; font-weight: 700; color: var(--accent); }
.text-btn:active { opacity: 0.4; }
.edit-pfp { display: flex; flex-direction: column; align-items: center; gap: 12px; margin: 4px 0 22px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.edit-pfp:active .pfp-wrap { opacity: 0.7; }
.pfp-wrap { position: relative; display: block; }
.edit-pfp-btn { display: inline-flex; align-items: center; justify-content: center; height: 30px; padding: 0 16px; border-radius: 10px; font-size: 14px; line-height: 1; text-align: center; }
/* Name + bio card, in the app's solid rounded style */
.edit-card { background: var(--solid); border-radius: 22px; padding: 0 18px; }
.edit-row { display: grid; grid-template-columns: 72px 1fr; align-items: start; gap: 10px; padding: 15px 0; }
.edit-row + .edit-row { border-top: 0.5px solid var(--line); }
.edit-row span { font-size: 15px; line-height: 22px; font-weight: 600; color: var(--fg); }
.edit-row input, .edit-row textarea {
  width: 100%; border: 0; padding: 0; background: none; outline: none; resize: none; color: var(--fg);
  font: 400 16px/22px -apple-system, system-ui, sans-serif;
}
.edit-row input::placeholder, .edit-row textarea::placeholder { color: var(--muted); }
/* Bio box with its character count tucked in the bottom-right corner */
.bio-field { display: flex; flex-direction: column; min-width: 0; }
.edit-row .bio-count { align-self: flex-end; margin-top: 6px; font-size: 12px; font-weight: 400; line-height: 16px; color: var(--muted); }
/* ---------- Settings and activity (the menu), laid out like Instagram's ---------- */
.menu-search {
  display: flex; align-items: center; gap: 8px; height: 38px; padding: 0 12px; margin: 4px 0 8px;
  border-radius: 12px; background: var(--solid); color: var(--muted);
}
.menu-search svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.menu-search input { flex: 1; min-width: 0; border: 0; background: none; outline: none; color: var(--fg); font: 400 16px -apple-system, system-ui, sans-serif; }
.menu-search input::placeholder { color: var(--muted); }
.menu-search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.msec { padding: 6px 0 8px; border-bottom: 0.5px solid var(--line); }
.msec:last-of-type { border-bottom: 0; }
.msec[hidden] { display: none; }
.msec h4 { margin: 12px 0 4px; font-size: 14px; font-weight: 600; color: var(--muted); }
.mrow {
  display: flex; align-items: center; gap: 14px; width: 100%; min-height: 52px; padding: 0; border: 0; background: none;
  color: var(--fg); font: 400 16px -apple-system, system-ui, sans-serif; text-align: left; -webkit-tap-highlight-color: transparent;
}
.mrow[hidden] { display: none; }
/* Tapped rows get a soft highlight (and the chevron nudges), instead of just fading */
button.mrow, label.mrow { border-radius: 12px; margin: 0 -10px; padding: 0 10px; width: calc(100% + 20px); transition: background-color 0.35s; }
button.mrow:active { background-color: var(--field); transition-duration: 0.05s; }
.mrow .chev { transition: transform 0.25s; }
button.mrow:active .chev { transform: translateX(3px); }
.mrow .mval { transition: opacity 0.2s; }
.mrow .mi { width: 24px; height: 24px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* The recovery-code key: the sign-in key's shape, drawn as an outline like the other icons */
.mrow .mi.fill { fill: none; stroke: currentColor; stroke-width: 3.4; stroke-linejoin: round; width: 23px; height: 23px; margin: 0 0.5px; }
.mrow .mlabel { flex: 1; min-width: 0; }
.mrow .mval { color: var(--muted); font-size: 15px; white-space: nowrap; }
.mrow .chev { width: 16px; height: 16px; flex: none; fill: none; stroke: var(--muted); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.mrow.danger { color: var(--danger); }
.macct { min-height: 64px; }
.macct .pfp { width: 46px; height: 46px; }
.macct .mlabel { display: flex; flex-direction: column; gap: 2px; }
.macct b { font-size: 16px; font-weight: 600; }
.macct small { font-size: 14px; color: var(--muted); }
.menu-view .invite-box { padding: 4px 0 12px; }
.menu-view .invite-box .small { margin: 0 0 10px; font-size: 14px; line-height: 1.4; color: var(--muted); }
/* The recovery code screen */
.code-view { z-index: 180; }
.code-screen { width: 100%; max-width: 440px; min-height: 100%; margin: 0 auto; display: flex; flex-direction: column; text-align: center; padding-top: 44px; }
/* The key in the app icon's blue-to-red glow */
.code-hero {
  align-self: center; width: 84px; height: 84px; border-radius: 26px; display: grid; place-items: center; color: #fff; margin-bottom: 22px;
  background: radial-gradient(circle at 10% 105%, #1a7cff, #2f5bff 35%, #8a3df0 60%, #e8306a 82%, #ff3b30);
  box-shadow: 0 10px 28px rgba(90, 60, 255, 0.28);
}
.code-hero .key { width: 42px; height: 42px; fill: currentColor; filter: drop-shadow(0 4px 8px rgba(30, 10, 60, 0.3)); }
.code-screen h1 { margin: 0 0 8px; font-size: 26px; line-height: 1.15; font-weight: 700; letter-spacing: -0.3px; }
.code-lead { margin: 0 12px 26px; color: var(--muted); font-size: 15px; line-height: 1.45; }
/* Four numbered groups, like a wallet's recovery words */
.code-card { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.code-card .grp { position: relative; padding: 16px 0 14px; border-radius: 18px; background: var(--solid); font: 600 21px ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: 2.5px; }
.code-card .grp b { position: absolute; top: 8px; left: 12px; font: 600 11px -apple-system, system-ui, sans-serif; letter-spacing: 0; color: var(--muted); }
.code-actions { margin-top: 18px; text-align: left; }
.code-actions .mrow { border-top: 0.5px solid var(--line); border-radius: 0; }
.code-actions .mrow:first-child { border-top: 0; }
.code-bottom { margin-top: auto; padding-top: 28px; }

.menu-empty { text-align: center; color: var(--muted); margin: 40px 0; }
.msec-note { margin: -4px 0 8px 38px; font-size: 13px; line-height: 1.4; color: var(--muted); }
.mrow .mlabel small { display: block; font-size: 13px; color: var(--muted); margin-top: 1px; }
.mrow .check { width: 22px; height: 22px; fill: none; stroke: var(--accent); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; visibility: hidden; }
.mrow.picked .check { visibility: visible; }
/* Liquid-glass switch, like iOS 26: a pill-shaped knob that, while you hold it, swells
   into a clear glass droplet with a bright rim, then settles back as it slides across */
.switch {
  -webkit-appearance: none; appearance: none; flex: none; position: relative; width: 63px; height: 28px; margin: 0;
  border-radius: 999px; cursor: pointer; overflow: visible; -webkit-tap-highlight-color: transparent;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.08), transparent 60%), rgba(120, 120, 128, 0.32);
  transition: background-color 0.3s;
}
.switch:checked { background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), transparent 60%), #34c759; }
.switch::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 37px; height: 24px; border-radius: 999px;
  background: #fff;
  box-shadow: 0 2px 7px rgba(0, 0, 0, 0.16), 0 0 0 0.5px rgba(0, 0, 0, 0.05);
  transition: transform 0.42s cubic-bezier(0.3, 1.35, 0.45, 1), background-color 0.18s, box-shadow 0.18s;
}
.switch::after { transform: translateX(var(--kx, 0px)); }
.switch:checked::after { transform: translateX(var(--kx, 22px)); }
.switch.dragging::after { transition: background-color 0.18s, box-shadow 0.18s; }
.switch:active::after {
  transform: translateX(var(--kx, 0px)) scale(1.38, 1.5);
  background: rgba(255, 255, 255, 0.16);
  -webkit-backdrop-filter: blur(1.5px) saturate(1.8); backdrop-filter: blur(1.5px) saturate(1.8);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.75), inset 0 1.5px 2px rgba(255, 255, 255, 0.9),
    inset 0 -2px 4px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.18);
}
.switch:checked:active::after { transform: translateX(var(--kx, 22px)) scale(1.38, 1.5); }
.switch:disabled { opacity: 0.5; }
.nick-who { cursor: default; }
/* Appearance: two little previews of the app, like iPhone's Display & Brightness */
.appear { padding-top: 14px; }
.appear-pick { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; padding: 6px 4px 8px; }
.appear-opt { display: flex; flex-direction: column; align-items: center; gap: 10px; border: 0; background: none; padding: 0; color: var(--fg); font: inherit; -webkit-tap-highlight-color: transparent; }
.appear-opt:active .mock { transform: scale(0.97); }
.mock {
  position: relative; display: block; width: 100%; max-width: 128px; aspect-ratio: 9 / 16; border-radius: 20px; overflow: hidden;
  box-shadow: 0 0 0 1px var(--line), 0 8px 20px rgba(0, 0, 0, 0.12); transition: transform 0.25s, box-shadow 0.25s;
}
.appear-opt.picked .mock, .appear-opt.picked .mock-auto { box-shadow: 0 0 0 2.5px var(--bg), 0 0 0 5px var(--accent), 0 8px 20px rgba(0, 0, 0, 0.12); }
/* Automatic: light and dark split diagonally in one preview */
.mock-auto {
  position: relative; display: block; width: 100%; max-width: 128px; aspect-ratio: 9 / 16; border-radius: 20px; overflow: hidden;
  box-shadow: 0 0 0 1px var(--line), 0 8px 20px rgba(0, 0, 0, 0.12); transition: transform 0.25s, box-shadow 0.25s;
}
.mock-auto .mock { position: absolute; inset: 0; max-width: none; border-radius: 0; box-shadow: none; }
.mock-auto .mock-dark { clip-path: polygon(100% 0, 100% 100%, 0 100%); }
.appear-opt:active .mock-auto { transform: scale(0.97); }
.appear-opt.picked .appear-name { color: var(--accent); }

.mock i { position: absolute; display: block; border-radius: 999px; }
.mock-light { background: #fff; } .mock-light i { background: #e6e6ea; }
.mock-dark { background: #121214; } .mock-dark i { background: #2a2a2e; }
.mock .m-top { top: 10%; left: 32%; right: 32%; height: 4%; }
.mock .m-pfp { top: 19%; left: 10%; width: 26%; aspect-ratio: 1; }
.mock .m-l1 { top: 22%; left: 42%; right: 12%; height: 4%; }
.mock .m-l2 { top: 29%; left: 42%; right: 26%; height: 4%; }
.mock .m-btn { top: 38%; left: 10%; width: 38%; height: 6%; border-radius: 6px; }
.mock .m-btn.b2 { left: 52%; }
.mock .m-bar { bottom: 6%; left: 10%; right: 10%; height: 8%; }
.mock-light .m-bar { background: rgba(255, 255, 255, 0.92); box-shadow: 0 0 0 1px #e6e6ea; }
.mock-dark .m-bar { background: #000; box-shadow: 0 0 0 1px #2a2a2e; }

.appear-name { font-size: 15px; font-weight: 600; transition: color 0.2s; }
.appear-opt.dim { opacity: 0.55; }
/* Picture cropper: the photo in a square, a round window showing what's kept */
.crop-view { z-index: 165; }
.crop-stage {
  position: relative; width: 100%; max-width: 420px; aspect-ratio: 1; margin: 18px auto 0; overflow: hidden;
  border-radius: 24px; background: #000; touch-action: none; cursor: grab;
}
.crop-stage img { position: absolute; left: 0; top: 0; transform-origin: 0 0; max-width: none; user-select: none; -webkit-user-select: none; pointer-events: none; }
.crop-hole { position: absolute; inset: 6px; border-radius: 50%; box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.55); outline: 2.5px solid rgba(255, 255, 255, 0.92); pointer-events: none; }
.crop-zoom { display: flex; align-items: center; gap: 12px; max-width: 420px; margin: 22px auto 0; padding: 0 6px; color: var(--muted); }
.crop-zoom svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
/* The zoom slider: a thin track with a blue fill and a liquid glass knob, like iOS 26 */
.crop-zoom input {
  flex: 1; -webkit-appearance: none; appearance: none; height: 30px; margin: 0; background: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: none;
}
.crop-zoom input::-webkit-slider-runnable-track {
  height: 6px; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) var(--p, 0%), rgba(120, 120, 128, 0.32) var(--p, 0%));
}
.crop-zoom input::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 38px; height: 24px; margin-top: -9px; border-radius: 999px;
  background: #fff; box-shadow: 0 2px 7px rgba(0, 0, 0, 0.18), 0 0 0 0.5px rgba(0, 0, 0, 0.06);
  transform: translateX(var(--zx, 0px)) scale(var(--zsx, 1), var(--zsy, 1)); /* springs in auth.js */
  transition: background-color 0.18s, box-shadow 0.18s;
}
/* Held: the knob swells into clear glass you can see the track through */
.crop-zoom input.held::-webkit-slider-thumb {
  background: rgba(255, 255, 255, 0.16);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.75), inset 0 1.5px 2px rgba(255, 255, 255, 0.9),
    inset 0 -2px 4px rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.18);
}
/* Rule-of-thirds grid over the photo, brighter while you're moving it */
.crop-grid { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.25s; } /* only while dragging */
.crop-stage.moving .crop-grid { opacity: 0.9; }
.crop-grid i { position: absolute; background: rgba(255, 255, 255, 0.8); box-shadow: 0 0 2px rgba(0, 0, 0, 0.45); }
.crop-grid i:nth-child(1), .crop-grid i:nth-child(2) { top: 0; bottom: 0; width: 2px; margin-left: -1px; }
.crop-grid i:nth-child(1) { left: 33.333%; } .crop-grid i:nth-child(2) { left: 66.666%; }
.crop-grid i:nth-child(3), .crop-grid i:nth-child(4) { left: 0; right: 0; height: 2px; margin-top: -1px; }
.crop-grid i:nth-child(3) { top: 33.333%; } .crop-grid i:nth-child(4) { top: 66.666%; }
.nick-for { font-size: 17px; font-weight: 600; }
.edit-section { font-size: 17px; font-weight: 600; color: var(--fg); margin: 24px 4px 10px; }
/* The preview: your profile header exactly as it'll appear, in a card */
/* In its own rounded square, the same fill as the name and bio card */
.edit-preview { border-radius: 18px; padding: 16px 16px 4px; background: var(--solid); pointer-events: none; }
.edit-preview .profile-head { margin: 0 0 10px; gap: 18px; }
.pfp.big-preview { width: 76px; height: 76px; }
.edit-preview .bio { margin: 0 0 12px; }
.edit-preview .bio:empty { display: none; }
.story-pfp {
  position: relative; flex: none; display: block; padding: 0; border: 0; background: none; border-radius: 50%;
  -webkit-tap-highlight-color: transparent; transition: transform 0.2s cubic-bezier(0.3, 1.35, 0.45, 1);
}
.story-pfp:active { transform: scale(0.95); }
.pfp.huge { width: 88px; height: 88px; }
/* The + for adding to your story: a blue dot cut out of the picture's corner */
.story-add {
  position: absolute; right: -2px; bottom: -2px; width: 28px; height: 28px; padding: 0;
  border: 3px solid var(--bg); border-radius: 50%; background: #fff; color: #000;
  display: grid; place-items: center; -webkit-tap-highlight-color: transparent;
}
.story-add svg { width: 15px; height: 15px; fill: none; stroke: #000; stroke-width: 3.2; stroke-linecap: round; }

/* Light mode flips it: black dot, white + */
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) .story-add { background: #000; }
:root:not([data-theme="dark"]) .story-add svg { stroke: #fff; }
}
/* (chosen in Settings → Appearance) */
:root[data-theme="light"] .story-add { background: #000; }
:root[data-theme="light"] .story-add svg { stroke: #fff; }
.profile-info { flex: 1; min-width: 0; }
.name-row { display: flex; align-items: baseline; gap: 6px; margin: 0 0 8px; min-width: 0; }
.profile-info h2 { margin: 0; font-size: 15px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Always lowercase and always in quotes, whatever it says */
.nickname { flex: none; font-size: 13px; color: var(--muted); text-transform: lowercase; }
.nickname[hidden] { display: none; }
.nickname::before { content: "\201C"; }
.nickname::after { content: "\201D"; }
/* A solid band where the status bar is: the page slides under this instead of under
   the status bar, where iOS would blur it */
/* Switching light/dark: the colours glide over a quarter second */
html.theming *, html.theming *::before, html.theming *::after {
  transition: background-color 0.28s ease, color 0.28s ease, border-color 0.28s ease, fill 0.28s ease, stroke 0.28s ease, box-shadow 0.28s ease !important;
}
html.theming, html.theming body { transition: background-color 0.28s ease, color 0.28s ease; }
html.theming .top-probe { transition: none !important; }
.top-probe { position: fixed; top: 0; left: 0; right: 0; height: calc(var(--safe-top) + 10px); background: var(--bg); z-index: 2147483647; }
.status-cover { position: fixed; top: 0; left: 0; right: 0; height: var(--safe-top); background: var(--bg); z-index: 8; pointer-events: none; transform: translateY(var(--vv-top, 0px)); }
/* The other person's profile, slid in from the right */
.profile-view {
  position: fixed; inset: 0; z-index: 150; overflow-y: auto; background: var(--bg); color: var(--fg);
  padding: calc(var(--safe-top) + 12px) max(16px, env(safe-area-inset-right)) calc(var(--safe-bottom) + 24px) max(16px, env(safe-area-inset-left));
  /* It slides with a transform (smooth: the phone just moves it, no redrawing). Its top row
     and typing box live outside it, in a layer that slides along with it (.view-float, see
     app.js), so they never scroll away mid-slide or flicker when it lands. */
  transform: translateX(100%); transition: transform 0.45s cubic-bezier(0.32, 0.72, 0, 1), filter 0.45s cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: -14px 0 30px rgba(0, 0, 0, 0.12); /* a soft edge while it slides over the screen below */
}
/* The screen underneath shifts a little left and dims, like iPhone Settings */
.profile-view.open.behind, .view-float.open.behind { transform: translateX(-28%); filter: brightness(0.86); }
.profile-view.open, .view-float.open { transform: none; }
/* The layer holding a screen's top row and typing box: moves exactly like its screen */
.view-float {
  position: fixed; inset: 0; z-index: 150; pointer-events: none; --kb: 0px; --composer-h: 60px;
  transform: translateX(100%); transition: transform 0.45s cubic-bezier(0.32, 0.72, 0, 1), filter 0.45s cubic-bezier(0.32, 0.72, 0, 1);
}
.view-float[hidden] { display: none; }
.view-float > * { pointer-events: auto; }
/* Full-screen views scroll natively (the app's own scroller only drives the main pages).
   Their top row (back button and title) stays put while the rest scrolls under it, with
   no background behind it. */
.profile-view { overflow-x: clip; }
/* Pinned to the screen itself (not the scrolling content), so nothing moves it, not even
   pulling past the top. The screen's padding makes room for it. */
.view-float > .edit-top, .view-float > .profile-top {
  position: fixed; z-index: 20; top: calc(var(--safe-top) + 12px); max-width: 648px; margin: 0 auto;
  transform: translateY(var(--vv-top, 0px)); /* (stays at the top when the keyboard slides the screen up) */
  left: max(12px, calc(env(safe-area-inset-left) - 4px)); right: max(12px, calc(env(safe-area-inset-right) - 4px));
}
.view-float > .profile-top { left: max(6px, calc(env(safe-area-inset-left) - 10px)); right: max(6px, calc(env(safe-area-inset-right) - 10px)); max-width: 660px; }
/* A fade behind the pinned header, so text slides underneath it (lens.js draws the same
   fade inside the glass buttons) */
.view-float > .edit-top::before, .view-float > .profile-top::before {
  content: ""; position: absolute; z-index: -1; left: -60px; right: -60px; pointer-events: none;
  top: calc(-1 * (var(--safe-top) + 120px)); bottom: -24px;
  background: linear-gradient(to bottom, var(--bg) calc(var(--safe-top) + 120px), color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--safe-top) + 142px), transparent);
}
.profile-view.has-edit-top { padding-top: calc(var(--safe-top) + 12px + 54px); }
.profile-view.has-profile-top { padding-top: calc(var(--safe-top) + 12px + 50px); }


/* The profile page's top row (+, nickname, menu) is held in place by app.js */
.page > .profile-top { position: relative; z-index: 6; will-change: transform; }

.profile-view { overscroll-behavior: contain; -webkit-overflow-scrolling: touch; touch-action: pan-y; }
.profile-view[hidden] { display: none; }
.profile-view > * { max-width: 640px; margin-left: auto; margin-right: auto; }
.profile-view .profile-top { margin: 0 auto; }
.profile-view .bio { cursor: default; }
.pv-left, .pv-right { display: flex; align-items: center; min-width: 0; }
.pv-title { font-size: 20px; font-weight: 700; letter-spacing: -0.3px; margin-left: -2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.icon-btn svg path { stroke-linejoin: round; }
.icon-btn svg.dots { fill: currentColor; stroke: none; }
.profile-actions.single { grid-template-columns: 1fr; }
/* Profile sections: four icon tabs across the full width, a sliding underline, and an
   empty state until there's something to show */
.ptabs { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); margin: 0 -16px; border-bottom: 0.5px solid var(--line); }
.ptabs button {
  height: 46px; border: 0; background: none; padding: 0; display: grid; place-items: center;
  color: var(--muted); transition: color 0.2s; -webkit-tap-highlight-color: transparent;
}
.ptabs button.on { color: var(--fg); }
.ptabs svg { width: 25px; height: 25px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.ptabs-bar {
  position: absolute; left: 0; bottom: -0.5px; width: 25%; height: 1.5px; background: var(--fg);
  transform: translateX(calc(var(--i, 0) * 100%)); transition: transform 0.42s cubic-bezier(0.25, 1.15, 0.4, 1);
}
.ptab-empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 56px 0 40px; color: var(--fg); }
.ptab-icon { width: 68px; height: 68px; border-radius: 50%; border: 2px solid var(--fg); display: grid; place-items: center; }
.ptab-icon svg { width: 32px; height: 32px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.ptab-title { font-size: 20px; font-weight: 700; }
/* @username, centred between the + and the menu, as big as those icons */
.profile-handle { flex: 1; min-width: 0; text-align: center; font-size: 20px; font-weight: 700; letter-spacing: -0.3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Three equal columns, so the counts sit evenly however big the numbers get */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); column-gap: 8px; }
.stats div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.stats b { font-size: 17px; font-weight: 700; line-height: 22px; font-variant-numeric: tabular-nums; letter-spacing: -0.2px; }
.stats span { font-size: 13px; line-height: 17px; color: var(--fg); }
.pfp-pick { cursor: pointer; display: block; flex: none; }
.pfp-pick:active { opacity: 0.7; }
.account h3 { font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); margin: 22px 4px 8px; }
.group {
  border-radius: 24px; overflow: hidden; margin-bottom: 14px; background: var(--solid);
}
.row-item.action { transition: background 0.2s; }
.row-item.action:active { background: var(--field); }
.row-item {
  display: flex; justify-content: space-between; align-items: center; width: 100%;
  min-height: 48px; padding: 0 16px; font-size: 17px; text-align: left; color: var(--fg);
}
.row-item[hidden] { display: none; }
.row-item + .row-item, .row-item + .invite-box { border-top: 0.5px solid var(--line); }
.row-item.action { color: var(--accent); }
.row-item .value { color: var(--muted); }
.invite-box { padding: 14px 16px 16px; }
.invite-box .small { margin: 0 0 10px; }
.invite-url { font: 13px ui-monospace, Menlo, monospace; word-break: break-all; padding: 10px 14px; border-radius: 16px; background: var(--field); margin-bottom: 12px; -webkit-user-select: all; user-select: all; }
.invite-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.invite-actions button { height: 42px; font-size: 15px; flex: 1; }

/* Splash while the app starts (index.html); auth.js fades it away once a screen is ready */
#splash {
  position: fixed; inset: 0; z-index: 5000; background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  transition: opacity 0.35s ease;
}
#splash.gone { opacity: 0; pointer-events: none; }
.splash-heart { width: 88px; height: auto; overflow: visible; margin-top: calc(-2 * var(--splash-shift, 0px)); } /* (centred on the whole screen) */
/* Sized like Instagram's "from Meta": a 15pt grey "from", then a 21pt medium-weight name */
.splash-by {
  position: absolute; left: 0; right: 0; bottom: calc(var(--safe-bottom) + 30px);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
}
.splash-by span { font-size: 15px; font-weight: 400; color: #8a8d98; }
.splash-by b {
  font-size: 22px; line-height: 1.2; font-weight: 600; letter-spacing: -0.2px; padding: 0 2px;
  background: linear-gradient(90deg, #1a7cff, #2f5bff 30%, #8a3df0 55%, #e8306a 80%, #ff3b30);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* In-app banner, like Instagram's for a new DM: a dark rounded card with a big round
   picture, the name in bold and the message underneath, both white. Slides down from the
   top, swipe it up to dismiss, tap to open. Above every screen (only the splash is higher). */
.banner {
  position: fixed; z-index: 4000; left: 8px; right: 8px; top: calc(var(--safe-top) + 6px); max-width: 520px; margin: 0 auto;
  display: flex; align-items: center; gap: 13px; height: 68px; box-sizing: border-box; padding: 0 16px 0 12px; border-radius: 24px;
  background: linear-gradient(90deg, #1b1b1d, #232325); color: #fff;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.22);
  /* Like Instagram's: slides down from above the screen and eases to a stop (no bounce, no
     fade), and slides back up the same way */
  transform: translateY(calc(var(--by, 0px) - 100% - var(--safe-top) - 14px)); pointer-events: none;
  transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); /* leaves the way it came in */
  -webkit-tap-highlight-color: transparent; touch-action: none; cursor: pointer;
}
.banner.show { transform: translateY(var(--by, 0px)); pointer-events: auto; transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); }
.banner.dragging { transition: none; }
.banner-pfp { width: 43px; height: 43px; border-radius: 50%; object-fit: cover; flex: none; background: rgba(128, 128, 128, 0.3); }
.banner-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0; }
/* Both lines the same size, like Instagram's: the name a little bolder, the message on one line */
.banner-text b, .banner-text span { font-size: 15px; line-height: 1.12; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.banner-text b { font-weight: 600; letter-spacing: -0.1px; }
.banner-text span { font-weight: 400; color: #fff; }
@media (prefers-color-scheme: light) {
:root:not([data-theme="dark"]) .banner { background: #fff; color: #000; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.14), inset 0 0 0 0.5px rgba(0, 0, 0, 0.06); }
:root:not([data-theme="dark"]) .banner-text span { color: #000; }
}
/* (chosen in Settings → Appearance) */
:root[data-theme="light"] .banner { background: #fff; color: #000; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.14), inset 0 0 0 0.5px rgba(0, 0, 0, 0.06); }
:root[data-theme="light"] .banner-text span { color: #000; }

/* ---------- Messages ---------- */
/* Unread messages: a red dot at the bottom right of the Messages icon, on the icon and on
   its copy inside the selected-tab pill (so it shows on whichever is on top) */
.tab[data-tab="messages"]::after, .lens-icons > span:nth-child(3)::after {
  content: ""; position: absolute; left: calc(50% + 8px); top: calc(50% + 6px); width: 7px; height: 7px; border-radius: 50%;
  background: #ff3040; pointer-events: none;
  transform: scale(0); transition: transform 0.3s cubic-bezier(0.3, 1.6, 0.5, 1);
}
.lens-icons > span:nth-child(3) { position: relative; }
#tabbar.unread .tab[data-tab="messages"]::after, #tabbar.unread .lens-icons > span:nth-child(3)::after { transform: scale(1); }
/* Inbox: one row for your conversation, like Instagram's */
.inbox-row {
  display: flex; align-items: center; gap: 14px; width: calc(100% + 32px); margin: 6px -16px 0; padding: 10px 16px;
  border: 0; background: none; color: var(--fg); text-align: left; font: inherit; -webkit-tap-highlight-color: transparent;
}
.inbox-row:active { background: var(--field); }
.inbox-pfp { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; flex: none; background: var(--solid); }
.inbox-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.inbox-text b { font-size: 15px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inbox-text span { font-size: 14px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inbox-row.unread .inbox-text span { color: var(--fg); font-weight: 600; }
.inbox-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); flex: none; }

/* The conversation */
.chat-view { --composer-h: 60px; --kb: 0px; padding-bottom: calc(var(--composer-h) + max(var(--kb), var(--safe-bottom)) + 8px); }
.chat-top { grid-template-columns: 44px 1fr; }
/* Like Instagram: their picture on the left by the back button, the name ›, and when they were last on under it */
.chat-who { justify-self: start; display: flex; align-items: center; gap: 10px; min-width: 0; max-width: 100%; border: 0; background: none; padding: 4px 6px 4px 10px; color: var(--fg); font: inherit; text-align: left; -webkit-tap-highlight-color: transparent; }
.chat-names { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
.chat-name-row { display: flex; align-items: center; gap: 1px; min-width: 0; }
.chat-name-row svg { flex: none; width: 15px; height: 15px; fill: none; stroke: var(--muted); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.chat-sub { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.chat-sub:empty { display: none; }
.chat-who:active { opacity: 0.6; }
.chat-pfp { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex: none; background: var(--solid); }
.chat-name { font-size: 16px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-list { display: flex; flex-direction: column; padding: 4px 0 0; }
.chat-more { align-self: center; margin: 6px 0 12px; font-size: 13px; color: var(--muted); }
.msg-time { align-self: center; margin: 16px 0 8px; font-size: 12px; font-weight: 600; color: var(--muted); }
.msg { display: flex; align-items: flex-end; gap: 8px; margin-top: 2px; max-width: 100%; }
.msg.first { margin-top: 8px; }
.msg.mine { flex-direction: row-reverse; }
.msg-pfp { width: 28px; height: 28px; margin-bottom: 6px; border-radius: 50%; object-fit: cover; flex: none; visibility: hidden; } /* level with the middle of the last line */
.msg.reacted .msg-pfp { margin-bottom: 20px; } /* (above the reaction under it) */
.msg.theirs.last .msg-pfp { visibility: visible; }
.msg.mine .msg-pfp { display: none; }
.msg-col { display: flex; flex-direction: column; max-width: 74%; position: relative; }
.msg.mine .msg-col { align-items: flex-end; }
.msg.theirs .msg-col { align-items: flex-start; } /* (a bubble is only as wide as its text, not its reply label) */
.bubble {
  max-width: none; width: auto; margin: 0; /* (not the old demo .bubble sizing) */
  padding: 9px 14px; border-radius: 20px; font-size: 17px; line-height: 1.3; white-space: pre-wrap; overflow-wrap: break-word;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; touch-action: manipulation;
}
.msg.theirs .bubble { background: var(--solid); color: var(--fg); }
.msg.mine .bubble { background: linear-gradient(135deg, #2f6bff, #1a7cff); color: #fff; }
/* Stacked messages: the corners on the sender's side tighten, like Instagram */
.msg.theirs:not(.first) .bubble { border-top-left-radius: 5px; }
.msg.theirs:not(.last) .bubble { border-bottom-left-radius: 5px; }
.msg.mine:not(.first) .bubble { border-top-right-radius: 5px; }
.msg.mine:not(.last) .bubble { border-bottom-right-radius: 5px; }
/* A few emoji on their own: big, no bubble */
.bubble.big { background: none !important; padding: 0 2px; font-size: 44px; line-height: 1.1; }
.msg.pending .bubble { opacity: 0.6; }
.msg.failed .bubble { opacity: 0.6; }
.msg-react {
  align-self: flex-start; margin: -6px 0 0 8px; position: relative; z-index: 1; padding: 1px 5px; border-radius: 12px;
  background: var(--bg); box-shadow: 0 0 0 2px var(--bg); font-size: 13px; line-height: 18px; background-color: var(--solid);
}
.msg.mine .msg-react { align-self: flex-end; margin: -6px 8px 0 0; }
.msg-react.pop { animation: heartPop 0.45s cubic-bezier(0.3, 1.6, 0.5, 1); }
.msg-react small { font-size: 12px; font-weight: 600; color: var(--muted); margin-left: 2px; }
@keyframes heartPop { from { transform: scale(0.2); } to { transform: scale(1); } }
.msg-status { align-self: flex-end; margin: 3px 4px 0; font-size: 12px; color: var(--muted); }
.msg-status.failed { color: var(--danger); }
/* Typing: three dots bouncing in a bubble */
.typing .bubble { display: flex; gap: 4px; padding: 16.5px 15px; }
.typing .bubble i { display: block; width: 7px; height: 7px; border-radius: 50%; background: var(--muted); animation: typingDot 1.2s infinite ease-in-out; }
.typing .bubble i:nth-child(2) { animation-delay: 0.15s; }
.typing .bubble i:nth-child(3) { animation-delay: 0.3s; }
@keyframes typingDot { 0%, 60%, 100% { opacity: 0.6; } 30% { opacity: 0.9; } } /* a subtle pulse, no bounce */
.chat-empty { align-self: center; margin-top: 30vh; text-align: center; color: var(--muted); font-size: 15px; }
.chat-empty img { display: block; width: 84px; height: 84px; border-radius: 50%; object-fit: cover; margin: 0 auto 12px; }
.chat-empty b { display: block; color: var(--fg); font-size: 18px; margin-bottom: 4px; }

/* Typing box: pinned to the bottom, riding up with the keyboard */
.composer {
  position: fixed; z-index: 20; left: 0; right: 0; bottom: max(var(--kb), var(--safe-bottom)); max-width: 672px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 0; padding: 8px 12px;
  transition: none;
}
/* Messages fade out beneath it: smoothly, fully gone by the middle of the typing box */
.composer::before {
  content: ""; position: absolute; z-index: -1; left: -60px; right: -60px; top: -32px; bottom: -60px; pointer-events: none;
  background: linear-gradient(to bottom,
    transparent 0,
    color-mix(in srgb, var(--bg) 12%, transparent) 14px,
    color-mix(in srgb, var(--bg) 35%, transparent) 28px,
    color-mix(in srgb, var(--bg) 62%, transparent) 42px,
    color-mix(in srgb, var(--bg) 86%, transparent) 54px,
    var(--bg) 64px);
}
.composer-row { /* one capsule, like Instagram */
  display: flex; align-items: flex-end; gap: 4px; min-height: 48px; padding: 5px; box-sizing: border-box; border-radius: 24px;
  background: var(--solid);
}
.cmp-camera {
  flex: none; width: 38px; height: 38px; border-radius: 50%; border: 0; padding: 0; display: grid; place-items: center;
  background: linear-gradient(135deg, #2f6bff, #1a7cff); color: #fff; -webkit-tap-highlight-color: transparent; transition: transform 0.3s cubic-bezier(0.3, 1.4, 0.5, 1);
}
.cmp-camera:active { transform: scale(0.88); }
.cmp-camera svg { width: 22px; height: 22px; fill: currentColor; grid-area: 1 / 1; }
.cmp-camera { transition: transform 0.3s cubic-bezier(0.3, 1.4, 0.5, 1), background-color 0.2s; }
/* While typing: a plain search icon (for GIFs, like Instagram) instead of the blue camera */
.cmp-camera .cmp-search { display: none; fill: none; stroke: var(--fg); stroke-width: 2; stroke-linecap: round; width: 24px; height: 24px; }
.composer.typing .cmp-camera { background: transparent; }
.composer.typing .cmp-camera svg:first-child { display: none; }
.composer.typing .cmp-camera .cmp-search { display: block; animation: iconIn 0.22s ease-out; }
@keyframes iconIn { from { opacity: 0; transform: scale(0.8); } }
.cmp-tools { flex: none; display: flex; align-items: center; height: 38px; padding-right: 4px; transition: opacity 0.18s; }
.cmp-tools button {
  width: 34px; height: 38px; border: 0; padding: 0; display: grid; place-items: center; background: none; color: var(--fg);
  -webkit-tap-highlight-color: transparent; transition: transform 0.3s cubic-bezier(0.3, 1.4, 0.5, 1);
}
.cmp-tools button:active { transform: scale(0.85); }
.cmp-tools svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.composer.typing .cmp-tools { display: none; } /* tools step aside for Send */
/* Rising and falling with the keyboard, at its pace */
.view-float.kb-move > .composer { transition: bottom 0.42s cubic-bezier(0.2, 0.85, 0.25, 1); }
.composer textarea {
  flex: 1; min-width: 0; min-height: 38px; max-height: 128px; resize: none; box-sizing: border-box; padding: 9px 6px 9px 8px; border: 0; border-radius: 0;
  background: none; color: var(--fg); font: 17px/1.18 -apple-system, system-ui, sans-serif; outline: none;
}
.composer textarea::placeholder { color: var(--muted); }
.chat-send {
  flex: none; width: 38px; height: 38px; border-radius: 50%; border: 0; padding: 0; display: none; place-items: center;
  background: linear-gradient(135deg, #2f6bff, #1a7cff); color: #fff; -webkit-tap-highlight-color: transparent;
  transition: transform 0.3s cubic-bezier(0.3, 1.4, 0.5, 1);
}
/* Send arrives smoothly: the circle grows in, and the plane glides in from the bottom left */
/* Send pops in from nothing (quick, no bounce), and shrinks away when the box is cleared */
.composer.typing .chat-send { display: grid; animation: sendPop 0.2s cubic-bezier(0.25, 0.8, 0.35, 1); }
.composer.typing.leaving .chat-send { animation: sendOut 0.14s ease-in forwards; }
@keyframes sendPop { from { opacity: 0; transform: scale(0); } }
@keyframes sendOut { to { opacity: 0; transform: scale(0); } }
/* ...then the tools come back, one after another */
.composer.tools-in .cmp-tools button { animation: toolIn 0.22s cubic-bezier(0.25, 0.8, 0.35, 1) both; }
.composer.tools-in .cmp-tools button:nth-child(2) { animation-delay: 30ms; }
.composer.tools-in .cmp-tools button:nth-child(3) { animation-delay: 60ms; }
.composer.tools-in .cmp-tools button:nth-child(4) { animation-delay: 90ms; }
@keyframes toolIn { from { opacity: 0; transform: scale(0.5); } }
.chat-send:active { transform: scale(0.9); }
.chat-send svg { width: 22px; height: 22px; margin: 2px 2px 0 0; } /* (optically centred) */
.chat-send .plane { fill: #fff; stroke: #fff; stroke-width: 1.6; stroke-linejoin: round; }
.chat-send .fold { fill: none; stroke: #2477ff; stroke-width: 1.6; stroke-linecap: round; }

/* Inbox top: a smaller title, a search, and the two of you (like Instagram's row of friends) */
.inbox-title { font-size: 17px; font-weight: 700; margin: 14px 0 2px; }
.inbox-title[hidden] { display: none; }
.inbox-search { margin: 2px 0 16px; height: 40px; border-radius: 999px; padding: 0 14px; } /* a capsule */
.inbox-people { display: flex; gap: 18px; padding: 0 0 6px; }
.person { display: flex; flex-direction: column; align-items: center; gap: 6px; width: 88px; border: 0; background: none; padding: 0; color: var(--fg); font: inherit; -webkit-tap-highlight-color: transparent; }
.person img { width: 84px; height: 84px; border-radius: 50%; object-fit: cover; background: var(--solid); transition: transform 0.2s cubic-bezier(0.3, 1.35, 0.45, 1); }
.person:active img { transform: scale(0.94); }
.person span { max-width: 100%; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inbox-people[hidden], .inbox-row[hidden] { display: none; }
/* Search results: matching messages */
.inbox-results { display: flex; flex-direction: column; }
.inbox-results[hidden] { display: none; }
.result { display: flex; align-items: center; gap: 12px; width: calc(100% + 32px); margin: 0 -16px; padding: 9px 16px; border: 0; background: none; color: var(--fg); text-align: left; font: inherit; -webkit-tap-highlight-color: transparent; }
.result:active { background: var(--field); }
.result img { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; flex: none; }
.result-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.result-text b { font-size: 14px; font-weight: 600; }
.result-text span { font-size: 14px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.result-text mark { background: none; color: var(--fg); font-weight: 600; }
.result time { font-size: 12px; color: var(--muted); flex: none; align-self: flex-start; margin-top: 3px; }
.inbox-none { padding: 30px 0; text-align: center; color: var(--muted); font-size: 14px; }
.msg.flash .bubble { animation: msgFlash 1.4s ease; }
@keyframes msgFlash { 0%, 100% { filter: none; } 20%, 60% { filter: brightness(1.35); } }

/* A reply: a small label, then the quoted message (faded) above the new one */
.msg-replied { font-size: 12px; color: var(--muted); margin: 2px 6px 3px; }
.msg-qrow { display: flex; gap: 8px; max-width: 100%; margin-bottom: 4px; } /* (a small gap above the reply) */
.msg.mine .msg-qrow { flex-direction: row-reverse; }
/* Theirs: the quote lines up with their bubble, and the line sits in the gap beside it */
.msg.theirs .msg-qrow { position: relative; }
.msg.theirs .msg-qline { position: absolute; left: -6px; top: 0; bottom: 0; }
.msg.theirs .msg-replied { margin-left: 4px; }
.msg-qline { flex: none; width: 3px; border-radius: 2px; background: var(--solid); filter: brightness(1.6); }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .msg-qline { filter: brightness(0.85); } }
:root[data-theme="light"] .msg-qline { filter: brightness(0.85); }
.msg-quote {
  min-width: 0; padding: 7px 12px; border-radius: 18px; font-size: 14px; line-height: 1.3;
  overflow-wrap: break-word; -webkit-user-select: none; user-select: none;
}
/* The quoted message keeps its own colours (blue if it was yours, grey if theirs), a bit darker */
.msg-quote.q-theirs { background: var(--solid); color: var(--fg); filter: brightness(0.78); }
.msg-quote.q-mine { background: linear-gradient(135deg, #2f6bff, #1a7cff); color: #fff; filter: brightness(0.68); }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .msg-quote.q-theirs { filter: brightness(0.9); } }
:root[data-theme="light"] .msg-quote.q-theirs { filter: brightness(0.9); }
.msg-quote.gone { background: transparent; color: var(--muted); border: 0.5px solid var(--line); filter: none; }
.msg-quote > span:not([class]) { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } /* at most two lines */
.msg-quote.gone { font-style: italic; }
.msg-col > .bubble { position: relative; }

/* Replying bar above the typing box */
/* Clipped at the top of the typing box, so it rises out from behind it */
.reply-bar { overflow: hidden; margin: 0 -12px; }
.reply-inner {
  display: flex; align-items: center; gap: 10px; padding: 8px 18px 10px 26px; background: var(--bg); /* solid: nothing shows through */
  transition: transform 0.3s cubic-bezier(0.2, 0.85, 0.25, 1);
}
.reply-bar[hidden] { display: none; }
.reply-what { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.reply-what b { font-size: 13px; font-weight: 600; }
.reply-what span { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reply-cancel { width: 30px; height: 30px; flex: none; border: 0; border-radius: 50%; padding: 0; display: grid; place-items: center; background: var(--solid); color: var(--fg); -webkit-tap-highlight-color: transparent; }
.reply-cancel svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }

/* Press-and-hold menu: the screen blurs, the message lifts, reactions above, actions below */
.msg-menu {
  position: fixed; inset: 0; z-index: 3000; background: rgba(0, 0, 0, 0.5); /* just darker (no blur) */
  opacity: 0; transition: opacity 0.2s ease; touch-action: none;
}
.msg-menu.show { opacity: 1; }
.msg-menu[hidden] { display: none; }
.mm-stack { position: absolute; left: 12px; right: 12px; display: flex; flex-direction: column; gap: 10px; }
/* The held message stays exactly where it is; the reactions and actions grow in around it */
.mm-react, .mm-actions { transform: scale(0.94); transition: transform 0.35s cubic-bezier(0.3, 1.4, 0.5, 1); }
.msg-menu.show .mm-react, .msg-menu.show .mm-actions { transform: none; }
.mm-stack.mine .mm-react, .mm-stack.mine .mm-actions { transform-origin: right center; }
.mm-stack.theirs .mm-react, .mm-stack.theirs .mm-actions { transform-origin: left center; }
/* Near the bottom: the actions go above; near the top: the reactions go below */
.mm-stack.up .mm-actions { order: -2; }
.mm-stack.up .mm-react { order: -1; }
.mm-stack.react-below .mm-bubble { order: -1; }
.mm-stack.mine { align-items: flex-end; }
.mm-stack.theirs { align-items: flex-start; }
.mm-react {
  display: flex; gap: 2px; padding: 6px 8px; border-radius: 999px; background: var(--solid);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.25);
}
.mm-react button { width: 44px; height: 44px; border: 0; border-radius: 50%; padding: 0; background: none; font-size: 28px; line-height: 44px; -webkit-tap-highlight-color: transparent; transition: transform 0.2s cubic-bezier(0.3, 1.6, 0.5, 1); }
/* The reactions bounce up one after another as the menu opens */
.msg-menu.show .mm-react button { animation: reactIn 0.55s cubic-bezier(0.3, 1.7, 0.45, 1) both; animation-delay: calc(var(--n) * 35ms); }
@keyframes reactIn { from { transform: translateY(14px) scale(0.2); opacity: 0; } 60% { opacity: 1; } to { transform: none; opacity: 1; } }
.mm-react button:active { transform: scale(1.3); }
.mm-react button.on { background: var(--field); }
.mm-bubble .bubble { max-width: 78vw; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); }
.mm-stack.theirs .mm-bubble .bubble { background: var(--solid); color: var(--fg); }
.mm-stack.mine .mm-bubble .bubble { background: linear-gradient(135deg, #2f6bff, #1a7cff); color: #fff; }
.mm-bubble .bubble.big { box-shadow: none; }
.mm-actions {
  min-width: 230px; border-radius: 16px; overflow: hidden; background: var(--solid);
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.28);
}
.mm-actions button {
  display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 13px 16px; border: 0; background: none;
  color: var(--fg); font: 400 16px -apple-system, system-ui, sans-serif; text-align: left; -webkit-tap-highlight-color: transparent;
}
.mm-actions button + button { border-top: 0.5px solid var(--line); }
.mm-actions button:active { background: var(--field); }
.mm-actions button[hidden] { display: none; }
.mm-actions button.danger { color: var(--danger); }
.mm-actions svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Swipe a message to reply: it follows your finger, and a reply arrow fades in behind it */
.msg { position: relative; }
.msg.swiping .msg-col { transition: none; }
.msg .msg-col { transition: transform 0.35s cubic-bezier(0.3, 1.3, 0.5, 1); z-index: 1; } /* the arrow is uncovered as it slides */
.swipe-reply {
  --p: 0; --sr-gray: color-mix(in srgb, var(--solid), var(--fg) 22%);
  position: absolute; top: 50%; width: 32px; height: 32px; margin-top: -16px; display: grid; place-items: center;
  color: var(--sr-gray); opacity: 0; pointer-events: none;
}
.swipe-reply > svg { grid-area: 1 / 1; }
.sr-ring { width: 32px; height: 32px; transform: rotate(-90deg); overflow: visible; }
.sr-ring circle {
  fill: transparent; stroke: var(--sr-gray); stroke-width: 2; stroke-linecap: round;
  stroke-dasharray: 88; stroke-dashoffset: calc(88 * (1 - var(--p)));
  transition: fill 0.2s, stroke 0.2s;
}
.sr-arrow { position: relative; width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: color 0.2s; }
.swipe-reply.ready { color: var(--fg); }
.swipe-reply.ready .sr-ring circle { fill: var(--solid); stroke: var(--solid); }

/* A green dot on their picture while they're in the app (like Instagram) */
.pfp-on { position: relative; display: block; flex: none; font-style: normal; line-height: 0; }
.pfp-on::after {
  content: ""; position: absolute; right: 0; bottom: 0; width: 26%; height: 26%; min-width: 10px; min-height: 10px; border-radius: 50%;
  background: #2fd158; box-shadow: 0 0 0 var(--ring, 2.5px) var(--bg); transform: scale(0); transition: transform 0.3s cubic-bezier(0.3, 1.4, 0.5, 1);
}
.person .pfp-on::after { --ring: 3px; width: 14px; height: 14px; right: 5px; bottom: 5px; }
.inbox-row .pfp-on::after { width: 12px; height: 12px; right: 1px; bottom: 1px; }
.pv-on::after { --ring: 3px; width: 16px; height: 16px; right: 3px; bottom: 3px; }
.pfp-on.online::after { transform: scale(1); }

/* Unsent: a small grey note where the message was; the message shrinks away first */
.msg-note { align-self: center; margin: 10px 0 6px; font-size: 12.5px; color: var(--muted); }
.msg-note.appear { animation: noteIn 0.35s ease 0.05s both; }
@keyframes noteIn { from { opacity: 0; transform: scale(0.92); } }
.msg.leaving .msg-col { transition: transform 0.24s cubic-bezier(0.4, 0, 0.7, 0.4), opacity 0.2s ease-in; transform: scale(0.4); opacity: 0; }
.msg.theirs.leaving .msg-col { transform-origin: left center; }
.msg.mine.leaving .msg-col { transform-origin: right center; }
.msg.leaving .msg-pfp { transition: opacity 0.2s; opacity: 0; }


/* ---------- Voice messages ---------- */
/* The bubble, like Instagram's: a plain play/pause, an even waveform of rounded bars that
   fills in as it plays, and how long it is */
.bubble.voice { display: flex; align-items: center; gap: 12px; padding: 10px 18px 10px 14px; min-height: 46px; min-width: 210px; }
.msg .bubble.voice { border-radius: 999px !important; } /* a capsule (even when grouped with others) */
.vplay {
  flex: none; width: 26px; height: 26px; margin: -4px 0; border: 0; border-radius: 50%; padding: 0; display: grid; place-items: center;
  background: none; color: inherit; -webkit-tap-highlight-color: transparent; transition: transform 0.2s cubic-bezier(0.3, 1.4, 0.5, 1);
}
.vplay:active { transform: scale(0.8); }
.vplay svg { width: 20px; height: 20px; fill: currentColor; }
.vwave { flex: 1; display: flex; align-items: center; justify-content: space-between; gap: 2px; height: 26px; min-width: 120px; }
.vwave i { flex: 0 0 3px; min-height: 4px; border-radius: 3px; background: currentColor; opacity: 0.4; transition: opacity 0.12s; }
.vwave i.on { opacity: 1; }
.vtime { flex: none; font-size: 14px; font-weight: 500; font-variant-numeric: tabular-nums; min-width: 32px; text-align: right; }

/* Recording: the typing box becomes a timer with "Slide to cancel"; the mic grows under your finger */
.rec-bar { display: none; flex: 1; align-items: center; gap: 10px; min-height: 38px; padding: 0 8px 0 12px; overflow: hidden; }
.composer.recording .rec-bar { display: flex; }
.composer.recording textarea, .composer.recording .cmp-camera, .composer.recording .cmp-tools > :not(#cmp-mic) { display: none; }
.rec-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: #ff3b30; animation: recBlink 1.1s ease-in-out infinite; }
@keyframes recBlink { 50% { opacity: 0.25; } }
.rec-time { flex: none; font-size: 16px; font-variant-numeric: tabular-nums; }
.rec-hint {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 2px; font-size: 15px; color: var(--muted);
  transform: translateX(calc(var(--slide, 0px) * 0.6)); transition: color 0.2s;
}
.rec-hint svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.rec-bar.cancelling .rec-hint { color: #ff3b30; }
#cmp-mic { touch-action: none; position: relative; z-index: 1; }
.composer.recording #cmp-mic { background: linear-gradient(135deg, #2f6bff, #1a7cff); color: #fff; border-radius: 50%; width: 38px; height: 38px; scale: 1.35; transition: scale 0.2s cubic-bezier(0.2, 0.8, 0.2, 1); }

/* ---------- Photos ---------- */
/* In the chat: the photo itself, rounded (no bubble around it) */
.msg .bubble.photo { padding: 0; background: none !important; border-radius: 20px; overflow: hidden; line-height: 0; }
.bubble.photo img { display: block; object-fit: cover; border-radius: inherit; background: var(--solid); -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.msg.pending .bubble.photo { opacity: 0.7; }
/* Full screen: grows out of the chat; tap or swipe down to close */
.photo-view {
  position: fixed; inset: 0; z-index: 3500; display: grid; place-items: center; touch-action: none;
  background: rgba(0, 0, 0, var(--fade, 1)); opacity: 0; transition: opacity 0.22s ease, background-color 0.3s ease;
}
.photo-view[hidden] { display: none; }
.photo-view.show { opacity: 1; }
.photo-view img {
  max-width: 100vw; max-height: calc(100% - var(--safe-top) - var(--safe-bottom)); object-fit: contain;
  transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); -webkit-user-select: none; user-select: none;
}
/* Its top bar: close, who sent it and when, and save/share */
.pv-bar {
  position: absolute; left: 0; right: 0; top: 0; display: flex; align-items: center; gap: 10px;
  padding: calc(var(--safe-top) + 8px) 12px 10px; color: #fff;
  opacity: var(--fade, 1);
}
/* Liquid glass buttons (the same glass as the back buttons, always the dark-mode look: the
   viewer is black whatever the theme) */
.pv-btn { flex: none; transition: transform 0.25s cubic-bezier(0.3, 1.4, 0.5, 1); }
:root .photo-view .pv-btn.glass-circle:not(.lens) {
  /* Clearer: almost no tint or blur, just the bright rim and a faint shine */
  color: #fff;
  background: radial-gradient(80% 80% at 28% 18%, rgba(255, 255, 255, 0.1), transparent 55%);
  -webkit-backdrop-filter: blur(1px) saturate(150%); backdrop-filter: blur(1px) saturate(150%);
  box-shadow:
    inset 1.5px 1.5px 1px -0.5px rgba(255, 255, 255, 0.7), inset -1.5px -1.5px 1px -0.5px rgba(255, 255, 255, 0.35),
    inset 0 0 8px rgba(255, 255, 255, 0.06), 0 4px 12px rgba(0, 0, 0, 0.18);
}
:root .photo-view .pv-btn.glass-circle:not(.lens)::before {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.08) 30%, rgba(255, 255, 255, 0.05) 70%, rgba(255, 255, 255, 0.5));
}
.pv-btn svg { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pv-who { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; line-height: 1.2; }
.pv-who b { font-size: 15px; font-weight: 600; }
.pv-who span { font-size: 12.5px; opacity: 0.75; }
/* Hold the photo for the iPhone's own menu (Save to Photos, Copy, Share) */
.photo-view img { -webkit-touch-callout: default; }
/* Held in the press-and-hold menu: exactly the same photo, nothing added around it */
.mm-bubble .bubble.photo { padding: 0; background: none !important; overflow: hidden; line-height: 0; }
/* With the real lens: the rim stays the light-on-dark one (the viewer is always black) */
:root .photo-view .pv-btn.lens::before { background: linear-gradient(135deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.08) 30%, rgba(255, 255, 255, 0.05) 70%, rgba(255, 255, 255, 0.5)); }
:root .photo-view .pv-btn.lens { color: #fff; }
/* Closing: only the black fades (the photo itself flies home, fully visible) */
.photo-view.closing { opacity: 1; background: transparent; }
.photo-view.closing .pv-bar { opacity: 0; transition: opacity 0.15s; }
.photo-view img { transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), border-radius 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); }

/* Replying to a photo or a voice message: a mini version of it, a little darker */
.msg-quote.q-photo { padding: 0; background: none !important; filter: none; border-radius: 14px; overflow: hidden; line-height: 0; }
.msg-quote.q-photo img { display: block; object-fit: cover; background: var(--solid); filter: brightness(0.72); }
.msg-quote.q-voice { display: flex; align-items: center; gap: 8px; padding: 7px 14px 7px 10px; border-radius: 999px; }
.qv-play { display: grid; place-items: center; width: 16px; height: 16px; }
.qv-play svg { width: 14px; height: 14px; fill: currentColor; }
.qv-wave { display: flex; align-items: center; gap: 2px; height: 16px; width: 64px; }
.qv-wave i { flex: 1; min-height: 3px; max-width: 2px; border-radius: 2px; background: currentColor; opacity: 0.7; }
.qv-time { font-size: 12px; font-variant-numeric: tabular-nums; opacity: 0.85; }

/* ---------- Stickers & GIFs tray ---------- */
.gif-tray { position: fixed; inset: 0; z-index: 3200; background: rgba(0, 0, 0, 0); transition: background-color 0.3s ease; }
.gif-tray[hidden] { display: none; }
.gif-tray.show { background: rgba(0, 0, 0, 0.35); }
.gt-sheet {
  position: absolute; left: 0; right: 0; bottom: 0; height: min(64vh, 560px); max-width: 672px; margin: 0 auto;
  display: flex; flex-direction: column; padding: 8px 12px 0; border-radius: 22px 22px 0 0; background: var(--bg);
  box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.25);
  transform: translateY(100%); transition: transform 0.36s cubic-bezier(0.2, 0.85, 0.25, 1);
}
.gif-tray.show .gt-sheet { transform: none; }
.gt-grab { align-self: center; width: 38px; height: 5px; border-radius: 3px; background: var(--muted); opacity: 0.6; margin: 0 0 10px; touch-action: none; }
.gt-tabs { display: flex; gap: 6px; margin-bottom: 10px; touch-action: none; }
.gt-tabs button {
  flex: 1; height: 34px; border: 0; border-radius: 999px; background: none; color: var(--muted);
  font: 600 15px -apple-system, system-ui, sans-serif; -webkit-tap-highlight-color: transparent; transition: background-color 0.2s, color 0.2s;
}
.gt-tabs button.on { background: var(--solid); color: var(--fg); }
.gt-search { display: flex; align-items: center; gap: 8px; height: 38px; margin-bottom: 10px; padding: 0 14px; border-radius: 999px; background: var(--solid); }
.gt-search[hidden] { display: none; }
.gt-search svg { width: 17px; height: 17px; flex: none; fill: none; stroke: var(--muted); stroke-width: 2; stroke-linecap: round; }
.gt-search input { flex: 1; min-width: 0; border: 0; background: none; outline: none; color: var(--fg); font: 16px -apple-system, system-ui, sans-serif; }
.gt-search input::-webkit-search-cancel-button { display: none; }
.gt-scroll { flex: 1; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; margin: 0 -2px; padding-bottom: 8px; }
/* Two columns, each GIF at its own shape (like Instagram's grid) */
.gt-grid { columns: 2; column-gap: 6px; }
.gt-item { display: block; width: 100%; margin: 0 0 6px; padding: 0; border: 0; border-radius: 12px; overflow: hidden; background: var(--solid); break-inside: avoid; -webkit-tap-highlight-color: transparent; transition: transform 0.2s cubic-bezier(0.3, 1.4, 0.5, 1); }
.gt-item:active { transform: scale(0.95); }
.gt-item img { display: block; width: 100%; height: 100%; object-fit: cover; }
.gt-empty { margin: 40px 0; text-align: center; color: var(--muted); font-size: 15px; }
.gt-empty[hidden] { display: none; }
.gt-credit { align-self: center; padding: 6px 0 calc(var(--safe-bottom) + 6px); font-size: 11px; font-weight: 600; letter-spacing: 0.3px; color: var(--muted); }
