/* Insight Outpatient - Treatment Plan Tracker
   Dark "liquid glass" theme. Deep ocean blues from The Insight Program's
   palette (#259ED7 sky / #2A3779 navy), animated flowing background,
   frosted glass surfaces. Mobile-first, built for Add-to-Home-Screen. */

:root {
  --bg0: #0b1430;
  --bg1: #13275c;
  --cyan: #4ec9ff;
  --blue: #2f8fe8;
  --ink: #eef5fd;
  --muted: #94aacb;
  --glass: rgba(255, 255, 255, 0.07);
  --glass-2: rgba(255, 255, 255, 0.11);
  --line: rgba(255, 255, 255, 0.13);
  --amber: #ffce7a;
  --violet: #c9bcff;
  --red: #ff8080;
  --red-deep: #e25555;
  --green: #3ddc84;
  --radius: 20px;
  --radius-sm: 14px;
  --grad: linear-gradient(135deg, #58d2ff, #2f8fe8 55%, #3d63e0);
  --glow: 0 6px 22px rgba(63, 170, 255, 0.35);
  --tabbar-h: 66px;
  /* How much room the tab bar ACTUALLY takes at the bottom of the screen,
     home-indicator inset and all. --tabbar-h above is only a guess at the bar's
     own height, and the real bar - icons, labels, inset - comes out taller on
     most phones, so anything reserving space from the guess reserved too
     little. measureTabbar() in app.js writes the measured number here once the
     bar is on screen; this value is the fallback until it does. */
  --tabbar-real: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
  /* The height of the screen, measured. Every CSS way of asking is wrong
     somewhere: 100vh ignores the browser's own bars, 100dvh moves when the
     keyboard opens, and 100svh comes back 59px short in a home-screen install
     because iOS takes the notch off it. window.innerHeight is right in all
     three cases and does not move for the keyboard, so measureTabbar() writes
     it here. The svh below is only what is used until it does. */
  --vph: 100svh;
  /* How much of the screen the on-screen keyboard is covering. Kept at 0 by
     default and set from JS while a keyboard is up (see trackKeyboard). */
  --kb: 0px;
  /* The notch, measured at startup (see measureSafeTop). env() is only the
     starting guess: iOS reports it as ZERO while a keyboard is up, which put
     the chat header underneath the clock. */
  --safe-top: env(safe-area-inset-top, 0px);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Tell the browser we're a dark app so native widgets (select dropdowns,
   date pickers, scrollbars) render dark instead of white-on-white. */
:root { color-scheme: dark; }

html {
  -webkit-text-size-adjust: 100%;
  /* The page's own background is attached to the viewport, which leaves the
     strip behind the home indicator unpainted - a black band under the tab
     bar. Giving the root a solid colour of its own puts a floor under
     everything, so there is nowhere left for the phone to show through. */
  background: #0a1330;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  background: linear-gradient(165deg, #0c1636 0%, #14295f 45%, #0d1d4b 75%, #0a1330 100%) fixed;
  color: var(--ink);
  min-height: 100vh;
  min-height: 100dvh;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}

/* ---- liquid background: two glowing blobs drifting slowly ---- */
body::before, body::after {
  content: "";
  position: fixed;
  z-index: -1;
  width: 65vmax; height: 65vmax;
  border-radius: 50%;
  pointer-events: none;
  will-change: transform;
}
body::before {
  top: -28vmax; right: -20vmax;
  background: radial-gradient(circle at 50% 50%, rgba(78, 201, 255, 0.34), rgba(78, 201, 255, 0.06) 55%, transparent 70%);
  animation: drift1 26s ease-in-out infinite alternate;
}
body::after {
  bottom: -30vmax; left: -22vmax;
  background: radial-gradient(circle at 50% 50%, rgba(97, 108, 255, 0.30), rgba(97, 108, 255, 0.05) 55%, transparent 70%);
  animation: drift2 32s ease-in-out infinite alternate;
}
@keyframes drift1 {
  0%   { transform: translate(0, 0) scale(1); }
  50%  { transform: translate(-9vmax, 7vmax) scale(1.15); }
  100% { transform: translate(4vmax, 13vmax) scale(0.95); }
}
@keyframes drift2 {
  0%   { transform: translate(0, 0) scale(1); }
  50%  { transform: translate(10vmax, -6vmax) scale(1.12); }
  100% { transform: translate(2vmax, -12vmax) scale(1.02); }
}
@media (prefers-reduced-motion: reduce) {
  body::before, body::after { animation: none; }
}

.hidden { display: none !important; }

#app {
  max-width: 640px;
  margin: 0 auto;
  padding: calc(env(safe-area-inset-top, 0px) + 14px) 14px
           calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 26px);
}

.boot { text-align: center; padding: 40vh 0; color: var(--muted); }

/* Subtle entrance, applied ONLY when the user actually navigates somewhere.
   As a blanket rule it replayed on every DOM write - including the 45-second
   background refresh - and that replay was the flash. `.entering` is added by
   go() and removed a moment later, so a refresh redraws in silence. */
/* One quick fade for the whole page rather than every card sliding up on its
   own. Animating each card meant a dozen elements moving at once on every
   navigation, which is what read as jumpy - and any of them still moving when
   a finger landed made the page feel like it was fighting back. */
@keyframes rise { from { opacity: 0; } to { opacity: 1; } }
#app.entering { animation: rise .16s ease-out both; }

/* Anyone who has asked their phone to keep still gets no animation at all. */
@media (prefers-reduced-motion: reduce) {
  #app.entering { animation: none; }
}

/* ---------- header ---------- */
.pagehead { display: flex; align-items: center; justify-content: space-between; margin: 6px 0 16px; gap: 10px; }
.pagehead h1 { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; color: #fff; }
.pagehead .sub { color: var(--muted); font-size: 13px; margin-top: 3px; }

/* ---------- buttons & inputs (big touch targets) ---------- */
button, .btn {
  font: inherit; border: none; cursor: pointer;
  border-radius: var(--radius);
  min-height: 48px;
  padding: 12px 18px;
  font-weight: 700; font-size: 16px;
  background: var(--grad); color: #fff;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  box-shadow: var(--glow);
  transition: transform .14s cubic-bezier(.34,1.56,.64,1), opacity .15s, box-shadow .2s;
  touch-action: manipulation;
}
button:active { transform: scale(.955); box-shadow: 0 3px 10px rgba(63, 170, 255, 0.28); }
button:disabled { opacity: .45; }
.btn-block { width: 100%; }
.btn-ghost {
  background: var(--glass-2); color: var(--cyan);
  border: 1px solid rgba(78, 201, 255, 0.4); box-shadow: none;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.btn-quiet { background: var(--glass-2); color: var(--ink); font-weight: 600; box-shadow: none; border: 1px solid var(--line); }
.btn-danger { background: rgba(255, 128, 128, 0.12); color: var(--red); border: 1px solid rgba(255, 128, 128, 0.35); box-shadow: none; }
.btn-sm { min-height: 38px; padding: 8px 14px; font-size: 14px; border-radius: 13px; }

input[type=text], input[type=password], input[type=search], input[type=date], input[type=time], textarea, select {
  font: inherit; width: 100%;
  min-height: 48px;
  padding: 12px 15px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: rgba(9, 18, 44, 0.55); color: var(--ink);
  font-size: 16px; /* prevents iOS zoom-on-focus */
  transition: border-color .15s, box-shadow .15s, background .15s;
}
input::placeholder, textarea::placeholder { color: rgba(148, 170, 203, 0.75); }
select { background: #16224d; }
select option { background: #16224d; color: var(--ink); }
input[type=date], input[type=time] { color-scheme: dark; }
input[type=date]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator { filter: invert(0.8); }

/* A time is four characters, so it gets a box four characters wide instead of
   the full width of the card. Stretched across the whole card, Safari centres
   the value in the middle of all that emptiness and the thing reads as a
   broken text field rather than something to tap. */
input[type=time], input[type=date] {
  width: auto; max-width: 100%;
  text-align: left; font-variant-numeric: tabular-nums;
}
input[type=time] { min-width: 128px; }
input[type=date] { min-width: 172px; }
/* Safari centres the value inside these fields on its own; put it back to the
   left so it lines up with everything else on the page. */
input[type=time]::-webkit-date-and-time-value,
input[type=date]::-webkit-date-and-time-value { text-align: left; margin: 0; }
input[type=time]::-webkit-datetime-edit,
input[type=date]::-webkit-datetime-edit { padding: 0; }
textarea { resize: vertical; min-height: 70px; }
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--cyan);
  background: rgba(9, 18, 44, 0.75);
  box-shadow: 0 0 0 3.5px rgba(78, 201, 255, 0.22);
}

label.fieldlabel { display: block; font-size: 12.5px; font-weight: 700; color: var(--muted); margin: 14px 0 6px; text-transform: uppercase; letter-spacing: .06em; }

/* ---------- auth ---------- */
.auth-wrap { max-width: 420px; margin: 0 auto; padding-top: 5vh; }
.auth-logo { text-align: center; margin-bottom: 24px; }
.auth-logo .mark {
  width: 84px; height: 84px; border-radius: 26px; margin: 0 auto 14px;
  background: var(--grad);
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 42px; font-weight: 900;
  box-shadow: 0 12px 36px rgba(63, 170, 255, .45);
}
.auth-logo h1 { font-size: 26px; letter-spacing: -.02em; color: #fff; }
.auth-logo p { color: var(--muted); font-size: 14px; margin-top: 4px; }

.card {
  background: var(--glass);
  -webkit-backdrop-filter: blur(22px); backdrop-filter: blur(22px);
  border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px;
  box-shadow: 0 8px 32px rgba(4, 10, 30, 0.35);
  margin-bottom: 14px;
}

.seg { display: flex; background: rgba(9, 18, 44, 0.5); border-radius: var(--radius-sm); padding: 4px; gap: 4px; border: 1px solid var(--line); }
.seg button {
  flex: 1; min-height: 46px; background: transparent; color: var(--muted);
  font-size: 13.5px; font-weight: 700; padding: 8px 4px; border-radius: 11px;
  box-shadow: none;
}
.seg button.on { background: var(--grad); color: #fff; box-shadow: 0 3px 12px rgba(63,170,255,.35); }

.hint { font-size: 13px; color: var(--muted); line-height: 1.5; margin-top: 10px; }
.hint b { color: var(--ink); }
.error-box { background: rgba(226, 85, 85, 0.16); border: 1px solid rgba(255,128,128,.3); color: var(--red); border-radius: var(--radius-sm); padding: 10px 12px; font-size: 14px; margin-top: 12px; }
.ok-box { background: rgba(78, 201, 255, 0.12); border: 1px solid rgba(78, 201, 255, 0.3); color: var(--cyan); border-radius: var(--radius-sm); padding: 10px 12px; font-size: 14px; margin-top: 12px; line-height: 1.5; }
.linkline { text-align: center; margin-top: 16px; font-size: 15px; color: var(--muted); }
.linkline a { color: var(--cyan); font-weight: 700; text-decoration: none; }

/* ---------- badges ---------- */
.badge { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 800; padding: 3.5px 9px; border-radius: 99px; letter-spacing: .03em; vertical-align: middle; }
.badge.OG { background: rgba(150, 130, 255, 0.16); color: var(--violet); border: 1px solid rgba(150, 130, 255, 0.3); }
.badge.YG { background: rgba(255, 190, 100, 0.14); color: var(--amber); border: 1px solid rgba(255, 190, 100, 0.3); }
.badge.COUNSELOR { background: rgba(78, 201, 255, 0.14); color: var(--cyan); border: 1px solid rgba(78, 201, 255, 0.32); }
.badge.YOU { background: var(--glass-2); color: var(--muted); border: 1px solid var(--line); }
/* Director wears the same gold as Admin - it's the other role that carries
   authority, and it should read that way at a glance. */
.badge.ADMIN, .badge.DIRECTOR {
  background: rgba(255, 200, 64, 0.14); color: #ffc840;
  border: 1px solid rgba(255, 200, 64, 0.45);
  box-shadow: 0 0 8px rgba(255, 200, 64, 0.25);
}

/* Outpatient's own tag. Sits BESIDE the OG/YG tag, never instead of it. */
.badge.OP { background: rgba(61, 220, 132, 0.14); color: var(--green); border: 1px solid rgba(61, 220, 132, 0.32); }

/* Special-role marks that attach to a name (steering wheel, coffee cup).
   Drawn as inline SVG so they stay sharp at any size and take their colour
   from here rather than depending on an emoji font being installed. */
.sp-icon { display: inline-block; vertical-align: -3px; line-height: 0; }
.sp-icon svg { width: 100%; height: 100%; display: block; }
.sp-steering { color: var(--cyan); filter: drop-shadow(0 0 3px rgba(78, 201, 255, 0.45)); }
.sp-outpatient { color: var(--green); filter: drop-shadow(0 0 3px rgba(61, 220, 132, 0.45)); }
/* Gold, and warmer than the rest on purpose - it is the one that marks
   something finished. */
.sp-graduate { color: #f5c451; filter: drop-shadow(0 0 4px rgba(245, 196, 81, 0.55)); }

/* Counselor identifier: monkey's fist knot (The Insight Program's logo mark) */
.cicon { display: inline-block; vertical-align: -3px; object-fit: contain; }

/* Sobriety milestone knots: bronze 30 days / silver 6 months / gold 1 year */
.knot-bronze { filter: drop-shadow(0 0 3px rgba(193, 122, 65, 0.55)); }
.knot-silver { filter: drop-shadow(0 0 3px rgba(203, 213, 225, 0.55)); }
.knot-gold   { filter: drop-shadow(0 0 4px rgba(255, 200, 64, 0.65)); }

/* Sobriety tab */
.sober-hero { padding: 22px 16px; }
.sober-hero img { display: block; margin: 0 auto 8px; }
.sober-hero-label { font-size: 16px; font-weight: 800; color: #fff; letter-spacing: .01em; }
/* Sobriety totals: one row per unit, each showing the whole elapsed time
   expressed in that unit. Stacked rather than tiled because the seconds
   count runs to seven digits and won't fit in a narrow tile. */
.sober-list { padding: 2px 18px; }
.sober-row {
  display: flex; align-items: baseline; justify-content: center; gap: 9px;
  padding: 13px 4px; border-bottom: 1px solid var(--line);
}
.sober-row:last-child { border-bottom: none; }
.sober-row b {
  font-size: 26px; font-weight: 800; font-variant-numeric: tabular-nums;
  background: var(--grad); -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.sober-row span { font-size: 15px; color: var(--muted); font-weight: 600; }
/* fixed-width digits so ticking numbers don't shift their row */
.stat b { font-variant-numeric: tabular-nums; }

/* ---------- plan cards ---------- */
.plan-card { padding: 0; overflow: hidden; }
.plan-head { padding: 14px 16px 10px; display: flex; align-items: center; gap: 11px; }
.avatar {
  width: 44px; height: 44px; border-radius: 50%; flex: none;
  background: var(--grad);
  color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px;
  box-shadow: 0 4px 14px rgba(63, 170, 255, .35);
}
.plan-who { flex: 1; min-width: 0; }
.plan-who .who-name { font-weight: 800; font-size: 15px; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; color: #fff; }
.plan-who .who-sub { font-size: 12.5px; color: var(--muted); margin-top: 1px; }

.progress { height: 9px; background: rgba(255, 255, 255, 0.09); border-radius: 99px; overflow: hidden; margin: 0 16px 4px; }
.progress > div { height: 100%; background: var(--grad); border-radius: 99px; transition: width .5s cubic-bezier(.22,1,.36,1); box-shadow: 0 0 12px rgba(78, 201, 255, 0.55); }
.progress-label { font-size: 12px; color: var(--muted); padding: 4px 16px 8px; }

.items { list-style: none; }
.item {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 16px; border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.item .tick {
  flex: none; width: 30px; height: 30px; margin-top: 1px;
  border: 2px solid rgba(78, 201, 255, 0.45); border-radius: 10px;
  background: rgba(9, 18, 44, 0.4);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; color: transparent; padding: 0; min-height: 0; box-shadow: none;
  transition: background .18s, border-color .18s, transform .14s cubic-bezier(.34,1.56,.64,1), box-shadow .2s;
}
.item.done .tick { background: var(--grad); border-color: transparent; color: #fff; box-shadow: 0 0 14px rgba(78, 201, 255, 0.5); }
.item .tick:active { transform: scale(.85); }
.item.readonly .tick { pointer-events: none; }
.item-main { flex: 1; min-width: 0; }
.item-text { font-size: 15.5px; line-height: 1.45; word-wrap: break-word; }
.item.done .item-text { color: var(--muted); text-decoration: line-through; text-decoration-color: rgba(148,170,203,.5); }
.item-note { font-size: 13.5px; color: #bcd2ec; margin-top: 5px; padding: 8px 11px; background: rgba(78, 201, 255, 0.09); border-left: 2.5px solid rgba(78, 201, 255, 0.45); border-radius: 8px; white-space: pre-wrap; }
.item-comment {
  font-size: 13px; color: #bcd2ec; margin-top: 5px; padding: 6px 10px;
  background: rgba(255, 255, 255, 0.05); border-left: 2.5px solid rgba(148, 170, 203, 0.4);
  border-radius: 8px; word-wrap: break-word;
}
.item-comment b { color: var(--cyan); font-weight: 700; }
.item-cbtn {
  flex: none; min-height: 0; width: 34px; height: 34px; padding: 0; margin-top: 0;
  background: var(--glass-2); border: 1px solid var(--line); border-radius: 10px;
  font-size: 14px; box-shadow: none; opacity: .8;
}
.item-actions { display: flex; gap: 16px; margin-top: 6px; }
.item-actions button { background: none; color: var(--cyan); font-size: 13px; font-weight: 700; padding: 4px 0; min-height: 0; box-shadow: none; }

.note-edit textarea { margin-top: 6px; }
.note-edit .row { display: flex; gap: 8px; margin-top: 8px; }

/* ---------- comments ---------- */
.comments { border-top: 1px solid rgba(255,255,255,.07); background: rgba(6, 12, 32, 0.35); padding: 12px 16px; }
.comments h4 { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 9px; }
.comment { display: flex; gap: 9px; margin-bottom: 10px; }
.comment .cavatar {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  background: rgba(78, 201, 255, 0.14); border: 1px solid rgba(78, 201, 255, 0.35);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800; color: var(--cyan);
}
.comment-body { background: var(--glass-2); border: 1px solid var(--line); border-radius: 5px 16px 16px 16px; padding: 8px 12px; font-size: 14px; flex: 1; }
.comment-body .cname { font-weight: 800; font-size: 12.5px; color: var(--cyan); margin-bottom: 2px; display: flex; align-items: center; gap: 4px; }
.comment-body .ctime { font-size: 11px; color: var(--muted); margin-top: 3px; }
.comment-form { display: flex; gap: 8px; margin-top: 4px; }
.comment-form input { min-height: 44px; }
.comment-form button { min-height: 44px; padding: 0 16px; flex: none; }

.card-foot { padding: 12px 16px; border-top: 1px solid rgba(255,255,255,.07); display: flex; gap: 10px; }

/* ---------- scan / new plan ---------- */
.scan-zone {
  border: 1.5px dashed rgba(78, 201, 255, 0.4); border-radius: var(--radius);
  background: var(--glass); padding: 36px 18px; text-align: center; color: var(--muted);
  -webkit-backdrop-filter: blur(22px); backdrop-filter: blur(22px);
}
.scan-zone .big { font-size: 46px; margin-bottom: 8px; }
.scan-zone b { color: #fff; font-size: 17px; }
.scan-zone p { font-size: 14px; margin: 8px 0 18px; line-height: 1.5; }
.preview-img { width: 100%; border-radius: var(--radius); border: 1px solid var(--line); display: block; }
.edit-item-row { display: flex; gap: 8px; margin-bottom: 8px; align-items: center; }
.edit-item-row input { flex: 1; }
.edit-item-row .del { flex: none; width: 44px; min-height: 44px; padding: 0; background: rgba(226, 85, 85, 0.14); color: var(--red); font-size: 18px; border-radius: var(--radius-sm); box-shadow: none; border: 1px solid rgba(255,128,128,.25); }
.spin {
  width: 22px; height: 22px; border-radius: 50%;
  border: 3px solid rgba(255,255,255,.25); border-top-color: #fff;
  animation: spin .8s linear infinite;
}
.spin.dark { border-color: rgba(78,201,255,.25); border-top-color: var(--cyan); }
@keyframes spin { to { transform: rotate(360deg); } }
.center { text-align: center; }

.ocr-progress { height: 7px; background: rgba(255,255,255,.1); border-radius: 99px; overflow: hidden; margin-top: 12px; }
.ocr-progress > div { height: 100%; background: var(--grad); border-radius: 99px; transition: width .25s ease; box-shadow: 0 0 10px rgba(78,201,255,.5); }

/* ---------- messages ---------- */
.thread-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: var(--glass); border: 1px solid var(--line); border-radius: var(--radius);
  -webkit-backdrop-filter: blur(22px); backdrop-filter: blur(22px);
  padding: 13px 14px; margin-bottom: 10px; color: var(--ink); font: inherit; text-align: left;
  box-shadow: 0 4px 18px rgba(4, 10, 30, 0.25);
}
.thread-row:active { transform: scale(.985); }
.thread-row .tmeta { flex: 1; min-width: 0; }
.thread-row .tname { font-weight: 800; font-size: 15px; display: flex; gap: 7px; align-items: center; color: #fff; }
.thread-row .tlast { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.unread-dot { min-width: 22px; height: 22px; border-radius: 99px; background: var(--red-deep); color: #fff; font-size: 12px; font-weight: 800; display: flex; align-items: center; justify-content: center; padding: 0 6px; box-shadow: 0 0 10px rgba(226,85,85,.5); }

.chat { display: flex; flex-direction: column; gap: 8px; }
.bubble { max-width: 82%; padding: 10px 14px; border-radius: 19px; font-size: 15px; line-height: 1.45; white-space: pre-wrap; word-wrap: break-word; }
.bubble.mine { align-self: flex-end; background: var(--grad); color: #fff; border-bottom-right-radius: 6px; box-shadow: 0 4px 14px rgba(63,170,255,.3); }
.bubble.theirs { align-self: flex-start; background: var(--glass-2); border: 1px solid var(--line); border-bottom-left-radius: 6px; -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
.bubble .btime { display: block; font-size: 10.5px; opacity: .7; margin-top: 3px; }
.chatbar {
  position: fixed; left: 0; right: 0;
  bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
  background: rgba(11, 20, 48, 0.72);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  padding: 8px 14px; display: flex; gap: 8px;
  max-width: 640px; margin: 0 auto;
}
.chatbar input { flex: 1; }
.chatbar button { flex: none; }
/* Photo button sits left of the text field, sized to match the send button. */
.chatbar .photo-btn { font-size: 19px; padding: 0 12px; line-height: 1; }

/* A photo inside a bubble. Capped so a tall portrait shot can't push the whole
   conversation off screen. */
.chat-photo {
  display: block; max-width: 100%; max-height: 320px; width: auto;
  border-radius: 13px; margin-bottom: 4px; cursor: zoom-in; background: var(--glass);
}
/* Shown in place of a photo KV has already aged out. */
.photo-gone {
  font-size: 13px; opacity: .75; padding: 14px 16px; text-align: center;
  border: 1px dashed var(--line); border-radius: 13px; margin-bottom: 4px;
}

/* Search box above the thread list */
.searchbar { margin-bottom: 12px; }
.searchbar input { width: 100%; }

/* ---------- acceptable use policy (bottom of the auth screen) ---------- */
/* Deliberately quiet and collapsed: present on every sign-up and log-in
   without competing with the two fields people came to fill in. */
.aup { margin-top: 34px; padding-top: 16px; border-top: 1px solid var(--line); }
.aup > summary {
  cursor: pointer; list-style: none;
  font-size: 12px; line-height: 1.5; color: var(--muted); text-align: center;
  padding: 4px 2px;
}
.aup > summary::-webkit-details-marker { display: none; }
.aup > summary::after { content: ' ▾'; opacity: .7; }
.aup[open] > summary::after { content: ' ▴'; }
.aup > summary:hover { color: var(--ink); }
.aup-body {
  margin-top: 12px; max-height: 46vh; overflow-y: auto;
  font-size: 12.5px; line-height: 1.6; color: var(--muted);
  background: var(--glass); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 14px 15px;
}
.aup-body h4 {
  margin: 15px 0 5px; font-size: 12.5px; color: var(--ink);
  text-transform: uppercase; letter-spacing: .05em;
}
.aup-body h4:first-of-type { margin-top: 6px; }
.aup-body p { margin: 0 0 8px; }
.aup-body b { color: var(--ink); }
.aup-body ul { margin: 0 0 8px; padding-left: 18px; }
.aup-body li { margin-bottom: 6px; }

/* ---------- profile pictures ---------- */
/* An <img> avatar has to sit exactly where the initials <div> did. */
.avatar-img { object-fit: cover; padding: 0; }
.avatar-sm { width: 36px; height: 36px; font-size: 13px; }
.avatar-lg { width: 96px; height: 96px; font-size: 30px; margin: 0 auto 10px; }
.avatar-btn { background: none; border: 0; padding: 0; min-height: 0; cursor: pointer; }

/* A name that behaves like a link without looking like a button */
.linkish {
  background: none; border: 0; padding: 0; min-height: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.linkish:active { opacity: .6; }

/* Nickname beside a real name - quieter, never a replacement for it */
.nick { color: var(--muted); font-weight: 600; }

/* ---------- profile page ---------- */
.profile-head { padding: 22px 18px 18px; }
.profile-name { font-size: 21px; font-weight: 800; color: #fff; }
.profile-nick { color: var(--muted); font-size: 15px; margin-top: 2px; }
.profile-tags {
  display: flex; flex-wrap: wrap; gap: 7px; align-items: center;
  justify-content: center; margin-top: 11px;
}
.profile-actions { margin-top: 14px; }
/* Bio sits under the name/tags. Preserves the line breaks people type. */
.profile-bio {
  margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--line);
  font-size: 14.5px; line-height: 1.5; color: var(--ink);
  white-space: pre-wrap; word-wrap: break-word; text-align: left;
}
/* Buttons side by side (Save / Cancel) */
.row { display: flex; gap: 9px; align-items: center; }
.row > button { flex: 1; }
.profile-stats { grid-template-columns: repeat(3, 1fr); }
.prof-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--line); font-size: 14px;
}
.prof-line:last-child { border-bottom: none; }
.prof-line span { color: var(--muted); }
.prof-line b { color: var(--ink); text-align: right; }

/* ---------- role chips on the Manage user list ---------- */
/* Lit = they hold it. Tap toggles, so granting a role is one tap from the
   list rather than a trip through a separate form. */
.mgmt-roles { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.rolechip {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--glass); border: 1px solid var(--line); color: var(--muted);
  font-size: 11.5px; font-weight: 700; padding: 5px 10px; border-radius: 99px;
  min-height: 0; cursor: pointer;
}
.rolechip.on { background: rgba(78, 201, 255, 0.14); border-color: rgba(78, 201, 255, 0.4); color: var(--cyan); }
.rolechip .sp-icon { width: 13px; height: 13px; }

/* Manage tab: who currently holds each special role */
.sp-group { margin-top: 15px; }
.sp-group-head { font-size: 13px; font-weight: 700; color: var(--ink); display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.sp-holder {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 14px; color: var(--ink);
}
.sp-holder:last-child { border-bottom: none; }

/* ---------- archive ---------- */
.arch-meta { flex: 1; min-width: 0; }
.arch-title { font-weight: 800; font-size: 15px; color: #fff; }
.arch-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.pill-done { background: rgba(61, 220, 132, 0.14); color: var(--green); border: 1px solid rgba(61, 220, 132, 0.32); font-size: 11px; font-weight: 800; padding: 3.5px 9px; border-radius: 99px; flex: none; }
.pill-replaced { background: var(--glass-2); color: var(--muted); border: 1px solid var(--line); font-size: 11px; font-weight: 800; padding: 3.5px 9px; border-radius: 99px; flex: none; }

/* ---------- bottom tab bar ---------- */
.tabbar {
  /* Plain bottom: 0. This is right in every case except a keyboard being up,
     which the viewport meta (interactive-widget=resizes-content) handles, and
     which body.kb-open handles below by getting the bar out of the way
     entirely. Positioning it from a measured value was worse than the problem:
     one stale measurement and the bar floats in the middle of the screen. */
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  /* Kept on its own compositing layer. Without this iOS drops a fixed bar out
     of position partway through a momentum scroll and leaves it there. */
  transform: translateZ(0); -webkit-backface-visibility: hidden; backface-visibility: hidden;
  display: flex; justify-content: space-around;
  background: rgba(10, 18, 44, 0.72);
  -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding: 6px 4px calc(env(safe-area-inset-bottom, 0px) + 6px);
  /* Reaches into the home-indicator strip so nothing shows through beneath. */
  margin-bottom: calc(-1 * env(safe-area-inset-bottom, 0px));
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) * 2 + 6px);
}
.tabbar button {
  flex: 1; max-width: 110px; background: none; color: var(--muted);
  display: flex; flex-direction: column; gap: 2px; align-items: center;
  font-size: 10.5px; font-weight: 700; min-height: 52px; padding: 4px 2px; position: relative;
  box-shadow: none; border-radius: var(--radius-sm);
  transition: color .15s;
}
.tabbar button .ticon { font-size: 22px; line-height: 1; }
.tabbar button.on { color: var(--cyan); }
.tabbar button.on::after {
  content: ""; position: absolute; bottom: 0; width: 22px; height: 3.5px;
  border-radius: 99px; background: var(--grad); box-shadow: 0 0 10px rgba(78,201,255,.6);
}
.tabbar .tbadge {
  position: absolute; top: 0; right: calc(50% - 22px);
  min-width: 17px; height: 17px; border-radius: 99px; background: var(--red-deep); color: #fff;
  font-size: 10px; font-weight: 800; display: flex; align-items: center; justify-content: center; padding: 0 4px;
}

/* ---------- toast ---------- */
.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 16px);
  background: rgba(20, 34, 74, 0.9); color: #fff;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid rgba(78, 201, 255, 0.35);
  padding: 11px 18px; border-radius: 99px;
  font-size: 14px; font-weight: 600; z-index: 100; max-width: 90vw; text-align: center;
  box-shadow: 0 8px 28px rgba(4, 10, 30, .55), 0 0 18px rgba(78, 201, 255, .25);
}

/* ---------- admin: manage ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 14px; }
.stat {
  background: var(--glass); border: 1px solid var(--line); border-radius: var(--radius-sm);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  padding: 12px 10px; text-align: center;
}
.stat b { display: block; font-size: 24px; font-weight: 800; background: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.stat span { display: block; font-size: 11px; color: var(--muted); margin-top: 3px; line-height: 1.35; font-weight: 600; }
.cardtitle { font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: 10px; }
.weekline { font-size: 14px; color: var(--ink); padding: 4px 0; }
.healthline { font-size: 14px; color: var(--ink); padding: 4px 0; display: flex; gap: 7px; align-items: baseline; }
.healthline span { color: var(--muted); font-size: 13px; }
.mgmt-row { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-top: 1px solid rgba(255,255,255,.07); }
.mgmt-row:first-of-type { border-top: none; }
.mgmt-meta { flex: 1; min-width: 0; }
.mgmt-name { font-weight: 700; font-size: 14px; color: #fff; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.mgmt-sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.mgmt-actions { display: flex; gap: 6px; align-items: center; flex: none; }
.mgmt-actions select {
  min-height: 38px; width: auto; padding: 6px 8px; font-size: 13px; font-weight: 700;
  background: #16224d; color: var(--ink); border: 1px solid var(--line); border-radius: 11px;
}
.mgmt-actions button { min-height: 38px; width: 40px; padding: 0; font-size: 15px; }
@media (max-width: 420px) {
  .mgmt-row { flex-wrap: wrap; }
  .mgmt-actions { width: 100%; justify-content: flex-end; }
}

.empty { text-align: center; color: var(--muted); padding: 48px 20px; font-size: 15px; line-height: 1.55; }
.empty .big { font-size: 44px; margin-bottom: 10px; }
.empty b { color: var(--ink); }

@media (min-width: 641px) {
  .tabbar { max-width: 640px; margin: 0 auto; border-left: 1px solid var(--line); border-right: 1px solid var(--line); border-radius: 18px 18px 0 0; }
}

/* ---------- navigation drawer ---------- */
/* Built once and only toggled, so opening/closing is a pure CSS transition on
   an element already in the DOM - nothing to rebuild, nothing to get stuck. */
.navsheet { position: fixed; inset: 0; z-index: 60; pointer-events: none; }
.navsheet.open { pointer-events: auto; }
.navsheet-scrim {
  position: absolute; inset: 0; background: rgba(4, 9, 24, 0.55);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  opacity: 0; transition: opacity .22s ease;
}
.navsheet.open .navsheet-scrim { opacity: 1; }
.navsheet-panel {
  /* Anchored the same way as the tab bar - fixed to bottom: 0 - rather than to
     the .navsheet box. On iOS a fixed inset:0 element is the LAYOUT viewport,
     which is taller than what you can actually see while the URL bar is up, so
     positioning against its bottom put this panel below the fold. The tab bar
     never had that problem, so the panel now shares its anchor and simply pads
     itself clear of it. */
  position: fixed; left: 0; right: 0; bottom: 0;
  max-width: 640px; margin: 0 auto;
  background: rgba(13, 24, 56, 0.97);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border-top: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 8px 10px calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 12px);
  transform: translateY(100%);
  visibility: hidden;
  transition: transform .26s cubic-bezier(.32,.72,0,1), visibility 0s linear .26s;
  max-height: 82vh; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
/* dvh tracks the visible viewport as the URL bar shows and hides. */
@supports (height: 100dvh) { .navsheet-panel { max-height: 82dvh; } }
.navsheet.open .navsheet-panel {
  transform: translateY(0); visibility: visible;
  transition: transform .26s cubic-bezier(.32,.72,0,1), visibility 0s;
}
.navsheet-grab {
  width: 38px; height: 4px; border-radius: 99px; background: var(--line);
  margin: 4px auto 10px;
}
.navsheet-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); padding: 0 8px 6px; font-weight: 700;
}
.navlink {
  display: flex; align-items: center; justify-content: flex-start; gap: 13px; width: 100%;
  background: none; border: 0; border-radius: var(--radius-sm);
  padding: 13px 12px; color: var(--ink); font-size: 15.5px; font-weight: 600;
  text-align: left; min-height: 0; cursor: pointer;
}
.navlink:active { background: var(--glass); }
.navlink.on { background: var(--glass-2); color: #fff; }
.navlink-icon { font-size: 19px; width: 24px; text-align: center; }
.navlink-badge { position: static; margin-left: auto; }

/* ---------- feed posts ---------- */
.post-card { padding: 15px 16px; }
.post-card.pinned { border-color: rgba(255, 200, 64, 0.32); }
.pin-flag { font-size: 11px; font-weight: 800; color: #ffc840; margin-bottom: 8px; letter-spacing: .04em; }
.post-head { display: flex; align-items: center; gap: 11px; margin-bottom: 10px; }
.post-body { font-size: 15px; line-height: 1.55; color: var(--ink); white-space: pre-wrap; word-wrap: break-word; }
.post-actions { display: flex; gap: 7px; margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--line); }

/* ---------- daily reflection card ---------- */
.reflection { display: block; text-decoration: none; border-color: rgba(78, 201, 255, 0.3); }
.reflection-tag { font-size: 11px; font-weight: 800; color: var(--cyan); letter-spacing: .05em; }
.reflection-title { font-size: 17px; font-weight: 800; color: #fff; margin-top: 6px; }
.reflection-excerpt { font-size: 14.5px; line-height: 1.55; color: var(--ink); margin-top: 7px; }
.reflection-cta { font-size: 13.5px; font-weight: 700; color: var(--cyan); margin-top: 10px; }
.reflection-copy { font-size: 10.5px; line-height: 1.45; color: var(--muted); margin-top: 11px; padding-top: 9px; border-top: 1px solid var(--line); }

/* ---------- tappable row that looks like a card ---------- */
.linkrow {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; font: inherit; color: var(--ink); cursor: pointer;
}
.linkrow-chev { color: var(--muted); font-size: 22px; }

/* The one-time "are you in Outpatient?" question, and the way back out. */
.op-ask { border-color: rgba(61, 220, 132, 0.3); }
.op-ask b { color: #fff; font-size: 16px; }
.op-grad { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }

/* A paused account is visibly marked in the Manage list. */
.mgmt-row.paused { opacity: .62; }
.rolechip.pausechip.on { background: rgba(255, 128, 128, 0.14); border-color: rgba(255, 128, 128, 0.4); color: var(--red); }

/* Group chats sit above direct messages in the Messages list. */
.room-list { margin-bottom: 6px; }
.room-avatar { background: var(--glass-2); border: 1px solid var(--line); box-shadow: none; font-size: 19px; }
/* Who said what, in a room where it isn't obvious. */
.bubble-who { font-size: 11.5px; font-weight: 800; opacity: .8; margin-bottom: 3px; }

/* A <select> has a wide intrinsic size; without this it refuses to shrink and
   pushes the button in the same row off the edge of the card. */
.edit-item-row { min-width: 0; }
.edit-item-row > select, .edit-item-row > input { min-width: 0; }

/* Search fields: same glass treatment as every other input, plus a magnifier
   so they read as search at a glance. Safari puts its own decorations on
   type=search, which have to be turned off or they sit on top of ours. */
input[type=search] {
  -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394aacb' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 14px 50%;
  background-size: 18px 18px;
  padding-left: 42px;
}
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-cancel-button { -webkit-appearance: none; }

/* New-chat picker: a tappable list of people with a tick when selected. */
.pick-row {
  display: flex; align-items: center; gap: 11px; width: 100%;
  background: none; border: 0; border-radius: var(--radius-sm);
  padding: 10px 12px; color: var(--ink); font-size: 15px; font-weight: 600;
  text-align: left; min-height: 0; cursor: pointer; justify-content: flex-start;
}
.pick-row:active { background: var(--glass); }
.pick-row.on { background: rgba(78, 201, 255, 0.14); color: #fff; }
.pick-tick {
  margin-left: auto; width: 22px; height: 22px; border-radius: 50%; flex: none;
  border: 1.5px solid var(--line); display: flex; align-items: center;
  justify-content: center; font-size: 13px; color: transparent;
}
.pick-row.on .pick-tick { background: var(--grad); border-color: transparent; color: #fff; }
.pick-count { font-size: 12.5px; color: var(--muted); margin: 10px 2px 0; }

/* Five items across has to stay readable on a 390px phone. */
.tabbar button { max-width: none; font-size: 10px; padding: 4px 1px; }
.tabbar button .ticon { font-size: 21px; }

/* Sender line inside a group-chat bubble. */
.bubble-who { display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 800; opacity: .85; margin-bottom: 4px; }
.bubble-who.mine-who { justify-content: flex-end; opacity: .7; }
.avatar-xs { width: 20px; height: 20px; font-size: 9px; box-shadow: none; }


/* Add-to-home-screen guide: shown once, then dismissed for good. */
.install-tip { position: relative; border-color: rgba(78, 201, 255, 0.3); padding-right: 46px; }
.install-tip b { color: #fff; font-size: 15.5px; }
.tip-close {
  position: absolute; top: 10px; right: 10px; width: 32px; height: 32px;
  min-height: 0; padding: 0; border-radius: 50%; font-size: 14px;
  background: var(--glass-2); color: var(--muted); box-shadow: none; border: 1px solid var(--line);
}
.tip-steps { margin-top: 10px; display: grid; gap: 7px; font-size: 13.5px; line-height: 1.5; color: var(--muted); }
.tip-steps b { color: var(--ink); font-size: inherit; }
.tip-key { font-family: -apple-system, sans-serif; }

/* The Profile tab wears the user's own picture. */
.tab-avatar {
  width: 22px; height: 22px; border-radius: 50%; object-fit: cover;
  display: inline-flex; align-items: center; justify-content: center;
}
.tab-initials { background: var(--grad); color: #fff; font-size: 9px; font-weight: 800; }

/* ---------- toolkit ---------- */
.tool-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: none; border: 0; border-bottom: 1px solid var(--line);
  border-radius: 0; padding: 13px 2px; color: var(--ink);
  font-size: 15.5px; font-weight: 600; text-align: left; min-height: 0;
  justify-content: flex-start; cursor: pointer; box-shadow: none;
}
.tool-row:last-child { border-bottom: none; }
.tool-row:active { background: var(--glass); }
.tool-icon {
  width: 34px; height: 34px; flex: none; border-radius: 9px;
  background: var(--glass-2); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; font-size: 17px;
}
.prayer-icon { background: rgba(150, 130, 255, 0.18); border-color: rgba(150, 130, 255, 0.35); }
.tool-name { flex: 1; min-width: 0; }

/* Prayer text: preserve the line breaks it was written with. */
.prayer-text { font-size: 16px; line-height: 1.65; color: var(--ink); white-space: pre-wrap; }
.prayer-heading { font-size: 19px; font-weight: 700; color: #fff; margin-bottom: 12px; }
/* The lead-in some prayers carry in the literature, before the prayer itself. */
.prayer-lead { font-size: 16px; line-height: 1.65; color: var(--ink); margin-bottom: 14px; }
/* Citations sit right-aligned and italic, the way they read on the page. */
.prayer-source {
  margin-top: 16px; font-size: 13px; line-height: 1.45; color: var(--muted);
  font-style: italic; text-align: right;
}

/* Saved entries */
.entry-list { padding: 4px 16px; }
.entry-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  padding: 13px 0; text-align: left; min-height: 0; justify-content: flex-start;
  color: var(--ink); cursor: pointer; box-shadow: none;
}
.entry-row:last-child { border-bottom: none; }
.entry-meta { flex: 1; min-width: 0; }
.entry-date { font-size: 15.5px; font-weight: 700; color: #fff; }
.entry-preview {
  font-size: 13px; color: var(--muted); margin-top: 3px; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* Nightly wizard */
.wiz-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 6px 0 12px; }
.wiz-count { font-size: 13.5px; color: var(--muted); font-weight: 600; }
.wiz-title { font-size: 26px; font-weight: 800; color: #fff; letter-spacing: -.02em; }
.wiz-bar { height: 4px; border-radius: 99px; background: var(--glass-2); margin: 12px 0 18px; overflow: hidden; }
.wiz-bar > div { height: 100%; background: var(--grad); border-radius: 99px; transition: width .25s ease; }
.wiz-date { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; }
.wiz-date span { color: var(--muted); font-size: 14px; }
.wiz-date input { width: auto; min-height: 40px; }
.wiz-q { font-size: 20px; font-weight: 800; color: #fff; line-height: 1.35; margin-bottom: 16px; }
.wiz-yn { display: flex; gap: 12px; margin-bottom: 18px; }
.yn {
  flex: 1; background: var(--glass); border: 1px solid var(--line); color: var(--ink);
  box-shadow: none; font-size: 17px; font-weight: 700; gap: 10px;
}
.yn.on { background: var(--grad); color: #fff; border-color: transparent; box-shadow: var(--glow); }
.yn-dot {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  border: 2px solid currentColor; display: flex; align-items: center;
  justify-content: center; font-size: 12px;
}
.yn.on .yn-dot { background: #fff; color: var(--blue); border-color: #fff; }
.wiz-label { display: block; font-size: 14px; color: var(--muted); margin-bottom: 8px; }
.wiz-foot { display: flex; justify-content: space-between; gap: 12px; margin-top: 20px; }
.wiz-foot button { flex: 1; }

/* Spot check "Affects My" */
.affect-row {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  background: none; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  padding: 13px 2px; color: var(--ink); font-size: 15.5px; font-weight: 600;
  min-height: 0; cursor: pointer; box-shadow: none;
}
.affect-dot { width: 22px; height: 22px; border-radius: 50%; border: 1.5px solid var(--line); flex: none; }
.affect-row.on .affect-dot { background: var(--grad); border-color: transparent; }
.affect-row.on { color: #fff; }

/* Gratitude lines */
.grat-list { padding: 6px 16px; }
.grat-line {
  border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  background: none; padding: 13px 2px; min-height: 0;
}
.grat-line:focus { box-shadow: none; border-bottom-color: var(--cyan); background: none; }

/* Saved gratitude lists read out in full, with their share button. */
.grat-card { padding: 16px; }
.grat-open {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 0 0 12px; min-height: 0; color: var(--ink); box-shadow: none; cursor: pointer;
}
.grat-items { font-size: 15px; line-height: 1.6; color: var(--ink); margin-top: 6px; }
.share-panel { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.share-results { margin-top: 8px; }

/* Spot check kind selector: four across, so the labels need to be tight. */
.sc-seg { margin-bottom: 6px; }
.sc-seg button { font-size: 12.5px; padding: 8px 2px; min-height: 42px; }

.insight-icon { background: rgba(255, 200, 64, 0.16); border-color: rgba(255, 200, 64, 0.3); }
.aa-icon { background: rgba(90, 200, 250, 0.15); border-color: rgba(90, 200, 250, 0.3); }

/* ---------------------------------------------------------------- settings */
/* Two buttons in a page header: on a narrow phone they wrap under each other
   rather than squeezing the title. */
.head-actions { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }

.notice-box {
  background: rgba(255, 200, 64, 0.1); border: 1px solid rgba(255, 200, 64, 0.28);
  border-radius: 12px; padding: 12px 14px; font-size: 14px;
}
.set-state { font-size: 15px; }
.set-state.on b { color: #7ee2a8; }

/* The preference cards stay readable but visibly inactive until notifications
   are actually switched on, so nobody sets a reminder that can't arrive. */
.set-dim { opacity: 0.55; }

.checkrow {
  display: flex; align-items: flex-start; gap: 10px; padding: 9px 0; cursor: pointer;
  font-size: 14px; line-height: 1.45;
}
.checkrow + .checkrow { border-top: 1px solid rgba(255, 255, 255, 0.06); }
.checkrow input[type=checkbox] { width: 20px; height: 20px; flex: none; margin-top: 1px; accent-color: var(--accent); }

/* Prayer page actions run the full width, the way they read on a phone. */
.prayer-actions { display: flex; flex-direction: column; gap: 10px; }
.prayer-actions > button { width: 100%; justify-content: center; }

/* ------------------------------------------------------- insight meeting sheet */
/* Read aloud at meetings, so it is set for reading at arm's length: generous
   line height, and step numbers that stay put in their own column while the
   text wraps beside them. */
.sheet-para { font-size: 16px; line-height: 1.65; color: var(--ink); }
.sheet-para + .sheet-para { margin-top: 14px; }
.sheet-steps + .sheet-para, .sheet-bullets + .sheet-para { margin-top: 16px; }

/* Bullets in a meeting guide: read from the chair, so they want room. */
.sheet-bullets { margin: 12px 0 4px; padding: 0 0 0 20px; list-style: none; }
.sheet-bullets li {
  position: relative; padding: 0 0 10px 0; font-size: 16px; line-height: 1.6; color: var(--ink);
}
.sheet-bullets li::before {
  content: "\2022"; position: absolute; left: -18px; top: 0; color: var(--accent); font-weight: 700;
}

/* A blank to be said aloud - a name, on the night. A rule rather than a row
   of underscores, so it can never run off the side of a narrow screen. */
.blank {
  display: inline-block; min-width: 92px; max-width: 100%;
  border-bottom: 1.5px solid var(--muted); margin: 0 3px; vertical-align: baseline;
}
.sheet-steps { margin: 18px 0 4px; padding: 0; list-style: none; counter-reset: step; }
.sheet-steps li {
  counter-increment: step; position: relative; padding: 0 0 14px 34px;
  font-size: 16px; line-height: 1.6; color: var(--ink);
}
.sheet-steps li::before {
  content: counter(step) "."; position: absolute; left: 0; top: 0;
  width: 28px; text-align: right; font-weight: 700; color: var(--accent);
}
.sheet-closing {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line);
  font-size: 15px; line-height: 1.65; color: var(--ink);
}
.sheet-closing + .sheet-closing { border-top: 0; padding-top: 0; margin-top: 12px; }

/* Where a step is read in different words than the source prints it, the page
   says so rather than leaving the reader to notice. */
.sheet-note {
  margin-top: 16px; padding: 10px 12px; border-radius: 10px;
  background: rgba(255, 200, 64, 0.09); border: 1px solid rgba(255, 200, 64, 0.22);
  font-size: 12.5px; line-height: 1.5; color: var(--ink);
}
/* Copyright and the pointer back to the book, as printed on the sheet. */
.sheet-credit {
  margin-top: 12px; font-size: 11px; line-height: 1.5; color: var(--muted); text-align: center;
}
.sheet-credit + .sheet-credit { margin-top: 6px; }

/* ---------------------------------------------------------------- markdown */
/* Feed posts. Kept close to the surrounding text so a formatted post reads as
   a post and not as a web page that wandered in. */
.post-body.md > *:first-child { margin-top: 0; }
.post-body.md > *:last-child { margin-bottom: 0; }
.post-body.md p { margin: 0 0 10px; line-height: 1.6; }
.post-body.md .md-h { color: #fff; font-weight: 700; margin: 14px 0 8px; line-height: 1.35; }
.post-body.md h3.md-h { font-size: 19px; }
.post-body.md h4.md-h { font-size: 17px; }
.post-body.md h5.md-h { font-size: 15px; }
.post-body.md .md-list { margin: 0 0 10px; padding-left: 22px; }
.post-body.md .md-list li { margin-bottom: 5px; line-height: 1.55; }
.post-body.md .md-quote {
  margin: 0 0 10px; padding: 4px 0 4px 12px; border-left: 3px solid var(--accent);
  color: var(--muted); font-style: italic;
}
.post-body.md .md-hr { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }
.post-body.md code {
  background: rgba(255, 255, 255, 0.09); border-radius: 5px; padding: 1px 5px;
  font-size: 0.92em; font-family: ui-monospace, Menlo, Consolas, monospace;
}
.post-body.md a { color: var(--accent); text-decoration: underline; overflow-wrap: anywhere; }

/* Formatting cheat sheet under the composer. */
.md-help {
  margin-top: 8px; font-size: 11.5px; line-height: 1.6; color: var(--muted);
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------ post pictures */
.post-imgs { margin-top: 12px; display: grid; gap: 6px; }
.post-imgs.one { grid-template-columns: 1fr; }
.post-imgs.many { grid-template-columns: 1fr 1fr; }
.post-imgs img {
  width: 100%; border-radius: 12px; display: block;
  background: rgba(255, 255, 255, 0.04);
}
.post-imgs.one img { max-height: 460px; object-fit: contain; }
.post-imgs.many img { aspect-ratio: 1; object-fit: cover; }

.post-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.post-thumb { position: relative; width: 74px; height: 74px; }
.post-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 10px; display: block; }
.thumb-x {
  position: absolute; top: -6px; right: -6px; width: 22px; height: 22px; min-height: 0;
  border-radius: 50%; padding: 0; font-size: 12px; line-height: 1;
  background: #1b2547; border: 1px solid var(--line); color: var(--ink); box-shadow: none;
}

/* ---------------------------------------------------------- post requests */
.req-avatar { background: rgba(255, 200, 64, 0.16); font-size: 18px; }
.ok-tag { color: #7ee2a8; }
.no-tag { color: #ff8f8f; }

/* --------------------------------------------------- toolkit: select/view */
.pick-box {
  flex: none; width: 22px; height: 22px; border-radius: 6px; margin-right: 10px;
  border: 1.5px solid var(--line); background: rgba(255, 255, 255, 0.05);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--accent); font-weight: 700;
}
.entry-row.picked .pick-box, .grat-card.picked .pick-box {
  border-color: var(--accent); background: rgba(90, 160, 255, 0.18);
}
.grat-card.picked, .entry-row.picked { background: rgba(90, 160, 255, 0.07); }

/* A saved entry read in full. */
.view-list { margin: 0; padding-left: 24px; }
.view-list li { padding: 5px 0; font-size: 16px; line-height: 1.55; color: var(--ink); }
.view-q { padding: 12px 0; border-bottom: 1px solid var(--line); }
.view-q:last-child { border-bottom: 0; }
.view-qtext { font-size: 13px; color: var(--muted); margin-bottom: 5px; line-height: 1.45; }
.view-note { font-size: 16px; line-height: 1.6; color: var(--ink); white-space: pre-wrap; }
.view-ans { font-size: 15px; font-weight: 700; margin-bottom: 5px; }
.view-ans.yes { color: #ffcf6b; }
.view-ans.no { color: #7ee2a8; }
.view-type {
  display: inline-block; margin-bottom: 10px; padding: 3px 10px; border-radius: 999px;
  background: rgba(90, 160, 255, 0.16); border: 1px solid rgba(90, 160, 255, 0.3);
  font-size: 12px; font-weight: 700; color: var(--ink);
}

/* ------------------------------------------------------- goal checklist */
/* Three parts of a life, divided by rules the way the sheet divides the page. */
.goal-sheet { margin-top: 4px; }
.goal-sec { padding: 14px 0; border-bottom: 1px solid var(--line); }
.goal-sec:first-child { padding-top: 4px; }
.goal-sec:last-child { border-bottom: 0; padding-bottom: 2px; }
.goal-sec-title {
  font-size: 13px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 9px;
}
.goal-items { list-style: none; margin: 0; padding: 0; }
.goal-items li {
  display: flex; align-items: flex-start; gap: 9px; padding: 5px 0;
  font-size: 16px; line-height: 1.5; color: var(--ink);
}
.goal-items li.done .goal-text { color: var(--muted); text-decoration: line-through; }
.goal-tick {
  flex: none; width: 20px; height: 20px; border-radius: 6px; margin-top: 1px;
  border: 1.5px solid var(--line); display: inline-flex; align-items: center;
  justify-content: center; font-size: 12px; font-weight: 700; color: var(--accent);
}
.goal-items li.done .goal-tick { border-color: var(--accent); background: rgba(90, 160, 255, 0.18); }
.goal-text { min-width: 0; overflow-wrap: anywhere; }
.goal-empty { padding: 2px 0; }

.goal-term {
  display: inline-block; padding: 3px 11px; border-radius: 999px;
  background: rgba(90, 160, 255, 0.16); border: 1px solid rgba(90, 160, 255, 0.3);
  font-size: 12px; font-weight: 700; color: var(--ink);
}
.goal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }

/* The editor */
.goal-edit .cardtitle { margin-bottom: 4px; }
.goal-row { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
.goal-row .goal-input { flex: 1; min-width: 0; margin: 0; }
.goal-tick-btn {
  flex: none; width: 30px; height: 30px; min-height: 0; padding: 0; border-radius: 8px;
  background: rgba(255, 255, 255, 0.05); border: 1.5px solid var(--line);
  color: var(--accent); font-size: 14px; font-weight: 700; box-shadow: none;
}
.goal-tick-btn.on { border-color: var(--accent); background: rgba(90, 160, 255, 0.2); }
.goal-x {
  flex: none; width: 30px; height: 30px; min-height: 0; padding: 0; border-radius: 8px;
  background: none; border: 0; color: var(--muted); font-size: 14px; box-shadow: none;
}
.goal-add { margin-top: 4px; }
.card-inline.goal-date { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.card-inline.goal-date input { margin: 0; }
.on-profile {
  font-size: 11px; font-weight: 700; color: var(--accent); margin-left: 6px;
  text-transform: uppercase; letter-spacing: 0.04em;
}

/* ------------------------------------------------- the notifications ask */
/* Shown once per device, just after signing in. A sheet rather than a banner:
   it wants an answer, and the answer has to come from a real tap. */
.ask-back {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-end;
  justify-content: center; background: rgba(4, 8, 22, 0.66);
  padding: 16px; padding-bottom: calc(16px + env(safe-area-inset-bottom));
  animation: askin 0.22s ease-out;
}
@keyframes askin { from { opacity: 0; } to { opacity: 1; } }
.ask-card {
  width: 100%; max-width: 420px; background: var(--card); border: 1px solid var(--line);
  border-radius: 18px; padding: 22px 20px; text-align: center;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
}
.ask-card b { color: #fff; font-size: 18px; }
.ask-icon { font-size: 34px; margin-bottom: 8px; }
@media (min-width: 560px) { .ask-back { align-items: center; } }

/* ---------------------------------------------------------------- chat head */
/* Pinned to the top of the window so the name of whoever you are talking to -
   and the way into a group's members and logo - stays reachable however far
   down the conversation you are. Sticky rather than fixed, so it scrolls with
   the page's own max-width column instead of fighting the iOS viewport. */
/* One compact row: back, who you are talking to, and that is all. The screen
   belongs to the conversation, so the header takes as little of it as it can.
   The notch clearance goes on the TOP - it was going on the bottom as well,
   which is where sixty pixels of empty space in the middle of the screen was
   coming from. */
.chathead {
  display: flex; align-items: center; gap: 10px;
  padding: calc(var(--safe-top, 0px) + 7px) 12px 7px;
  background: rgba(11, 20, 48, 0.9);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  border-bottom: 1px solid var(--line);
}
.chathead-main { display: flex; align-items: center; gap: 9px; min-width: 0; flex: 1; }
.chathead-text { min-width: 0; }
.chathead-name {
  background: none; border: 0; padding: 0; box-shadow: none; min-height: 0;
  font-size: 16.5px; font-weight: 700; letter-spacing: -0.01em; color: #fff;
  text-align: left; display: block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chathead-sub {
  font-size: 11px; color: var(--muted); margin-top: 1px;
  display: flex; align-items: center; gap: 5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chathead-actions { display: flex; gap: 6px; flex: none; }
/* The header's own buttons are small and quiet - they are not the point of
   the screen. */
.chathead .btn-sm { min-height: 34px; padding: 0 12px; font-size: 13px; }
.chathead .avatar-sm, .chathead .avatar { width: 34px; height: 34px; font-size: 12px; }

/* -------------------------------------------------------------- reactions */
/* A bubble and its reactions travel together, so a chip sits under the message
   it belongs to and on the same side of the conversation. */
.bubble-wrap { display: flex; flex-direction: column; max-width: 82%; }
.bubble-wrap.mine { align-self: flex-end; align-items: flex-end; }
.bubble-wrap.theirs { align-self: flex-start; align-items: flex-start; }
.bubble-wrap:has(.react-row) { margin-bottom: 4px; }

/* A message on its way to the server, and one that did not make it. */
.bubble-wrap.pending .bubble { opacity: 0.62; }
.bubble-wrap.failed .bubble { opacity: 1; background: rgba(255, 120, 120, 0.22); border: 1px solid rgba(255, 120, 120, 0.5); box-shadow: none; }
.bubble-wrap .bubble { max-width: 100%; align-self: auto; }
/* Stops iOS offering "Copy / Look Up" over a long press we are handling. */
.bubble-wrap .bubble { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }

/* Sits UNDER its bubble with room to breathe. A negative margin here tucked
   the chips up over the message above and into the one below. */
.react-row { display: flex; flex-wrap: wrap; gap: 4px; margin: 5px 4px 2px; }
.react-chip {
  display: inline-flex; align-items: center; gap: 4px; min-height: 0;
  padding: 2px 8px; border-radius: 999px; font-size: 13px; line-height: 1.5;
  background: var(--glass-2); border: 1px solid var(--line); color: var(--ink);
  box-shadow: none;
}
.react-chip.mine { border-color: var(--accent); background: rgba(90, 160, 255, 0.2); }
.react-chip span { font-size: 11px; font-weight: 700; opacity: 0.85; }

/* The picker a long press opens. */
.react-pop {
  position: fixed; z-index: 70; display: flex; gap: 2px; padding: 6px;
  /* Ten of them will not sit on one line on a narrow phone, so it wraps to a
     second row rather than running off the side. The radius is kept modest so
     it still looks right either way. */
  flex-wrap: wrap; justify-content: center;
  max-width: min(336px, calc(100vw - 24px));
  background: #1a2450; border: 1px solid var(--line); border-radius: 22px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.5);
  opacity: 0; transform: scale(0.86); transform-origin: center bottom;
  transition: opacity 0.14s ease-out, transform 0.14s ease-out;
}
.react-pop.in { opacity: 1; transform: scale(1); }
.react-pop button {
  background: none; border: 0; box-shadow: none; min-height: 0;
  padding: 5px 6px; font-size: 23px; line-height: 1; border-radius: 50%;
}
.react-pop button:active { background: rgba(255, 255, 255, 0.12); }

/* --------------------------------------------------------- suggestion box */
.suggest-row { text-align: left; }
.suggest-row b { color: #fff; }

/* The Messages badge announcing itself as a message lands, rather than just
   appearing at the next repaint. */
@keyframes badgepop {
  0%   { transform: scale(0.4); opacity: 0; }
  55%  { transform: scale(1.28); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
.tbadge.pop { animation: badgepop 0.42s cubic-bezier(0.2, 1.3, 0.4, 1); }


/* ---------------------------------------------------------- the chat screen */
/* iOS reports the layout viewport at the wrong size while a keyboard is up, so
   ANY element told to sit at `bottom: 0` ends up stranded in the middle of the
   screen. There is no arguing with it, so the chat screen stops asking: it is
   one box, sized and placed from the visible viewport (the only measurement
   iOS gets right), laid out as a column. The composer is at the bottom because
   it is the last child of that column - not because it was told where the
   bottom is. The message list is the part that scrolls. */
/* The chat is an ordinary page that scrolls, not a fixed box.
   That is the whole point. On this phone iOS neither shrinks the viewport for
   the keyboard nor reports it through visualViewport, so there is NOTHING to
   measure and no arithmetic that can place the composer above it. But iOS has
   always done one thing reliably: when you focus an input in a normal
   scrolling document, it scrolls that input into view above the keyboard.
   So the composer is simply the last thing on the page, and iOS puts it where
   it belongs. No measuring, no fixed positioning, nothing to get wrong. */
/* A column at least as tall as the screen. With only a message or two in it the
   conversation used to end wherever the last bubble did, leaving the composer
   stranded near the top with a field of empty blue under it. The message list
   takes up whatever slack is left, so the composer lands at the bottom without
   anything here being told where the bottom is - it is still simply the last
   child, exactly as described above.
   svh rather than dvh on purpose: the small viewport height does not move when
   the keyboard opens, so this is a constant. A height that changed with the
   keyboard would restart the very layout fight this whole section exists to
   avoid. */
.chatscreen {
  display: flex;
  flex-direction: column;
  min-height: calc(var(--vph) - var(--tabbar-real));
  /* Held back for the frame or two it takes to land on the newest message, so
     the scroll into place is never something you watch happen. */
  transition: opacity 0.14s ease-out;
}
.chatscreen.settling { opacity: 0; transition: none; }
@media (prefers-reduced-motion: reduce) {
  .chatscreen { transition: none; }
}

/* The name stays at the top while the conversation scrolls under it. */
.chatscreen .chathead {
  position: sticky; top: 0; z-index: 20;
  margin: 0 0 4px;
}
/* The part that absorbs the spare height, which is what pushes the composer
   down to the bottom on a short conversation. */
.chatscreen .chat { padding: 8px 14px 10px; flex: 1 0 auto; }
.chatscreen .chatbar {
  position: static; max-width: none; margin: 0;
  /* No home-indicator inset here. The tab bar sits below the composer and its
     reserved strip already covers that inset - adding it again is what left
     the composer floating a finger's width above the bar. */
  padding: 8px 14px;
  background: none; -webkit-backdrop-filter: none; backdrop-filter: none;
}

/* Room for the tab bar under the composer, so the last thing on the page is
   not hidden behind it. */
body.in-chat #app {
  padding: 0 0 var(--tabbar-real);
}
/* While the keyboard is up the tab bar steps aside, so that room is not
   needed - and it must not push the composer down behind the keyboard. */
body.kb-open.in-chat #app { padding-bottom: 8px; }
body.kb-open .tabbar { display: none; }


/* ---------------------------------------------------------- inline editing */
/* Editing happens where the text already is, in a box the size of what is
   being written - not in a one-line browser prompt with the rest of the post
   hidden behind an ellipsis. Deliberately built to look like the composer, so
   editing something feels like writing it did. */
.inline-edit {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 12px;
  margin: 2px 0;
}
.inline-edit .ie-text {
  width: 100%; margin: 0; resize: none; overflow-y: auto;
  min-height: 76px; line-height: 1.55;
}
.inline-edit .md-help { margin-top: 8px; }
.inline-edit .row { flex-wrap: wrap; }
.inline-edit .ie-save { flex: 1; min-width: 130px; }

/* The time and what it means, on one line. */
.time-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.time-row .hint { margin: 0; }

/* ---------------------------------------------------------------- lightbox */
/* A photo full size over the app. Opening one in a new window was a dead end:
   a home-screen app has no address bar and no back button, so the only way
   back to the conversation was closing the whole app. */
.lightbox {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  background: rgba(2, 5, 16, 0.94);
  padding: calc(env(safe-area-inset-top, 0px) + 12px) 12px
           calc(env(safe-area-inset-bottom, 0px) + 12px);
  opacity: 0; transition: opacity 0.16s ease-out;
}
.lightbox.in { opacity: 1; }
.lightbox img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 10px;
}
.lb-close {
  position: absolute; top: calc(env(safe-area-inset-top, 0px) + 10px); right: 12px;
  width: 40px; height: 40px; min-height: 0; padding: 0; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14); border: 1px solid rgba(255, 255, 255, 0.22);
  color: #fff; font-size: 17px; line-height: 1; box-shadow: none;
}


/* A built-in chat a graduate has stepped out of: still listed, clearly not
   theirs any more, and one tap from walking back in. */
.thread-row.left-room { opacity: 0.55; }
.rejoin-btn {
  flex: none; min-height: 32px; padding: 0 12px; font-size: 12.5px; border-radius: 10px;
}
