/*
 * OI! — Global Stylesheet
 * Single source of truth for theme, typography, and shared components.
 * Page-specific styles remain inline but should be minimal.
 *
 * Usage: <link rel="stylesheet" href="/styles.css"> in every page <head>
 */

/* ═══ Reset ═══ */
*, *::before, *::after { box-sizing: border-box; }
html { overflow: hidden; height: 100%; height: 100dvh; overscroll-behavior: none; }

/* Prevent iOS auto-zoom on input focus (requires font-size >= 16px) */
input, textarea, select { font-size: 16px; font-family: var(--font-sans); }

/* App-wide: textareas auto-grow to fit their content (Chrome 123+ /
   Safari 17.4+ via field-sizing). Older browsers ignore the property and
   fall back to their default fixed height. max-height caps growth so a
   huge value doesn't push the rest of the form off-screen — content
   scrolls past the cap. */
textarea { field-sizing: content; min-height: 2.4em; max-height: 60vh; }

/* ═══ Dark Theme (default) ═══ */
:root {
  color-scheme: dark;

  /* Width of the desktop workspace rail. Every fixed-position surface that
     sits BESIDE the rail (comms panels, overlays, the hosted-trip panel)
     offsets from this instead of a hardcoded 72px, so the rail can change
     width in one place. nav.js overrides it when the rail is expanded.
     Always write it as var(--oi-rail-w, 72px) — a handful of client pages
     don't load this stylesheet, and an undefined var drops the whole
     declaration. */
  --oi-rail-w: 72px;

  /* Backgrounds */
  --bg:         #0e1117;
  --bg-2:       #161b22;
  --bg-3:       #1c2128;
  --bg-card:    #161b22;
  --bg-panel:   #1c2128;
  --bg-hover:   rgba(255,255,255,0.04);
  --bg-input:   #0d1117;

  /* Surfaces (matches nav.js --oi-surface) */
  --surface:    #111116;
  --surface2:   #18181f;
  --surface3:   #2a2a35;
  --bubble-other: #252530;

  /* Borders */
  --border:     #21262d;
  --border-2:   #30363d;

  /* Text */
  --text:       #e2e4ea;
  --text-1:     var(--text); /* alias — some code uses --text-1; track --text in both themes */
  --text-2:     #c9d1d9;
  --text-3:     #8b949e;
  --text-4:     #767e8a;
  --text-5:     #747f8e;
  --text-muted: #7c7c92;

  /* Accent — "Classic" palette. NOTE: palettes.css overrides --accent for
     every other palette, and the DEFAULT is timber-sage, so for most users the
     accent comes from there and not from here. Changing this line changes the
     Classic palette only. (Learned the hard way, 6 Sep 2026.) */
  --accent:     #1db954;
  --accent-text: #1db954;  /* the accent as SMALL TEXT on a card — see lib/contrast.js.
                              Classic already clears AA here (6.69:1), so it is the
                              accent itself; three dark palettes need a lifted one. */
  --accent-hover:#1ed760;
  /* A filled control takes its background from whatever palette is active, and
     the text on it must come from the palette too — no single ink passes on all
     seven accents. Each palette declares its own --accent-on; these are
     Classic's. Measured: near-black on #1db954 is 7.30:1, white is 2.59:1. */
  --accent-fill: var(--accent);
  --accent-on:   #0f1117;
  --green:      #1db954;
  --green-bg:   rgba(29,185,84,0.06);
  --green-border:rgba(29,185,84,0.25);

  /* Semantic colors */
  --red:        #f85149;
  --orange:     #f0883e;
  --blue:       #58a6ff;
  --gold:       #eab308;
  --silver:     #94a3b8;
  --purple:     #a371f7;
  --yellow:     #d29922;
  --warning:    #d29922; /* alias for star/warning surfaces (matches --yellow) */
  --cyan:       #39d2c0;
  --bronze:     #d97706;
  /* NOTE: a second '--green: #3fb950' used to live here and silently
     overrode line 58, making --green != --accent. Removed. */

  /* Dashboard aliases (legacy compat) */
  --card:       var(--bg-card);
  --card-border:var(--border);
  --card-bg:    var(--bg-card);   /* was referenced but never defined */
  --accent2:    #39d2c0;         /* was referenced but never defined */

  /* Contacts aliases (no-dash naming compat) */
  --text2:      var(--text-2);
  --text3:      var(--text-3);
  --green2:     #1aa34a;

  /* Layout */
  --nav-height: 56px;
  --tab-height: 60px;
  --radius:     10px;
  --radius-sm:  6px;

  /* Typography */
  --font-sans:  'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --font-display: 'Bricolage Grotesque', 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono:  'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;

  /* Chart palette — read by dashboard / chart.js datasets via getComputedStyle.
     Override in light theme below if a chart needs different shades. */
  --chart-1:    #f97316; /* primary / current period (orange) */
  --chart-2:    #22c55e; /* positive / up (green) */
  --chart-3:    #06b6d4; /* average / info (cyan) */
  --chart-4:    #eab308; /* record / highlight (yellow) */
  --chart-1-soft: rgba(249,115,22,0.15);
  --chart-1-mid:  rgba(249,115,22,0.5);
  --chart-1-bold: rgba(249,115,22,0.9);
}

/* ═══ Light Theme ═══ */
[data-theme="light"] {
  color-scheme: light;

  --bg:         #f6f8fa;
  --bg-2:       #f0f3f6;
  --bg-3:       #e8ecf0;
  --bg-card:    #ffffff;
  --bg-panel:   #ffffff;
  --bg-hover:   rgba(0,0,0,0.04);
  --bg-input:   #ffffff;

  --surface:    #ffffff;
  --surface2:   #f0f3f6;
  --surface3:   #d0d7de;

  /* ── Light-theme overrides for tokens that were dark-only ──
     These previously bled dark values into light mode. Chart colors
     are darkened to clear 3:1 contrast on white (they measured
     1.9–2.8:1 before, i.e. effectively unreadable). */
  --gold:       #a16207;
  --silver:     #64748b;
  --warning:    #9a6700;
  --bronze:     #b45309;
  --chart-1:    #c2410c;
  --chart-2:    #15803d;
  --chart-3:    #0e7490;
  --chart-4:    #a16207;
  --chart-1-soft: rgba(194,65,12,0.12);
  --chart-1-mid:  rgba(194,65,12,0.45);
  --chart-1-bold: rgba(194,65,12,0.90);

  /* Referenced across dashboard pages but never defined anywhere. */
  --card-bg:    var(--bg-card);
  --accent2:    #0e7490;
  --bubble-other: #e9ecf0;

  --border:     #d0d7de;
  --border-2:   #d8dee4;

  --text:       #1f2328;
  --text-2:     #32383f;
  --text-3:     #656d76;
  --text-4:     #68717c;
  --text-5:     #637283;
  --text-muted: #656d76;

  --accent:     #1a7f37;
  --accent-text: #1a7f37;  /* 5.08:1 on white — already readable. */
  --accent-hover:#116329;
  /* On light, Classic's accent is dark enough that white is the readable ink:
     5.08:1 against near-black's 3.72:1. */
  --accent-fill: var(--accent);
  --accent-on:   #ffffff;
  --green:      #1a7f37;
  --green-bg:   rgba(26,127,55,0.06);
  --green-border:rgba(26,127,55,0.25);

  --red:        #cf222e;
  --orange:     #bc4c00;
  --blue:       #0969da;
  --purple:     #8250df;
  --yellow:     #9a6700;
  --cyan:       #0969da;
  --green:      #1a7f37;
}

/* ═══ Base ═══ */
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  overflow: hidden;
  overscroll-behavior: none;
  position: fixed;
  width: 100%;
  height: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* A page that reads as a document (pay, claim, webinar, show…) scrolls the
   whole page instead of an app-shell scroller: <html class="lore-doc">. */
html.lore-doc, html.lore-doc body { overflow: visible; overflow-x: clip; height: auto; min-height: 100%; position: static; overscroll-behavior: auto; }

/* ═══ Typography — Bricolage (display) + DM Sans (body) ═══ */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  letter-spacing: -0.02em;
}
.font-display, .oi-brand, .oi-stat-value, .oi-page-heading {
  font-family: var(--font-display);
  letter-spacing: -0.02em;
}

/* ═══ Scrollbar ═══ */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-2); }

/* ═══ Typography ═══ */
h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 600; color: var(--text); }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ═══ Common Components ═══ */

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  border: none;
  transition: all 0.15s;
  font-family: var(--font-sans);
}
.btn-primary {
  background: var(--accent-fill);
  color: var(--accent-on);
}
.btn-primary:hover {
  background: var(--accent-hover);
}
.btn-secondary {
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
}
.btn-secondary:hover {
  background: var(--bg-hover);
}

/* Cards */
.card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

/* Inputs */
.input {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-input);
  color: var(--text);
  border: 1px solid var(--border-2);
  border-radius: 8px;
  font-size: 14px;
  font-family: var(--font-sans);
  outline: none;
  transition: border-color 0.15s;
}
.input:focus {
  border-color: var(--accent);
}
.input::placeholder {
  color: var(--text-4);
}

/* Badges / Pills */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.badge-green { background: var(--green-bg); color: var(--green); border: 1px solid var(--green-border); }
.badge-red { background: rgba(239,68,68,0.08); color: var(--red); border: 1px solid rgba(239,68,68,0.2); }
.badge-orange { background: rgba(245,158,11,0.08); color: var(--orange); border: 1px solid rgba(245,158,11,0.2); }

/* Loading spinner */
.spinner {
  width: 20px;
  height: 20px;
  border: 2px solid var(--border-2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px;
  color: var(--text-4);
  gap: 12px;
}

.empty {
  text-align: center;
  padding: 40px;
  color: var(--text-4);
}

/* ═══ Responsive ═══ */
@media (max-width: 767px) {
  body {
    font-size: 13px;
  }
}

/* ═══ Touch Device Hover Fix ═══ */
/* Prevent sticky :hover states on touch devices (iOS tap-and-hold) */
@media (hover: none) {
  /* Cards, buttons, rows — remove hover transforms and bg changes */
  .card:hover,
  .btn:hover,
  .btn-primary:hover,
  .btn-secondary:hover,
  a:hover {
    transform: none !important;
    box-shadow: none !important;
  }
}

/* ═══ Message Reactions ═══ */
/* Messages can be selected and copied (Cory, 7 Oct: "I can't copy messages to
   paste … a huge deal"). Only a touch screen holds selection back, so a long
   press opens the message's actions (Copy is one of them) instead. */
@media (hover: none) and (pointer: coarse) {
  [data-msg-id] { -webkit-touch-callout: none !important; -webkit-user-select: none !important; user-select: none !important; }
}
@media (hover: hover), (pointer: fine) {
  [data-msg-id] .oi-msg-text, [data-msg-id] .oi-msg-text * { -webkit-user-select: text !important; user-select: text !important; cursor: text; }
}
.oi-reaction-row {
  display: flex !important; gap: 4px; padding: 2px 12px 2px 12px; flex-wrap: wrap;
  clear: both;
}
.oi-reaction-pill {
  /* Slack's reaction pill (Cory, 24 Sep): quiet grey, the count beside the
     emoji, blue when it is yours. */
  display: inline-flex !important; align-items: center; gap: 4px; padding: 0 7px;
  border-radius: 12px; border: 1px solid rgba(127, 127, 127, .28);
  background: rgba(127, 127, 127, .08); font-size: 13px; cursor: pointer;
  transition: background .15s, border-color .15s; line-height: 1; height: 24px; max-height: 24px;
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
  overflow: hidden; color: var(--text-2, #4a525c);
}
.oi-reaction-pill:hover { border-color: rgba(127, 127, 127, .55); background: rgba(127, 127, 127, .14); }
.oi-reaction-pill.is-mine { background: rgba(29, 155, 209, .12); border-color: #1d9bd1; color: #1264a3; }
.oi-reaction-emoji { font-size: 14px; }
.oi-reaction-count {
  font-size: 11.5px; font-weight: 600; color: inherit;
}
.oi-reaction-picker {
  position: fixed; 
  display: flex; gap: 2px; padding: 4px 6px; flex-wrap: wrap; max-width: 260px;
  justify-content: center;
  background: var(--oi-bg-panel, #fff); border: 1px solid var(--oi-border, #ddd);
  border-radius: 20px; box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  z-index: 10000;
}
.oi-reaction-pick-btn {
  background: none; border: none; font-size: 20px; cursor: pointer;
  padding: 4px 5px; border-radius: 8px; transition: all 0.1s; line-height: 1;
}
.oi-reaction-pick-btn:hover {
  background: var(--oi-surface-2, #f0f0f0); transform: scale(1.2);
}
.oi-reaction-trigger {
  position: absolute; bottom: -8px; right: -8px;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--oi-bg-panel, #fff); border: 1px solid var(--oi-border, #ddd);
  font-size: 14px; cursor: pointer; display: flex; align-items: center;
  justify-content: center; box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  z-index: 50; transition: all 0.15s; line-height: 1; padding: 0;
}
.oi-reaction-trigger:hover {
  transform: scale(1.15); box-shadow: 0 3px 12px rgba(0,0,0,0.2);
}

/* ═══ Attachments ═══ */
#oi-attach-preview {
  display: flex; gap: 6px; padding: 6px 12px; flex-wrap: wrap; min-height: 0;
}
#oi-attach-preview:empty { display: none; padding: 0; }
.oi-attach-thumb {
  position: relative; display: inline-block;
}
.oi-attach-remove {
  position: absolute; top: -6px; right: -6px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #ef4444; color: #fff; border: none;
  font-size: 12px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.oi-attach-btn {
  background: none; border: none; font-size: 18px; cursor: pointer;
  padding: 4px 6px; border-radius: 6px; color: var(--oi-text-2, #888);
  transition: color 0.15s;
}
.oi-attach-btn:hover { color: var(--accent); }

/* ═══ Message Action Bar ═══ */
.oi-action-bar {
  position: absolute; top: -30px; right: 0;
  display: flex; gap: 0; padding: 0;
  background: var(--oi-bg-panel, #fff); border: 1px solid var(--oi-border, #ddd);
  border-radius: 6px; box-shadow: 0 1px 4px rgba(0,0,0,0.1);
  z-index: 50; white-space: nowrap; overflow: hidden;
}
.oi-action-btn {
  background: none; border: none; cursor: pointer;
  padding: 5px 7px; line-height: 1;
  color: var(--oi-text-2, #666);
  transition: background 0.1s, color 0.1s;
  display: flex; align-items: center; justify-content: center;
}
.oi-action-btn:hover {
  background: var(--oi-surface-2, #f0f0f0);
  color: var(--oi-text, #333);
}
.oi-action-btn svg { display: block; }
.oi-action-bar-mobile {
  border-radius: 12px; box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  padding: 2px 4px;
}
.oi-action-bar-mobile .oi-action-btn {
  padding: 8px 10px;
}
.oi-quick-emoji {
  font-size: 16px; padding: 4px 6px;
}

/* ═══ Custom Tooltip ═══ */
.oi-tip {
  position: fixed; z-index: 100001;
  padding: 4px 8px; border-radius: 4px;
  background: #1d1c1d; color: #fff; font-size: 12px; font-weight: 500;
  white-space: nowrap; pointer-events: none;
  opacity: 0; transition: opacity 0.1s ease;
}
.oi-tip.show { opacity: 1; }
.oi-tip::after {
  content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: #1d1c1d;
}
[data-theme="dark"] .oi-tip {
  background: #e8e8e8; color: #1d1c1d;
}
[data-theme="dark"] .oi-tip::after {
  border-top-color: #e8e8e8;
}

/* ═══ Action Menu (dropdown) ═══ */
.oi-action-menu {
  position: fixed; min-width: 160px; padding: 4px 0;
  background: var(--oi-bg-2, var(--oi-card-bg, #1e2130)); border: 1px solid var(--oi-border, rgba(255,255,255,0.1));
  border-radius: 10px; box-shadow: 0 6px 24px rgba(0,0,0,0.4);
  z-index: 10001;
}
.oi-action-menu-item {
  display: flex; align-items: center; width: 100%; text-align: left; padding: 9px 14px;
  background: none; border: none; font-size: 13px; cursor: pointer;
  color: var(--oi-text, #e8eaf0); transition: background 0.12s; gap: 8px;
}
.oi-action-menu-item svg { flex-shrink: 0; }
@media (hover: hover) {
  .oi-action-menu-item:hover {
    background: var(--oi-surface-2, rgba(255,255,255,0.06));
  }
}
[data-theme="light"] .oi-action-menu {
  background: #fff; border-color: #e0e0e0; box-shadow: 0 4px 16px rgba(0,0,0,0.12);
}
[data-theme="light"] .oi-action-menu-item { color: #1a1d27; }
[data-theme="light"] .oi-action-menu-item:hover { background: #f5f5f5; }

/* ═══ Reply Indicator ═══ */
.oi-reply-bar {
  display: flex; align-items: center; gap: 8px; padding: 6px 12px;
  background: var(--oi-surface-2, #f5f5f5); border-left: 3px solid var(--accent);
  border-radius: 4px; margin: 4px 12px;
}

/* ═══ Toast ═══ */
.oi-toast {
  position: fixed; bottom: 80px; left: 50%; transform: translateX(-50%) translateY(20px);
  padding: 8px 16px; background: #333; color: #fff; border-radius: 8px;
  font-size: 13px; z-index: 100000; opacity: 0; transition: all 0.3s ease;
  pointer-events: none; white-space: nowrap;
}
.oi-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ═══ Auth Screen (index.html) ═══ */
/* A tester could not finish registration on 17 Sep: the page "won't scroll up".
   Measured at 390x500 (a phone with the keyboard open) on the Sign Up tab, the
   card was 966px tall in a 500px window with its top at -233px — the logo, the
   Google button and the first fields sat above the screen with no way back.

   Three things were true at once. `height: 100vh` does not shrink when the
   keyboard opens; `align-items: center` overflows a too-tall card EQUALLY off
   both ends, and centred flex overflow has no scroll position that recovers the
   top; and nothing in the chain could scroll, because the app shell sets
   `overflow: hidden` on html and body and this screen never opted out.

   So: a bounded scroll container on the dynamic viewport, and auto margins in
   place of centre alignment — `margin: auto` centres the card when there is
   room and simply stops centring when there is not, which is the behaviour
   `align-items: center` lacks. Pinned by test/auth-screen-scroll.test.js. */
#auth-screen {
  display: flex; align-items: flex-start; justify-content: center;
  height: 100vh;            /* fallback first — browsers without dvh */
  height: 100dvh;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: linear-gradient(135deg, var(--bg) 0%, var(--bg-card) 100%);
}
.auth-container {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px;
  padding: 40px; width: 100%; max-width: 400px; margin: auto 20px;
}
.auth-logo { text-align: center; margin-bottom: 32px; }
.auth-logo h1 { font-family: var(--font-display); font-size: 2.5rem; color: var(--accent); margin-bottom: 4px; letter-spacing: -0.03em; }
.auth-logo p { color: var(--text-3); font-size: 0.9rem; }
.auth-tabs { display: flex; margin-bottom: 24px; border-bottom: 1px solid var(--border); }
.auth-tab {
  flex: 1; padding: 12px; text-align: center; cursor: pointer; color: var(--text-3);
  border-bottom: 2px solid transparent; transition: all 0.2s;
  background: none; border-top: none; border-left: none; border-right: none; font-size: 0.95rem;
}
.auth-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.auth-form { display: none; }
.auth-form.active { display: block; }
.form-group { margin-bottom: 16px; }
.form-group label { display: block; margin-bottom: 6px; color: var(--text-2); font-size: 0.85rem; }
.form-group input {
  width: 100%; padding: 10px 14px; background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; color: var(--text); font-size: 0.95rem; outline: none; transition: border-color 0.2s;
}
.form-group input:focus { border-color: var(--accent); }
.auth-btn {
  width: 100%; padding: 12px; background: var(--accent-fill); color: var(--accent-on); border: none;
  border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: background 0.2s; margin-top: 8px;
}
.auth-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.auth-error { color: var(--red); font-size: 0.85rem; margin-top: 12px; text-align: center; min-height: 20px; }
.auth-skip { text-align: center; margin-top: 20px; }
.auth-skip a { color: var(--text-3); font-size: 0.85rem; text-decoration: none; cursor: pointer; }
.auth-legal { text-align: center; margin-top: 18px; color: var(--text-3); font-size: 0.75rem; line-height: 1.7; }
.auth-legal a { color: var(--text-3); text-decoration: none; }
.auth-legal a:hover { color: var(--text-2); }
/* "Continue with Google" button — white with Google's color logo, the
   standard branding pattern. Sits above the magic-link form as the
   recommended path. */
.auth-btn-google { background: #fff; color: #1f1f1f; border: 1px solid #dadce0; font-weight: 500; display: flex; align-items: center; justify-content: center; font-size: 0.88rem; padding: 10px; white-space: nowrap; gap: 8px; }
.auth-btn-google svg, .auth-btn-google img { flex: 0 0 auto; }
.auth-btn-google:hover { background: #f8f9fa; border-color: #c5c8cb; }
.auth-btn-apple { background: #000; color: #fff; border: 1px solid #000; font-weight: 500; display: flex; align-items: center; justify-content: center; font-size: 0.88rem; padding: 10px; white-space: nowrap; gap: 8px; margin-bottom: 10px; }
.auth-btn-apple:hover { background: #1c1c1e; }
.auth-divider { display: flex; align-items: center; gap: 10px; margin: 14px 0 16px; color: var(--text-3); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; }
.auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.auth-fallback summary::-webkit-details-marker { display: none; }
.auth-fallback summary { list-style: none; }
.auth-fallback[open] summary { margin-bottom: 8px; }

/* ═══ Chat Screen (index.html) ═══ */
#chat-screen { display: none; }
#chat-screen.active { display: flex; flex-direction: column; height: 100%; }
#chat-screen .oi-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
#chat-screen #messages { flex: 1; overflow-y: auto; }
#chat-screen #input-area { flex-shrink: 0; }

.user-badge { font-size: 0.75rem; padding: 3px 10px; border-radius: 12px; background: var(--border); color: var(--text-2); }
.user-badge.admin { background: color-mix(in srgb, var(--purple) 13%, transparent); color: var(--purple); }
.user-badge.consultant { background: color-mix(in srgb, var(--accent) 13%, transparent); color: var(--accent); }

#role-switcher {
  background: var(--bg-card); border: 1px solid color-mix(in srgb, var(--purple) 27%, transparent);
  color: var(--purple); padding: 5px 10px; border-radius: 8px; font-size: 0.75rem; cursor: pointer; display: none;
}
#role-switcher option { background: var(--bg-card); color: var(--text); }

#notif-bell {
  position: relative; background: none; border: none; color: var(--text-3); font-size: 1.2rem;
  cursor: pointer; padding: 4px 8px; display: none; transition: color 0.2s;
}
#notif-bell .notif-count {
  position: absolute; top: -2px; right: 0; background: var(--red); color: white;
  font-size: 0.6rem; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px;
  display: none; align-items: center; justify-content: center; line-height: 1; padding: 0 4px;
}
#notif-bell .notif-count.has-count { display: flex; }

#test-banner {
  display: none; background: color-mix(in srgb, var(--purple) 20%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--purple) 40%, transparent);
  color: var(--purple); text-align: center; padding: 6px; font-size: 0.75rem; font-weight: 500;
}

#messages { flex: 1; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 16px; }
/* One shared conversation column (~860px) centered via container padding —
   user bubbles hug the right edge, Lore's hug the left, like any messenger.
   Bubbles are fit-content so widths read naturally instead of janky
   full-width cards next to small pills. */
#chat-screen #messages { padding-left: max(20px, calc((100% - 860px) / 2)); padding-right: max(20px, calc((100% - 860px) / 2)); }
.message.user { width: fit-content; max-width: 78%; }
.message.assistant { width: fit-content; max-width: 92%; position: relative; margin-left: 34px; }
/* Lore avatar on replies — the ember mark (was a literal "L"). (Cory 7 Sep) */
.message.assistant::before {
  content: ''; position: absolute; left: -34px; top: 2px;
  width: 26px; height: 26px; border-radius: 50%;
  background-color: var(--bg-2, rgba(127,127,127,.14));
  background-image: var(--lore-ember); background-repeat: no-repeat;
  background-position: center; background-size: 52%;
}
#messages > .suggestions { width: 100%; padding-left: 34px; }
/* Composer rides WITH the thread on desktop (last element of the column) */
#messages #input-area { background: transparent; border-top: none; padding: 4px 0 10px; width: 100%; }
#messages #input-area #input-form { max-width: 100%; }
/* ═══ Chat bubble module — GLOBAL. Every chat surface (home, advisor,
   group chat, my-trips) uses these tokens so bubbles match app-wide. ═══ */
:root {
  --bubble-radius: 16px;   /* shared shape */
  --bubble-tail: 4px;      /* the "speech" corner */
  /* Composed shapes — the ONLY thing a bubble should set. Changing the two
     atoms above changes every bubble in the app. test/bubble-shape.test.js
     fails the build if a surface hardcodes a radius instead. */
  --bubble-shape-self:  var(--bubble-radius) var(--bubble-radius) var(--bubble-tail) var(--bubble-radius);
  --bubble-shape-other: var(--bubble-radius) var(--bubble-radius) var(--bubble-radius) var(--bubble-tail);
  --bubble-shape-plain: var(--bubble-radius);
  --bubble-user-bg: var(--accent);
  --bubble-user-fg: #fff;
  --bubble-ai-bg: var(--bg-card);
  --bubble-ai-border: var(--border);
  /* Composer standard (Cory 7/11): every Lore chat/message INPUT is a 12px
     rounded box — NOT a pill — with round mic + send circles beside it. This
     is the ONE radius every composer reads; test/composer-shape.test.js fails
     the build if a surface hardcodes its own. Both roots define it (this file
     for staff pages, lore-tokens.css for member pages) and must agree. */
  --composer-radius: 12px;
  /* Lore's ember mark as an image, for the chat-row avatar (::before can't hold
     an SVG element, but it can hold one as a background). Same flame as
     _emberMark in chat-render.js. lore-brand: this is Lore's own logo, orange
     in every workspace by nature — like the nav ember. */
  --lore-ember: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 78'%3E%3Cg transform='translate(17,43)'%3E%3Ccircle cx='8' cy='-39' r='2.4' fill='%23f7b65c'/%3E%3Cpath d='M0,31 C -15,19 -15,-2 -5,-15 C 0,-22 3,-27 1,-33 C 13,-23 17,-7 15,8 C 13,21 7,26 0,31 Z' fill='%23e8833a'/%3E%3Cpath d='M2,24 C -7,14 -6,0 0,-10 C 3,-15 6,-8 5,-1 C 9,5 8,16 2,24 Z' fill='%23f7b65c'/%3E%3C/g%3E%3C/svg%3E");
}
.message { max-width: 85%; padding: 12px 16px; border-radius: var(--bubble-shape-plain, 16px); line-height: 1.6; font-size: 0.95rem; }
.message.user { align-self: flex-end; background: var(--bubble-user-bg); color: var(--bubble-user-fg); border-radius: var(--bubble-shape-self, 16px 16px 4px 16px); }
.message.assistant { align-self: flex-start; background: var(--bubble-ai-bg); border: 1px solid var(--bubble-ai-border); border-radius: var(--bubble-shape-other, 16px 16px 16px 4px); }
.message.assistant p { margin-bottom: 8px; }
.message.assistant p:last-child { margin-bottom: 0; }
.message.assistant code { background: var(--bg); padding: 2px 6px; border-radius: 4px; font-size: 0.85em; }
.message.assistant pre { background: var(--bg); padding: 12px; border-radius: 8px; overflow-x: auto; margin: 8px 0; }
.message.assistant pre code { background: none; padding: 0; }
.message.assistant ul, .message.assistant ol { margin: 8px 0; padding-left: 20px; }
.message.assistant table { border-collapse: collapse; margin: 8px 0; width: max-content; min-width: 100%; }
.message.assistant .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 8px 0; }
.message.assistant th, .message.assistant td { border: 1px solid var(--border); padding: 6px 10px; text-align: left; white-space: nowrap; }
.message.assistant a { color: var(--accent); }
.message.assistant a.oi-link-booking { text-decoration: none; background: var(--green-bg); padding: 1px 5px; border-radius: 4px; font-family: monospace; font-size: 0.9em; font-weight: 600; }
.message.assistant a.oi-link-action { display: inline-block; margin: 2px 0; padding: 3px 10px; border: 1px solid var(--green-border); border-radius: 12px; text-decoration: none; font-size: 0.9em; background: var(--green-bg); }
.message.assistant th { background: var(--bg); }
.booking-link { color: var(--accent); cursor: pointer; text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px; }
.message.thinking {
  align-self: flex-start; color: var(--text-3); font-style: normal;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; border-bottom-left-radius: 4px;
  padding: 12px 16px; display: inline-flex; align-items: baseline; gap: 4px;
  position: relative; margin-left: 34px; width: fit-content;
}
/* Thinking-row avatar: the same ember, flickering while Lore works. The bubble
   itself (OiChat.renderAiThinking, noAvatar) supplies the word + animated dots,
   so there is no ::after here and no second flame inside. (Cory 7 Sep) */
.message.thinking::before {
  content: ''; position: absolute; left: -34px; top: 2px;
  width: 26px; height: 26px; border-radius: 50%;
  background-color: var(--bg-2, rgba(127,127,127,.14));
  background-image: var(--lore-ember); background-repeat: no-repeat;
  background-position: center; background-size: 52%;
  animation: oiEmberFlicker 1.05s ease-in-out infinite; transform-origin: 50% 62%;
}
@keyframes oiEmberFlicker { 0%,100%{opacity:1;transform:scale(1)} 40%{opacity:.6;transform:scale(.94)} 70%{opacity:.85;transform:scale(1.03)} }
/* Once a step trail is showing, the bubble is a list rather than one baseline
   row of dots — and it stays put when the answer arrives instead of being
   thrown away, so you can still read how Lore got there. `.settled` stops the
   ember flickering and steps the whole thing back a shade: it is a record now,
   not activity. (9 Sep) */
.message.thinking:has(.oi-steps) { display: block; align-items: stretch; max-width: 100%; }
.message.thinking.settled { opacity: .72; }
.message.thinking.settled::before { animation: none; opacity: .5; }
@keyframes thinking-dots {
  0%   { content: ''; }
  25%  { content: '.'; }
  50%  { content: '..'; }
  75%  { content: '...'; }
  100% { content: ''; }
}

/* New / History, under the box at the right — quiet text links, the same
   on every page (Cory, 23 Sep: "I do like the New/History links bottom
   right of home"). A way back to something, not a call to action. */
#lore-thread-bar { display: flex; justify-content: flex-end; gap: 14px; padding: 6px 6px 0; max-width: 720px; margin: 0 auto; }
#lore-thread-bar button {
  font-family: inherit; font-size: 11.5px; font-weight: 400; line-height: 1.6;
  padding: 0; border: 0; background: none; cursor: pointer; color: var(--text-3);
  transition: color .15s;
}
#lore-thread-bar button:hover { color: var(--accent); }

/* THE MIC'S STATES — lore-voice.js sets .ofv-<state> on the box's mic, on
   every page (lore-composer.js). The mic stays the quiet outline icon at
   rest; its colour says what it is doing, the line under the box says it
   in words, and waiting is the flame. (23 Sep) */
.oi-comp-mic.ofv-connecting, .oi-comp-mic.ofv-thinking { color: var(--text-3); opacity: .6; }
.oi-comp-mic.ofv-listening { color: var(--red, #dc2626); animation: oi-mic-pulse 1.2s ease-in-out infinite; }
.oi-comp-mic.ofv-speaking { color: var(--accent); }
.oi-comp-mic.ofv-error { color: var(--orange, #d97706); }
@keyframes oi-mic-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .oi-comp-mic.ofv-listening { animation: none; } }
.oi-comp-status { max-width: 720px; margin: 6px auto 0; padding: 0 6px; font-size: 12px; color: var(--text-3); text-align: center; }
.oi-comp-status[hidden] { display: none; }

/* The caption card: what you and Lore said, above the box on pages with no
   thread of their own (home puts it in its thread). */
.oi-voice-sheet { position: relative; max-width: 720px; margin: 0 auto 8px; padding: 12px 36px 12px 14px; background: var(--surface, var(--bg-card, #fff)); border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 6px 24px rgba(0,0,0,.08); pointer-events: auto; }
.oi-voice-sheet-lines { max-height: 38vh; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; font-size: 14px; line-height: 1.45; }
.oi-voice-line.is-you { align-self: flex-end; max-width: 85%; padding: 6px 10px; border-radius: 12px; background: var(--accent-soft, #eef4ee); color: var(--text); }
.oi-voice-line.is-lore { color: var(--text); }
.oi-voice-sheet-x { position: absolute; top: 8px; right: 8px; width: 24px; height: 24px; border: 0; background: none; color: var(--text-3); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.oi-voice-sheet-x:hover { color: var(--text); }

/* The composer is docked at the foot of the page, like Claude's (Cory 16
   Sep): no full-width bar — a rounded box on the page background, the thread
   and the welcome scrolling above it. */
#input-area {
  padding: 6px 16px 12px; padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  background: transparent; border-top: none;
}
#chat-screen #input-area #message-input { background: var(--surface); box-shadow: 0 6px 24px rgba(0,0,0,.08); }
#chat-screen #messages { padding-bottom: 8px; }
@media (max-width: 767px) { #input-area { padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); } }
#input-form { display: flex; gap: 8px; max-width: 900px; margin: 0 auto; align-items: center; }
/* Lore composer standard (Cory 7/11): ROUNDED box (12px — not a pill),
   perfectly round mic + send circles, up-arrow send icon. Every Lore chat
   surface (home / lead advisor / drawer) follows this. */
#message-input {
  flex: 1; background: var(--bg-hover); border: 1px solid var(--border);
  border-radius: var(--composer-radius, 12px); color: var(--text); font-size: 16px; outline: none; resize: none; max-height: 120px; font-family: inherit; line-height: 1.4;
}
/* The composer standard (.oi-comp-input) owns the padding: it has to clear
   the + on the left and the mic + send on the right. This id rule was
   winning on specificity and putting the text at 16px — under the + (Cory,
   22 Sep: "i can't click the +"; the + was drawn beneath the A of "Ask").
   Only a box that is NOT a standard composer keeps the plain padding. */
#message-input:not(.oi-comp-input) { padding: 10px 16px; }
#message-input:focus { border-color: var(--green-border); }
/* The send and mic buttons have no id rules: .oi-comp-send / .oi-comp-mic are
   the single owners, so the box looks the same on every page (23 Sep). */

/* Welcome / Starters */
.welcome-msg { text-align: center; margin: auto; padding: 20px; max-width: 860px; width: 100%; }

/* ── THE HOME, ON A DESKTOP ─────────────────────────────────────────────
   Cory, 5 Sep, looking at the live page: "Still pretty close to the old
   style." Correct — every fix until now went INSIDE this skeleton, and the
   skeleton was one 860px column with nine things of near-equal weight
   stacked down it and roughly 290px of dead margin either side of a 1440px
   screen. That is a phone layout with the phone taken away.

   Below 1100px the wrappers are `display: contents`, so they are not in the
   layout at all and the phone flows exactly as it did. Above it, the
   photograph runs the full width and the page splits: WHAT TO DO on the
   left (Lore's line, the composer, the things that need you), THE LIFE
   ALREADY LIVED on the right (your plans, everything you've done). */
.home-cols, .home-do, .home-life { display: contents; }
@media (min-width: 1100px) {
  .welcome-msg { max-width: 1180px; text-align: left; }
  /* The chips span BOTH columns, under the grid, where a question like
     "What should I pack for my Guided 1st Rifle Elk Hunt?" fits on one
     line instead of six. */
  .welcome-msg > .welcome-starters { grid-template-columns: repeat(4, 1fr); margin-top: 20px; }
  .home-cols { display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr); gap: 0 38px; align-items: start; width: 100%; }
  .home-do, .home-life { display: block; min-width: 0; }
  /* The right rail is the quieter half — it is the record, not the ask. */
  .home-life { border-left: 1px solid var(--border); padding-left: 34px; }
  .home-life > [id$="-hdr"] { margin-top: 0 !important; }
  /* The strips stop being a phone's horizontal scroller and become a rail.
     ONE card per row, not two: the app's sidebar takes ~290px before this
     grid even starts, so a two-up rail was ~120px per card and every title
     truncated — "2026 DIY Grizzly/Ca…", "2025 Guided Free R…". A list you
     cannot read is not a record of anything. */
  .home-life .welcome-trips { flex-wrap: wrap; overflow-x: visible; }
  .home-life .wt-card { min-width: 0; max-width: none; flex: 1 1 100%; }
  .home-life .wt-card.wt-photo { min-height: 96px; }
  /* Freed from the 640px cap that made the hero a card in a wide room. */
  .welcome-msg .lhb, .welcome-msg .lhb-hero { max-width: none; }
  #home-hero .lhb-hero--photo { min-height: 400px; }
  /* The tagline/quote sits under the photograph, not centred over the fold. */
  #welcome-sub { text-align: left; }
}
/* welcome content fills the same column as the active chat — no width jump */
.welcome-starters { display: grid !important; grid-template-columns: 1fr 1fr; gap: 8px; width: 100%; }
@media (max-width: 640px) { .welcome-starters { grid-template-columns: 1fr; } }
.welcome-smart { width: 100%; }
#welcome-msg #input-form { max-width: 100% !important; }
.welcome-logo { font-family: var(--font-display); font-size: 2.2rem; font-weight: 700; color: var(--accent); margin-bottom: 4px; letter-spacing: -0.03em; }
.welcome-sub { color: var(--text-3); font-size: 0.85rem; margin-bottom: 24px; }
.welcome-starters { display: flex; flex-direction: column; gap: 8px; text-align: left; }
/* Once a conversation exists, the welcome compacts to a header: logo +
   greeting stay, chips/trips hide, content anchors to the top. */
#messages.has-thread .welcome-msg { margin: 4px auto 0; max-width: 860px; width: 100%; }
#messages.has-thread .welcome-starters,
#messages.has-thread .home-myday,
#messages.has-thread .welcome-trips,
#messages.has-thread #welcome-plans-hdr,
#messages.has-thread #welcome-memories-hdr { display: none !important; }
#messages.has-thread .welcome-logo { font-size: 1.5rem; margin-bottom: 0; }

/* Memories step aside while you're working comms — any open thread/contact
   panel (comms-l2-open) hides the rail; closing restores it. */
body.comms-l2-open #oi-memories-header,
body.comms-l2-open #oi-memories-rail { display: none !important; }

/* Inline composer — in the welcome state the input sits under the Lore bubble */
#welcome-msg #input-area { background: transparent; border-top: none; padding: 2px 0 14px; }
#welcome-msg #input-form { max-width: 420px; }
body.composer-inline #messages { overflow-y: auto; }

/* Smart welcome — Lore greets you like the advisor does */
.welcome-smart { display: flex; gap: 8px; text-align: left; margin: 0 0 14px; align-items: flex-start; }
.welcome-smart .ws-avatar { flex: 0 0 auto; width: 24px; height: 24px; border-radius: 50%; background: var(--accent-fill); color: var(--accent-on); font-weight: 800; font-size: 12px; line-height: 24px; text-align: center; font-family: var(--font-display); }
.welcome-smart .ws-bubble { background: var(--bubble-ai-bg); border: 1px solid var(--bubble-ai-border); border-radius: var(--bubble-shape-other, 16px 16px 16px 4px); padding: 12px 16px; font-size: 0.95rem; line-height: 1.6; color: var(--text); }
.welcome-trips { display: flex; gap: 8px; overflow-x: auto; width: 100%; margin: 0 0 16px; padding-bottom: 4px; text-align: left; scroll-behavior: smooth; }
.welcome-trips::-webkit-scrollbar { display: none; }
/* Desktop (mouse, no touch-swipe) needs a visible affordance + drag target —
   the JS in index.html also maps vertical wheel → horizontal scroll. (Cory, 6/13) */
@media (pointer: fine) {
  .welcome-trips { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
  .welcome-trips::-webkit-scrollbar { display: block; height: 7px; }
  .welcome-trips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
  .welcome-trips:hover::-webkit-scrollbar-thumb { background: var(--text-3); }
  .welcome-trips::-webkit-scrollbar-track { background: transparent; }
}
.wt-card { flex: 0 0 auto; min-width: 170px; max-width: 210px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px; cursor: pointer; transition: border-color .15s; }
.wt-card:hover { border-color: var(--accent); }
.wt-title { font-size: 12.5px; font-weight: 700; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wt-status { font-size: 11px; color: var(--accent); font-weight: 600; margin-top: 3px; }
.wt-when { font-size: 11px; color: var(--text-3); margin-top: 1px; }
.wt-card.wt-photo { background-size: cover; background-position: center; border-color: transparent; min-height: 76px; display: flex; flex-direction: column; justify-content: flex-end; }
.wt-card.wt-photo .wt-title { color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.5); }
.wt-card.wt-photo .wt-status { color: #ffd9b8; text-shadow: 0 1px 2px rgba(0,0,0,.5); }
.wt-card.wt-photo .wt-when { color: rgba(255,255,255,.85); text-shadow: 0 1px 2px rgba(0,0,0,.5); }
/* "Add yours" — on a finished trip whose picture is the trip product's rather
   than the traveller's, and on one with no picture at all. It is the honest
   label for a stock photograph AND the ask the app most needs: 1,198 real trip
   photographs exist and none are publishable, because nobody was ever asked. */
.wt-ask { display: flex; align-items: center; gap: 4px; margin-top: 5px; font-size: 10.5px; font-weight: 600; color: var(--text-3); }
.wt-ask svg { width: 12px; height: 12px; flex: 0 0 auto; }
.wt-card.wt-photo .wt-ask { color: rgba(255,255,255,.8); text-shadow: 0 1px 2px rgba(0,0,0,.5); }
.wt-card:hover .wt-ask { color: var(--accent); }
.wt-card.wt-photo:hover .wt-ask { color: #ffd9b8; }
/* A borrowed picture sits back a little, so a real one always reads as the
   brighter card on the strip. */
.wt-card.wt-stock { filter: saturate(.82); }
.wt-card.wt-stock:hover { filter: none; }
.welcome-starter {
  display: flex; align-items: center; gap: 12px; background: var(--bg-hover); border: 1px solid var(--border);
  padding: 12px 16px; border-radius: 14px; cursor: pointer; transition: all 0.15s;
  font-family: inherit; color: var(--text); font-size: 0.88rem; line-height: 1.3;
}
.welcome-starter-icon { font-size: 1.3rem; flex-shrink: 0; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: var(--bg-hover); border-radius: 10px; }
/* The tile now holds an SVG, not an emoji. Ember, so the marks read as one set
   with the rest of the app instead of four grey glyphs. */
.welcome-starter-icon svg { color: var(--accent); display: block; }
.welcome-starter-text { flex: 1; }
.welcome-starter-label { color: var(--text-3); font-size: 0.75rem; margin-top: 2px; }
/* A tile that DOES something reads differently from one that asks something.
   The tiles are how people learn what Lore is, and until now every one of them
   was a question — so the whole teaching surface said "he answers". Marked with
   the ember rather than a badge: quiet enough not to shout on a home screen,
   distinct enough that the two kinds are obviously two kinds. (10 Sep) */
.welcome-starter.is-do { border-color: var(--green-border, var(--accent)); }
.welcome-starter.is-do .welcome-starter-icon { background: var(--green-bg, var(--bg-2)); }
.welcome-starter.is-do .welcome-starter-label { color: var(--accent); font-weight: 600; }
.welcome-starter.is-do .welcome-starter-label::before {
  content: ''; display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent); margin-right: 6px; vertical-align: 1px;
}
.suggestions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; padding: 0 4px; }
.suggestion-chip {
  background: var(--green-bg); border: 1px solid var(--green-border); color: var(--accent);
  padding: 5px 12px; border-radius: 16px; font-size: 0.8rem; cursor: pointer; transition: all 0.15s; font-family: inherit;
}

/* ═══ Home View (operator dashboard) ═══ */
#home-view { display:none; overflow-y:auto; overflow-x:hidden; background:var(--bg); position:relative; }
#home-view.active { display:flex; flex-direction:column; flex:1; min-height:0; }
#home-view.active ~ #messages { display:none !important; }
#home-view.active ~ #input-area { flex-shrink:0; }
/* input-area stays visible — tap to chat, mic to talk */
.hv-wrap { max-width:940px; margin:0 auto; padding:20px 16px 80px; position:relative; z-index:1; }
/* Mobile feed pills on the home (Cory 7/9) — same switcher as the desktop
   sidebar; hidden on desktop where the sidebar carries it. */
#hv-feed-pills { display:none; gap:6px; margin:8px 12px 2px; }
#hv-feed-pills button { flex:1; font-size:11px; font-weight:700; padding:7px 4px; border-radius:12px; border:1px solid var(--border); background:transparent; color:var(--text-3); cursor:pointer; white-space:nowrap; }
/* STAFF ONLY. These open the staff comms rail — "Entire Feed" is the whole
   company's — so `body.oi-staff` (set in renderSmartWelcome, after the view-as
   role override) is required. Without it every client on a phone saw them. */
@media (max-width:767px) { body.oi-staff #hv-feed-pills { display:flex; } }
/* Ember avatar chip (Cory 7/9: always the ember, never the letter L) */
.ws-avatar-ember { background:#fff !important; border:1px solid var(--border); display:flex; align-items:center; justify-content:center; }
/* Phones: home content goes wider + "Your day" becomes a peek-swipe
   carousel (Cory 7/9) — card edges are the swipe affordance. */
@media (max-width:767px) {
  /* Full-width phone home (Cory 7/9 device test): kill the double gutters */
  #messages { padding: 12px 8px; }
  #chat-screen #messages { padding-left: 8px; padding-right: 8px; }
  .welcome-msg { padding: 10px 2px; }
  .welcome-smart .ws-bubble { padding: 11px 13px; }
  .hv-wrap { padding:12px 8px 70px; }
  /* Task edit caret: a 13px icon is un-tappable on phones (Kyle 7/9) */
  .oit-edit-btn { padding: 8px 10px; opacity: .85; }
  #welcome-dispatch { display:flex !important; overflow-x:auto; scroll-snap-type:x mandatory; gap:10px; scrollbar-width:none; -webkit-overflow-scrolling:touch; padding-bottom:4px; }
  #welcome-dispatch::-webkit-scrollbar { display:none; }
  #welcome-dispatch > * { flex:0 0 86%; scroll-snap-align:start; min-width:0; }
  #welcome-dispatch[style*="display: none"], #welcome-dispatch[style*="display:none"] { display:none !important; }
}
.hv-topo { position:absolute; top:0; left:0; right:0; height:100%; pointer-events:none; z-index:0; opacity:0.9; }
.hv-topo line, .hv-topo path, .hv-topo ellipse { stroke: var(--accent); opacity:0.1; }
.hv-briefing { background:var(--bg-hover); border:1px solid var(--border); border-radius:var(--radius); padding:18px 20px; margin-bottom:20px; }
.hv-briefing-head { display:flex; align-items:center; gap:10px; margin-bottom:12px; }
.hv-briefing-head h3 { font-family:var(--font-display); font-size:13px; font-weight:600; margin:0; }
.hv-briefing-head span { font-size:10px; color:var(--text-3); }
.hv-briefing-orb { position:relative; width:24px; height:24px; flex-shrink:0; }
.hv-briefing-text { font-size:14px; line-height:1.65; color:var(--text); }
.hv-cursor { color:var(--accent); animation:pulse 0.8s ease infinite; }
.hv-chips { display:flex; gap:6px; margin-top:12px; flex-wrap:wrap; }
.hv-chip { padding:5px 12px; border-radius:20px; border:1px solid var(--border); font-size:11px; color:var(--text-3); cursor:pointer; background:none; font-family:var(--font-sans); transition:all 0.2s; }
.hv-section-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
.hv-section-head h3 { font-family:var(--font-display); font-size:14px; font-weight:600; margin:0; }
.hv-section-head .hv-count { margin-left:8px; font-size:11px; font-family:var(--font-sans); font-weight:500; color:var(--red); background:color-mix(in srgb, var(--red) 12%, transparent); padding:2px 8px; border-radius:10px; }
.hv-section-head a { font-size:11px; color:var(--text-3); text-decoration:none; }
.hv-priorities { display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-bottom:20px; }
.hv-pcard { background:var(--bg-card); border-radius:var(--radius); border:1px solid var(--border); padding:14px 16px; display:flex; flex-direction:column; gap:6px; position:relative; overflow:hidden; cursor:pointer; transition:border-color 0.2s; }
.hv-pcard-bar { position:absolute; left:0; top:0; bottom:0; width:3px; border-radius:var(--radius) 0 0 var(--radius); }
.hv-pcard-top { display:flex; align-items:center; gap:10px; }
.hv-pcard-icon { flex-shrink:0; color:var(--text-3); }
.hv-pcard-head { flex:1; min-width:0; }
.hv-pcard-urgency { font-size:9px; font-weight:500; text-transform:uppercase; letter-spacing:0.08em; margin-bottom:2px; }
.hv-pcard-title { font-size:13px; font-weight:500; }
.hv-pcard-sub { font-size:11px; color:var(--text-3); line-height:1.4; padding-left:28px; }
.hv-pcard-actions { flex-shrink:0; }
.hv-pcard-btn { padding:5px 12px; border-radius:5px; background:var(--accent-fill); color:var(--accent-on); font-size:11px; font-weight:600; border:none; cursor:pointer; white-space:nowrap; font-family:var(--font-sans); }
.hv-mid { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-bottom:20px; }
.hv-feed { background:var(--bg-card); border-radius:var(--radius); border:1px solid var(--border); padding:16px; }
.hv-feed-tabs { display:flex; gap:0; border-radius:6px; overflow:hidden; border:1px solid var(--border); }
.hv-feed-tab { padding:4px 10px; font-size:10px; font-weight:500; background:none; border:none; color:var(--text-3); cursor:pointer; font-family:var(--font-sans); }
.hv-feed-tab.active { background:var(--bg-hover); color:var(--accent); }
.hv-feed-list { max-height:300px; overflow-y:auto; }
.hv-feed-item { display:flex; gap:10px; align-items:flex-start; padding:10px 0; border-bottom:1px solid var(--bg-hover); }
.hv-feed-icon { width:28px; height:28px; border-radius:6px; display:flex; align-items:center; justify-content:center; flex-shrink:0; background:var(--bg-hover); }
.hv-feed-icon.hl { background:var(--green-bg); }
.hv-feed-text { font-size:12px; line-height:1.45; }
.hv-feed-time { font-size:10px; color:var(--text-3); margin-top:2px; }
.hv-qa-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-bottom:14px; }
.hv-contact { background:var(--bg-card); border-radius:8px; border:1px solid var(--border); padding:10px 14px; cursor:pointer; transition:border-color 0.2s; }
.hv-contact-top { display:flex; align-items:center; gap:8px; margin-bottom:4px; }
.hv-avatar { width:28px; height:28px; border-radius:50%; background:var(--bg-panel); display:flex; align-items:center; justify-content:center; font-size:11px; font-weight:600; color:var(--text-3); }
.hv-contact-name { font-size:12px; font-weight:500; }
.hv-contact-role { font-size:10px; color:var(--text-3); }
.hv-contact-status { font-size:9px; font-weight:500; text-transform:uppercase; letter-spacing:0.06em; margin-top:4px; display:flex; align-items:center; gap:4px; }
.hv-followups { background:var(--bg-card); border-radius:var(--radius); border:1px solid var(--border); padding:14px; }
.hv-followups h4 { font-family:var(--font-display); font-size:12px; font-weight:600; margin:0 0 10px; }
.hv-fu-row { display:flex; align-items:center; justify-content:space-between; padding:7px 0; border-bottom:1px solid var(--bg-hover); }
.hv-fu-row:last-child { border:none; }
.hv-fu-left { display:flex; align-items:center; gap:8px; }
.hv-fu-left span { font-size:12px; font-weight:500; }
.hv-fu-time { font-size:10px; color:var(--text-3); }

@keyframes hvFadeUp { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:translateY(0); } }
@keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.4; } }

@media (max-width:767px) {
  .hv-priorities { grid-template-columns:1fr; }
  .hv-mid { grid-template-columns:1fr; }
  .hv-qa-grid { grid-template-columns:1fr 1fr; }
  /* Mobile: stage+button top, name+details below */
  .hv-pcard { padding:10px 12px; gap:4px; }
  .hv-pcard-icon { display:none; }
  .hv-pcard-top { gap:8px; }
  .hv-pcard-head { display:flex; align-items:center; gap:6px; }
  .hv-pcard-urgency { margin-bottom:0; white-space:nowrap; }
  .hv-pcard-title { display:none; }
  .hv-pcard-sub { padding-left:0; }
  .hv-pcard-sub::before { content: attr(data-name); display:block; font-size:13px; font-weight:500; color:var(--text); margin-bottom:2px; }
}

/* Hover states — guarded for touch devices */
@media (hover: hover) {
  .auth-btn:hover { background: var(--accent-hover); }
  .auth-skip a:hover { color: var(--text-2); }
  #notif-bell:hover { color: var(--text); }
  .message.assistant a.oi-link-booking:hover { background: var(--green-border); }
  .message.assistant a.oi-link-action:hover { background: var(--green-bg); border-color: var(--accent); }
  .booking-link:hover { color: var(--orange); text-decoration-style: solid; }
  .hv-chip:hover { border-color: var(--accent); color: var(--accent); }
  .hv-pcard:hover { border-color: var(--accent); }
  .hv-contact:hover { border-color: var(--accent); }
  .welcome-starter:hover, .welcome-starter:active { background: var(--green-bg); border-color: var(--green-border); transform: translateY(-1px); }
  .suggestion-chip:hover { border-color: var(--accent); }
}

/* ═══ Unassigned Lead Assign (home priority cards) ═══ */
.hv-assign-wrap { display:flex; flex-direction:column; gap:4px; align-items:flex-end; }
.hv-assign-select {
  background: var(--bg); border: 1px solid var(--border); border-radius: 5px;
  color: var(--text); font-size: 11px; padding: 4px 6px; font-family: var(--font-sans);
  cursor: pointer; max-width: 130px;
}
.hv-assign-select:focus { border-color: var(--accent); outline: none; }
.hv-assign-confirm {
  padding: 4px 10px; border-radius: 5px; background: var(--accent-fill); color: var(--accent-on);
  font-size: 10px; font-weight: 600; border: none; cursor: pointer; font-family: var(--font-sans);
  white-space: nowrap; transition: opacity 0.15s;
}
.hv-assign-confirm:disabled { opacity: 0.4; cursor: not-allowed; }
.hv-pcard-assigned {
  background: color-mix(in srgb, var(--green) 8%, var(--bg-card));
  border-color: var(--green-border); transition: all 0.3s;
}
.hv-pcard-assigned .hv-pcard-bar { background: var(--green) !important; }

/* ═══ Home Lead Detail Overlay ═══ */
#hv-lead-overlay {
  display: none; position: fixed; inset: 0; z-index: 1102;
  background: rgba(0,0,0,0.4); transition: background 0.25s ease;
}
#hv-lead-overlay.open { display: block; }
@media (min-width: 768px) { #hv-lead-overlay { left: var(--oi-rail-w, 72px); } }
#hv-lead-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: 56%; max-width: 640px; min-width: 360px;
  background: var(--bg-panel); border-left: 1px solid var(--border-2);
  box-shadow: -4px 0 24px rgba(0,0,0,0.3);
  overflow-y: auto; animation: slideRight 0.25s ease-out;
}
@media (max-width: 767px) {
  #hv-lead-panel { width: 100%; max-width: none; min-width: 0; }
}
@keyframes slideRight { from { transform: translateX(40px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
.hvl-close {
  position: absolute; top: 14px; right: 14px; background: none; border: none;
  color: var(--text-3); font-size: 20px; cursor: pointer; z-index: 10; padding: 4px 8px; border-radius: 6px; line-height: 1;
}
.hvl-header { padding: 20px 24px 16px; border-bottom: 1px solid var(--border); }
.hvl-created { font-size: 11px; color: var(--text-4); margin-top: 4px; }
.hvl-identity { display: flex; align-items: center; gap: 14px; margin-top: 12px; }
.hvl-avatar {
  width: 44px; height: 44px; border-radius: 50%; background: var(--bg-hover);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  font-size: 15px; font-weight: 700; color: var(--text-2);
}
.hvl-identity-info { flex: 1; min-width: 0; }
.hvl-name { font-family: var(--font-display); font-size: 20px; font-weight: 700; line-height: 1.2; }
.hvl-contact-links { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 4px; }
.hvl-contact-link {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; color: var(--text-3); text-decoration: none;
}
.hvl-assigned { font-size: 12px; color: var(--text-4); margin-top: 10px; }
.hvl-meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.hvl-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; padding: 3px 10px; border-radius: 12px;
  background: var(--bg-hover); color: var(--text-2); border: 1px solid var(--border);
}
.hvl-booking { font-size: 11px; font-weight: 600; color: var(--text-3); font-family: var(--font-mono, monospace); letter-spacing: 0.04em; }
.hvl-section { padding: 16px 24px; border-bottom: 1px solid var(--border); }
.hvl-section-title { font-size: 11px; font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 8px; }
.hvl-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; }
.hvl-label { font-size: 12px; color: var(--text-3); }
.hvl-value { font-size: 13px; font-weight: 500; }
.hvl-inquiry { font-size: 13px; line-height: 1.6; color: var(--text-2); background: var(--bg-hover); border-radius: 8px; padding: 12px 14px; margin-top: 6px; white-space: pre-wrap; }
.hvl-assign-section { padding: 20px 24px; }
.hvl-assign-row { display: flex; gap: 8px; align-items: center; }
.hvl-assign-row select {
  flex: 1; padding: 10px 12px; background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; color: var(--text); font-size: 14px; font-family: var(--font-sans);
}
.hvl-assign-row select:focus { border-color: var(--accent); outline: none; }
.hvl-assign-row button {
  padding: 10px 20px; background: var(--accent-fill); color: var(--accent-on); border: none; border-radius: 8px;
  font-size: 14px; font-weight: 600; cursor: pointer; font-family: var(--font-sans); transition: 0.15s;
  white-space: nowrap;
}
.hvl-assign-row button:disabled { opacity: 0.4; cursor: not-allowed; }
.hvl-actions { padding: 12px 24px 24px; display: flex; gap: 8px; }
.hvl-link {
  font-size: 12px; color: var(--text-3); text-decoration: none; padding: 6px 12px;
  border: 1px solid var(--border); border-radius: 6px; transition: 0.15s;
}
@media (hover: hover) {
  .hvl-close:hover { color: var(--text); background: var(--border); }
  .hvl-contact-link:hover { color: var(--accent); }
  .hvl-link:hover { color: var(--accent); border-color: var(--accent); }
  .hvl-assign-row button:hover:not(:disabled) { background: var(--accent-hover); }
}

/* ═══ AI Research Items (lead panel) ═══ */
.hvl-research-item {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; margin-bottom: 6px; border-radius: 8px;
  background: var(--bg-hover); font-size: 12px; line-height: 1.5;
}
.hvl-research-icon { flex-shrink: 0; font-size: 14px; margin-top: 1px; }
.hvl-research-match { background: color-mix(in srgb, var(--blue) 8%, transparent); border: 1px solid color-mix(in srgb, var(--blue) 20%, transparent); }
.hvl-research-warning { background: color-mix(in srgb, var(--red) 8%, transparent); border: 1px solid color-mix(in srgb, var(--red) 20%, transparent); }
.hvl-research-suggestion { background: color-mix(in srgb, var(--green) 8%, transparent); border: 1px solid color-mix(in srgb, var(--green) 20%, transparent); }

/* ═══ Home Lead Overlay + Comms Panel Sync ═══ */

/* ═══ Lead Panel Stage Select ═══ */
.hvl-stage-select {
  appearance: none; -webkit-appearance: none;
  background: var(--bg); border: 1px solid currentColor; border-radius: 12px;
  color: inherit; font-size: 11px; font-weight: 600; padding: 3px 24px 3px 10px;
  font-family: var(--font-sans); cursor: pointer; transition: 0.15s;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none' stroke='%238b949e' stroke-width='1.5'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center;
}
.hvl-stage-select:focus { outline: none; box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 20%, transparent); }
.hvl-stage-select option { background: var(--bg-card); color: var(--text); }

/* ═══ Danger Zone (Spam + Delete) ═══ */
.hvl-danger {
  display: flex; gap: 8px; padding: 16px 24px 24px;
  border-top: 1px solid var(--border);
}
.hvl-danger-btn {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 16px; border-radius: 8px; font-size: 13px; font-weight: 500;
  cursor: pointer; font-family: var(--font-sans); transition: 0.15s; border: 1px solid;
}
.hvl-spam-btn { background: none; border-color: var(--orange); color: var(--orange); }
.hvl-delete-btn { background: none; border-color: var(--red); color: var(--red); }
.hvl-danger-btn:disabled { opacity: 0.4; cursor: not-allowed; }
@media (hover: hover) {
  .hvl-spam-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--orange) 10%, transparent); }
  .hvl-delete-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--red) 10%, transparent); }
}

/* ═══ Lead Panel Action Bar (Acknowledge + Reassign) ═══ */
.hvl-action-bar {
  display: flex; gap: 8px; padding: 16px 24px;
  border-bottom: 1px solid var(--border);
}
.hvl-action-btn {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 16px; border-radius: 8px; font-size: 14px; font-weight: 600;
  cursor: pointer; font-family: var(--font-sans); transition: 0.15s; border: none;
}
.hvl-ack-btn { background: var(--accent); color: var(--bg); }
.hvl-ack-btn:disabled { cursor: not-allowed; }
.hvl-ack-done { background: var(--green); pointer-events: none; }
.hvl-reassign-btn { background: var(--bg-hover); color: var(--text-2); border: 1px solid var(--border); }
.hvl-reassign-btn:disabled { opacity: 0.6; cursor: not-allowed; }
@media (hover: hover) {
  .hvl-ack-btn:hover:not(:disabled):not(.hvl-ack-done) { filter: brightness(1.1); }
  .hvl-reassign-btn:hover:not(:disabled) { background: var(--border); color: var(--text); }
}

/* ═══ Priority Card Inquiry Snippet ═══ */
.hv-pcard-snippet {
  margin-top: 4px; font-size: 11px; color: var(--text-4);
  font-style: italic; line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}

/* ═══ Global Avatar (OiChat.avatar) ═══ */
.oi-avatar-g { background: var(--surface-3, #2a2a35); color: var(--text-3, #a0a0a8); letter-spacing: 0.3px; }
.oi-avatar-g.oi-avatar-header { background: linear-gradient(135deg, var(--accent), #148f3f); color: #fff; }
[data-theme="light"] .oi-avatar-g { background: var(--surface-3, #e8e8ed); color: var(--text-3, #666); }
[data-theme="light"] .oi-avatar-g.oi-avatar-header { background: linear-gradient(135deg, var(--accent), #148f3f); color: #fff; }

/* ═══ Comms Panel v2 — Filter Tabs ═══ */
/* Contact header — enriched with details */
.oi-contact-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--oi-border, var(--surface2));
  background: var(--oi-bg, var(--bg));
  flex-shrink: 0;
}

.oi-filter-tabs {
  display: flex; border-top: 1px solid var(--oi-border); flex-shrink: 0;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; /* Firefox */
}
.oi-filter-tabs::-webkit-scrollbar { display: none; }
.oi-filter-tab {
  flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 3px;
  padding: 7px 4px; font-size: 11px; font-weight: 600; border: none; cursor: pointer;
  background: var(--oi-surface-2); color: var(--oi-text-3); white-space: nowrap;
  transition: all .15s; position: relative; border-bottom: 2px solid transparent;
}
.oi-filter-tab.active {
  background: var(--oi-surface); color: var(--accent); border-bottom-color: var(--accent);
}
.oi-filter-tab.disabled {
  opacity: 0.35; pointer-events: none; cursor: default;
}
.oi-filter-tab:not(.active):not(.disabled):hover {
  background: var(--oi-surface); color: var(--oi-text-2);
}
.oi-filter-tab-icon { display: flex; align-items: center; flex-shrink: 0; }
.oi-filter-tab-badge {
  font-size: 9px; font-weight: 700; background: var(--accent-fill); color: var(--accent-on);
  border-radius: 8px; padding: 0 5px; min-width: 14px; text-align: center;
  line-height: 14px; margin-left: 2px;
}

/* ═══ Comms Panel v2 — Read/Unread Email Indicators ═══ */
.oi-email-unread-dot {
  width: 7px; height: 7px; border-radius: 50%; background: #3b82f6;
  flex-shrink: 0; display: inline-block;
}
.oi-email-bubble:hover { filter: brightness(1.08); }

/* ═══ Comms Panel v2 — Email Detail Panel ═══ */
.oi-email-detail-panel {
  display: none; flex-direction: column; width: 400px; max-width: 100%;
  background: var(--oi-bg, #0f1117); border-left: 1px solid var(--oi-border);
  flex-shrink: 0; overflow: hidden;
}
@media (max-width: 767px) {
  .oi-email-detail-panel { background: #fff; }
  .oi-email-detail-header { background: #fff !important; }
}
/* When used as L2 push panel, fill all remaining space */
.oi-email-detail-panel.oi-l2-panel {
  flex: 1; width: auto; min-width: 0; overflow: hidden;
}
.oi-email-detail-panel.oi-l2-panel * {
  box-sizing: border-box;
}
/* Email thread view — expand to fill full content area (hide folder list, take full width) */
/* comms-email-thread-open: positioning handled via inline JS styles */
.oi-email-detail-panel.open { display: flex; }
.oi-email-detail-header {
  display: flex; align-items: stretch; justify-content: flex-start;
  padding: 10px 14px; border-bottom: 1px solid var(--oi-border);
  background: var(--oi-bg); flex-shrink: 0;
}
@media (max-width: 767px) {
  .oi-email-detail-header { border-bottom: none; }
  /* Subject row smaller on mobile */
  #oi-email-thread-subject { font-size: 15px !important; }
  /* Attachment pills in thread view don't overflow sender row */
  .oi-msg-attach { position: static !important; overflow: visible; }
}
.oi-email-detail-header .oi-edp-close {
  background: none; border: none; color: var(--oi-text-3); cursor: pointer;
  font-size: 18px; padding: 2px 6px; line-height: 1; transition: color .15s;
}
.oi-email-detail-header .oi-edp-close:hover { color: var(--oi-text); }
.oi-email-detail-header .oi-edp-reply {
  background: none; border: 1px solid var(--accent); border-radius: 8px;
  color: var(--accent); cursor: pointer; font-size: 12px; font-weight: 600;
  padding: 4px 12px; transition: all .15s; display: flex; align-items: center; gap: 4px;
}
.oi-email-detail-header .oi-edp-reply:hover { background: var(--accent-fill); color: var(--accent-on); }
.oi-email-detail-body { flex: 1; overflow-y: auto; min-height: 0; }

/* Email search pill — Gmail-style rounded grey input that's actually visible.
   Always shows the focused styling so the field is obvious at rest. */
.oi-email-search-row { display: flex; align-items: center; gap: 12px; }
.oi-email-search-pill {
  display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;
  background: var(--oi-bg-panel, var(--oi-surface));
  border: 1px solid var(--accent, #1a73e8);
  border-radius: 24px; padding: 8px 14px;
  color: var(--oi-text);
  box-shadow: 0 1px 6px rgba(0,0,0,0.15);
}
.oi-email-search-pill svg { color: var(--accent, #1a73e8); flex-shrink: 0; }
.oi-email-search-pill input { color: var(--oi-text) !important; font-size: 14px; }
.oi-email-search-pill input::placeholder { color: var(--oi-text-2); }
[data-theme="light"] .oi-email-search-pill {
  background: #fff; border-color: #1a73e8; box-shadow: 0 1px 6px rgba(32,33,36,0.12);
}
.oi-email-detail .oi-email-thread-item:hover { background: var(--oi-surface) !important; }

/* Mobile: full-screen email detail */
@media (max-width: 700px) {
  .oi-email-detail-panel {
    position: fixed; top: 0; left: 0; bottom: 0; width: 100%;
    border-left: none; z-index: 1200;
  }
  .oi-email-detail-header { padding: 8px 12px; }
}

/* Light theme overrides */
[data-theme="light"] .oi-filter-tab { background: #f5f5f5; color: #888; }
[data-theme="light"] .oi-filter-tab.active { background: #fff; color: var(--accent); }
[data-theme="light"] .oi-filter-tab:not(.active):not(.disabled):hover { background: #fff; color: #555; }
[data-theme="light"] .oi-email-detail-panel { background: #fff; }
[data-theme="light"] .oi-email-detail .oi-email-thread-item:hover { background: #f0f0f0 !important; }

/* ═══════════════════════════════════════════════════════════════
   TASK MODULE (tasks-ui.js)
   ═══════════════════════════════════════════════════════════════ */
/* Global section-title look (matches .ov-section-title): QUICK COMMS text style
   + full-width ember underline on the header row, on every page. (Cory 6/19) */
.oit-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:12px; padding-bottom:6px; border-bottom:2px solid var(--accent); }
.oit-header-title { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:1px; color:var(--text-2); display:inline-block; }
.oit-count { font-size:11px; color:var(--text-4); font-weight:400; }
/* Sidebar tasks panel: run the ember underline the full panel width. The footer
   carries 12px side padding, so bleed the header out by that much; the title and
   "+" stay inset via the re-added padding. (Cory 6/22) */
#oi-cp-tasks-footer .oit-header { margin-left:-12px; margin-right:-12px; padding-left:12px; padding-right:12px; }

/* Task list */
.oit-list { min-height:20px; margin-bottom:12px; }

/* Individual task row */
.oit-row { display:flex; align-items:flex-start; gap:10px; padding:10px 0; border-bottom:1px solid var(--border); cursor:pointer; }
.oit-row:last-child { border-bottom:none; }
.oit-check { flex-shrink:0; margin-top:2px; width:18px; height:18px; border-radius:50%; border:1.5px solid var(--border-2,#555); background:transparent; cursor:pointer; padding:0; color:#fff; font-size:10px; line-height:1.8; text-align:center; transition:border-color .15s, background .15s; }
.oit-check.done, .oit-check.oit-check-done { background:var(--accent); border-color:var(--accent); }
.oit-row-body { flex:1; min-width:0; }
.oit-row-title { font-weight:600; font-size:13px; line-height:1.3; color:var(--text); }
.oit-row-title.done, .oit-row-title.oit-done { text-decoration:line-through; color:var(--text-4); }
.oit-row-title.pri-urgent, .oit-row-title.oit-pri-urgent { color:#dc2626; }
.oit-row-title.pri-high,   .oit-row-title.oit-pri-high   { color:#ea580c; }
.oit-row-title.pri-low,    .oit-row-title.oit-pri-low    { color:var(--text-4); }
.oit-row-notes { font-size:11px; color:var(--text-4); margin-top:3px; line-height:1.4; }
.oit-del { flex-shrink:0; background:none; border:none; color:var(--text-3); cursor:pointer; font-size:14px; padding:2px 6px; opacity:.55; transition:opacity .15s, color .15s; }
.oit-del:hover { opacity:1; color:var(--text-1); }
/* Edit caret (replaces the snooze clock) — opens the inline editor. (Cory 6/23) */
.oit-edit-btn { flex-shrink:0; background:none; border:none; color:var(--text-3); cursor:pointer; padding:2px 5px; opacity:.6; transition:opacity .15s, color .15s; display:inline-flex; align-items:center; margin-top:1px; }
.oit-edit-btn:hover { opacity:1; color:var(--accent); }
.oit-row.oit-row-editing .oit-edit-btn { display:none; }
/* Two-line context: primary client + trip on their own lines (no truncation). */
.oit-row-client { font-weight:500; color:var(--text-3,#9aa0a6); }
.oit-row-trip { white-space:normal; }
/* Native date input: color-scheme tells the browser to render the picker glyph
   AND the mm/dd/yyyy text in theme-appropriate contrast — the invert filter was
   unreliable. App default is dark. (Cory 6/23) */
.oit-date-input { color-scheme: dark; }
[data-theme="light"] .oit-date-input { color-scheme: light; }
[data-theme="dark"] .oit-date-input { color-scheme: dark; }
.oit-date-input::-webkit-calendar-picker-indicator { cursor:pointer; opacity:.9; }

/* Due date chip */
.oit-due { font-size:10px; margin-left:8px; padding:1px 6px; border-radius:3px; display:inline-flex; align-items:center; vertical-align:middle; }
.oit-due.overdue { font-weight:700; color:#dc2626; background:rgba(220,38,38,.1); }
.oit-due.today { font-weight:700; color:var(--accent); background:rgba(201,122,58,.1); }
.oit-due.upcoming { font-weight:400; color:var(--text-3,#aaa); background:transparent; }

/* Assignee chip */
.oit-assignee-chip { font-size:10px; padding:1px 6px; border-radius:10px; background:var(--bg-3,#333); color:var(--text-4); margin-left:6px; display:inline-flex; align-items:center; vertical-align:middle; }

/* Lore badge */
.oit-lore { font-size:9px; color:var(--accent); margin-right:4px; display:inline-flex; align-items:center; vertical-align:middle; }

/* Booking number suffix */
.oit-bn { font-size:11px; color:var(--text-4); font-weight:400; margin-left:5px; }

/* Delete confirm */
.oit-del-confirm { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:8px 12px; background:rgba(220,38,38,.1); border:1px solid rgba(220,38,38,.25); border-radius:6px; margin:2px 0; font-size:12px; color:var(--text); }
.oit-del-confirm-msg { color:#f87171; }
.oit-del-no { font-size:11px; padding:4px 12px; border-radius:5px; border:1px solid var(--border); background:var(--bg-card); color:var(--text); cursor:pointer; }
.oit-del-yes { font-size:11px; padding:4px 12px; border-radius:5px; border:none; background:#dc2626; color:#fff; cursor:pointer; font-weight:600; }

/* Inline edit row */
.oit-edit-row { padding:12px; background:var(--bg-2,#181818); border:1px solid var(--border); border-radius:8px; margin:4px 0; display:flex; flex-direction:column; gap:10px; }
.oit-edit-row input[type="text"],
.oit-edit-row textarea { background:transparent; border:none; border-bottom:1px solid var(--border); padding:4px 0; color:var(--text); width:100%; outline:none; font-family:inherit; }
.oit-edit-row textarea { resize:vertical; background:var(--bg-card); border:1px solid var(--border); border-radius:6px; padding:8px; line-height:1.5; box-sizing:border-box; font-family:inherit; color:var(--text); font-size:12px; }
.oit-edit-row select, .oit-edit-row input[type="date"] { font-size:12px; background:var(--bg-card); border:1px solid var(--border); color:var(--text); border-radius:6px; padding:6px 8px; font-family:inherit; }
.oit-edit-title { font-size:13px; font-weight:600; }
.oit-ctx-chips { display:flex; flex-wrap:wrap; gap:4px; margin-bottom:2px; }
.oit-ctx-chip { font-size:10px; padding:2px 8px; border-radius:10px; background:var(--bg-3,#2a2a2a); color:var(--text-4); display:inline-flex; align-items:center; gap:3px; }
.oit-ctx-chip-link { cursor:pointer; transition:background .15s, color .15s; }
.oit-ctx-chip-link:hover { background:var(--accent-fill); color:var(--accent-on); }
.oit-assigned-by { font-size:11px; color:var(--text-4); display:flex; align-items:center; gap:4px; }
.oit-edit-actions { display:flex; justify-content:flex-end; gap:8px; }
.oit-edit-cancel { font-size:12px; padding:6px 14px; border-radius:6px; border:1px solid var(--border); background:transparent; color:var(--text-4); cursor:pointer; }
.oit-edit-save { font-size:12px; padding:6px 16px; border-radius:6px; border:none; background:var(--accent,#c97a3a); color:#fff; cursor:pointer; font-weight:600; font-family:inherit; }

/* Add trigger */
.oit-add-trigger { cursor:pointer; display:flex; align-items:center; gap:8px; padding:10px 14px; border:1px dashed var(--border); border-radius:8px; color:var(--text-4); font-size:13px; transition:border-color .15s, color .15s; }
.oit-add-trigger:hover { border-color:var(--accent); color:var(--accent); }

/* Add form */
.oit-form { display:none; background:var(--bg-2,#181818); border:1px solid var(--border); border-radius:10px; padding:14px; flex-direction:column; gap:10px; margin-top:6px; }
.oit-form.open { display:flex; }
.oit-form input[type="text"],
.oit-form textarea { font-family:var(--font-sans); color:var(--text); width:100%; box-sizing:border-box; outline:none; font-size:12px; }
.oit-input { font-size:13px; font-weight:600; background:transparent; border:none; border-bottom:1px solid var(--border); padding:4px 0; }
.oit-notes, .oit-notes-inp { font-size:12px; resize:vertical; background:var(--bg-card); border:1px solid var(--border); border-radius:6px; padding:8px; line-height:1.5; font-family:var(--font-sans); color:var(--text); }
.oit-form select,
.oit-form input[type="date"] { font-size:12px; background:var(--bg-card); border:1px solid var(--border); color:var(--text); border-radius:6px; padding:6px 8px; font-family:inherit; }
.oit-form-row { display:flex; gap:8px; flex-wrap:wrap; }
.oit-form-row > * { flex:1; min-width:110px; }
/* Entity context line under the task title in non-entity-scoped views
   (inbox / comms / global). Tight grey one-liner that survives long
   trip titles via ellipsis. Click → opens the linked lead / contact /
   company so the consultant lands in full context. */
.oit-row-ctx { font-size:11px; color:var(--text-4); margin-top:2px; line-height:1.3; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.oit-row-ctx-link { cursor:pointer; transition:color .12s; }
.oit-row-ctx-link:hover { color:var(--accent); }
.oit-assignee-row { display:flex; gap:8px; align-items:center; min-width:0; }
.oit-assignee-label { font-size:11px; color:var(--text-4); white-space:nowrap; display:flex; align-items:center; gap:3px; }
/* Constrain the assignee dropdown so long staff names don't push the
   select past the card edge. */
.oit-assignee-row select { flex:1; min-width:0; max-width:100%; }
.oit-form-actions { display:flex; justify-content:space-between; align-items:center; }
.oit-cancel-btn { font-size:12px; padding:6px 14px; border-radius:6px; border:1px solid var(--border); background:transparent; color:var(--text-4); cursor:pointer; }
.oit-add-btn { font-size:13px; padding:8px 20px; background:var(--accent,#c97a3a); color:#fff; border:none; border-radius:6px; cursor:pointer; font-weight:600; font-family:inherit; }
.oit-error { display:none; font-size:11px; color:#f87171; }

/* Lead search */
.oit-lead-search-wrap { position:relative; }
.oit-lead-search { font-size:12px; width:100%; box-sizing:border-box; background:var(--bg-card); border:1px solid var(--border); color:var(--text); border-radius:6px; padding:6px 8px; font-family:inherit; }
.oit-lead-results { display:none; position:absolute; top:100%; left:0; right:0; background:var(--bg-2,#181818); border:1px solid var(--border); border-radius:6px; max-height:180px; overflow-y:auto; z-index:100; margin-top:2px; }

/* Search results overlay shares the main-content offset with any
   lead/pipeline view. When the comms rail collapses, it slides left to
   match. */
@media (max-width: 767px) {
  #search-results-overlay { left: 0 !important; }
}
.oit-lead-result { padding:8px 12px; cursor:pointer; font-size:12px; border-bottom:1px solid var(--border); }
.oit-lead-result:hover { background:var(--bg-3,#2a2a2a); }
.oit-lead-selected { font-size:11px; color:var(--accent); margin-top:4px; padding:3px 8px; background:rgba(201,122,58,.1); border-radius:4px; display:none; align-items:center; justify-content:space-between; }
.oit-lead-clear { background:none; border:none; color:var(--text-4); cursor:pointer; font-size:13px; padding:0 4px; }

.oit-row.oit-row-editing { opacity:0.5; pointer-events:none; }
.oit-row.oit-row-editing .oit-del { display:none; }
.oit-svg { display:inline-block; vertical-align:middle; margin-right:3px; }
.oit-svg-fire { color:var(--accent); }
.oit-lore-badge { font-size:9px; color:var(--accent); margin-right:4px; display:inline-flex; align-items:center; vertical-align:middle; }
.oit-empty { color:var(--text-4); font-size:12px; padding:4px 0; display:block; }
.oit-loading { color:var(--text-4); font-size:12px; }
.oit-del-btns { display:flex; gap:6px; }
.oit-lead-selected { display:none; font-size:11px; color:var(--accent); margin-top:4px; padding:3px 8px; background:rgba(201,122,58,.1); border-radius:4px; align-items:center; justify-content:space-between; }
.oit-lead-selected.active { display:flex; }

/* ═══════════════════════════════════════════════════════════════
   TOUCH TIMELINE
   ═══════════════════════════════════════════════════════════════ */
.ov-touch-section { padding: 14px 16px 10px; border-top: 1px solid var(--border); }
.ov-touch-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.ov-touch-last { font-size: 11px; }
.touch-row { display: flex; gap: 6px; margin-bottom: 10px; }
.ov-touch-timeline { margin-top: 4px; }
.ov-touch-timeline-list { display: flex; flex-direction: column; gap: 4px; }
.touch-timeline-entry { display: flex; align-items: center; gap: 6px; font-size: 11px; padding: 4px 0; border-bottom: 1px solid var(--border); }
.touch-timeline-entry:last-child { border-bottom: none; }
.touch-tl-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.touch-tl-type { font-weight: 700; font-size: 11px; min-width: 38px; }
.touch-tl-date { margin-left: auto; color: var(--text-4); font-size: 10px; white-space: nowrap; }
.touch-detail { color: var(--text-3); font-size: 11px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.touch-src-badge { font-size: 9px; padding: 1px 5px; border-radius: 4px; font-weight: 600; flex-shrink: 0; }
.touch-src-badge.comms { background: rgba(68,147,248,.12); color: #4493f8; }
.touch-src-badge.manual { background: var(--bg-3, #2a2a2a); color: var(--text-4); }

/* Touch section inline (inside workspace tab) */
.ov-touch-inline { border-top: 1px solid var(--border); }
.ov-touch-inline .ov-touch-section { padding: 14px 20px 10px; }

/* Touch count badge in Last Touch fact */
.touch-count-badge { display:inline-flex; align-items:center; justify-content:center; background:var(--accent-fill); color:var(--accent-on); font-size:9px; font-weight:700; border-radius:8px; padding:1px 5px; margin-left:4px; vertical-align:middle; min-width:16px; }

/* Lore dossier cache age note */
.lore-cache-note { font-size:10px; color:var(--text-4); text-align:right; margin-top:4px; font-style:italic; }

/* ── OiLoreVoice Speak button ─────────────────────────────────────────── */
/* Icon-only since 6/24, so it's a PERFECT circle — the oval pill read as a
   different control than the round send button beside it (Cory 7/11). */
.ofv-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0; border-radius: 50%;
  border: none; cursor: pointer; font-size: 14px; font-weight: 600;
  font-family: var(--font-sans); transition: all .2s;
  background: var(--bg-3, #2a2a2a); color: var(--text);
  white-space: nowrap; flex-shrink: 0;
}
.ofv-btn svg { flex-shrink: 0; }
.ofv-btn span { line-height: 1; }
.ofv-btn:hover { background: var(--bg-2); }

/* Active states */
.ofv-btn.ofv-connecting { background: var(--bg-3); opacity: .7; }
.ofv-btn.ofv-thinking   { background: var(--bg-3); opacity: .7; }
.ofv-btn.ofv-listening  { background: var(--accent-fill); color: var(--accent-on); }
.ofv-btn.ofv-speaking   { background: #4a9e6b; color: #fff; }
.ofv-btn.ofv-error      { background: var(--danger, #c0392b); color: #fff; }

/* Animated waveform bars */
.ofv-wave-anim rect { transform-origin: bottom center; }

/* Light mode */
[data-theme="light"] .ofv-btn { background: var(--accent-fill); color: var(--accent-on); }
[data-theme="light"] .ofv-btn:hover { background: var(--accent); opacity: .85; }
[data-theme="light"] .ofv-btn.ofv-listening { background: var(--accent); }

/* ═══ Circle Comm Picker (global — used on all pages) ═══ */
.ov-ch-bar { display: flex; gap: 8px; padding: 8px 20px 10px; background: var(--bg-card); border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.ov-ch-btn { flex:1; display:inline-flex; flex-direction:row; align-items:center; justify-content:center; gap:6px; padding:8px 4px; border:1px solid var(--border-2); border-radius:10px; background:var(--bg-card); color:var(--text-3); cursor:pointer; font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; transition:background .12s,color .12s,border-color .12s; }
@media (hover:hover) { .ov-ch-btn:hover { background:var(--border); color:var(--text); border-color:var(--accent); } }
.ov-ch-btn.active { background:var(--accent-fill); color:var(--accent-on); border-color:var(--accent); }
.ov-ch-picker { position:relative; background:var(--bg-card); border:1px solid var(--border-2); border-radius:10px; padding:12px; margin-bottom:10px; }
.ov-ch-picker-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
.ov-ch-picker-title { font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--text-3); }
.ov-ch-picker-close { background:none; border:none; color:var(--text-4); cursor:pointer; padding:0; line-height:1; }
.ov-ch-search { width:100%; box-sizing:border-box; background:var(--bg); border:1px solid var(--border-2); border-radius:7px; padding:6px 10px; font-size:13px; color:var(--text); outline:none; margin-bottom:8px; }
.ov-ch-search:focus { border-color:var(--accent); }
.ov-ch-search::placeholder { color:var(--text-5); }
.ov-ch-columns { display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-bottom:10px; }
.ov-ch-col-label { font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--text-4); margin-bottom:4px; }
.ov-ch-list { display:flex; flex-direction:column; gap:2px; max-height:160px; overflow-y:auto; }
.ov-ch-item { display:flex; align-items:center; gap:10px; padding:6px 8px; border-radius:7px; cursor:pointer; transition:background .1s; }
@media (hover:hover) { .ov-ch-item:hover { background:var(--border); } }
.ov-ch-item input[type=checkbox] { width:15px; height:15px; accent-color:var(--accent); cursor:pointer; flex-shrink:0; }
.ov-ch-item-avatar { width:28px; height:28px; border-radius:50%; background:var(--accent-fill); color:var(--accent-on); font-size:11px; font-weight:700; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.ov-ch-item-avatar.operator { background:rgba(201,122,58,.25); color:var(--accent); }
.ov-ch-item-info { flex:1; min-width:0; }
.ov-ch-item-name { font-size:13px; font-weight:500; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ov-ch-item-sub { font-size:11px; color:var(--text-4); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ov-ch-item-ineligible { opacity:.4; cursor:not-allowed; }
.ov-ch-tag { display:inline-block; font-size:9px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; padding:1px 5px; border-radius:4px; margin-left:5px; vertical-align:middle; }
.ov-ch-tag-operator { background:rgba(201,122,58,.15); color:var(--accent); border:1px solid rgba(201,122,58,.3); }
.ov-ch-tag-staff { background:rgba(88,166,255,.12); color:#58a6ff; border:1px solid rgba(88,166,255,.25); }
.ov-ch-apply { width:100%; padding:8px; border-radius:8px; background:var(--accent-fill); color:var(--accent-on); border:none; font-size:13px; font-weight:600; cursor:pointer; transition:opacity .12s; }
.ov-ch-apply:disabled { opacity:.4; cursor:not-allowed; }
.ov-ch-empty { font-size:12px; color:var(--text-4); text-align:center; padding:12px 0; }

/* ═══ Comms L1 Panel ═══ */
.oi-contacts-panel { background:#fff; border-right:1px solid #e0e0e0; }

/* ── THE SIMPLER HOME (flag: oi_home_simple, 19 Sep) ──────────────────────
   Cory: "I think that almost everything (maybe everything) should go away on
   the home page and the Lore chat is up front and center… I'm trying to go
   for simple, clean and intuitive."

   The evidence was already on the page: the greeting ended "…they're in Your
   day, just below" — Lore narrating the thing directly under it. When the
   page's own AI has to tell you what is on the page, the page is not earning
   its space.

   A CLASS, NOT A SECOND HOME PAGE. Every strip, card and starter below is
   built by exactly the code that builds them today; this decides what is
   seen. A second renderer is how the flagged version and the real one drift
   apart, which is the whole period the flag exists to survive. */

/* Gone: the dark hero slab, the block rail, and Your day — the sidebar's
   Tasks section carries the Dispatcher queue AND his written tasks, while
   this carried the queue plus report chases. Two renderings of one queue,
   each missing something the other had. */
html.oi-home-simple #home-hero,
html.oi-home-simple #home-blocks,
html.oi-home-simple #welcome-dispatch-hdr,
html.oi-home-simple #welcome-dispatch,
html.oi-home-simple #welcome-memories-hdr,
html.oi-home-simple #welcome-plans-hdr { display: none !important; }
/* Members/clients on the one home: what needs them shows where staff see Your day (1 Oct). */
/* One home for everybody (Cory, 1 Oct): a member's contract, deposit or
   credits sit inside Today (index.html onRows), never a card of their own. */

/* "Much smaller with just title and countdown, click to open." The status
   line, the photo ask and the picture are what make these cards tall. */
/* A SLIDER, not a wrapped grid. `.home-life .welcome-trips` sets
   flex-wrap:wrap, so the pills and the + stacked down the column instead of
   running along one line — seen live. He asked for a slider with the + on
   the right, and a wrapped one has no right. */
html.oi-home-simple .welcome-trips { gap: 6px; margin: 10px 0 14px; flex-wrap: nowrap !important; overflow-x: auto; justify-content: center; align-self: stretch; }
/* flex:0 0 auto — `.home-life .wt-card` sets `flex: 1 1 100%`, the phone rule
   that makes the full home's cards full width, and it stretched the + into a
   slab while squeezing the trip title to "2026 Guid…". */
/* SMALLER, so the trip and the new-plan chip share one line at 390px
   (Cory: "Plan pills need to be smaller to fit on one line"). */
html.oi-home-simple .wt-card { flex: 0 0 auto; min-width: 0; max-width: 190px; min-height: 0; padding: 5px 10px; border-radius: 999px; background: var(--surface); display: flex; align-items: baseline; gap: 6px; filter: none; }
html.oi-home-simple .wt-card.wt-photo:not(.md-mem .wt-card) { background-image: none !important; border-color: var(--border); }
html.oi-home-simple .wt-status,
html.oi-home-simple .wt-ask { display: none !important; }
html.oi-home-simple .wt-title { font-size: 11.5px; font-weight: 650; color: var(--text-1); text-shadow: none; max-width: 120px; }
html.oi-home-simple .wt-when { font-size: 10.5px; color: var(--text-3); margin: 0; white-space: nowrap; text-shadow: none; }

/* "A + on the right side to start a new one." It is rendered first. */
/* "Should the + Be 'Start new plan +'?" — yes in substance: a bare + beside
   trip pills does not say what it makes. Short, because it shares a line
   with the trips on a 390px screen. */
/* ONE LINE. The card is built `flex-direction: column`, so the + sat ABOVE
   its label — that is the "two lines" Cory is seeing, not the strip
   wrapping (measured at 390px: 362px of content in a 362px box).

   AND IT STAYS PUT. His question: "What happens if there are lots of plans?
   Do they scroll horizontally? *with + new plan staying right aligned?"
   Yes, and yes — sticky to the right edge, because a strip that scrolls
   would carry the create button away exactly when somebody with a lot of
   plans wants it. */
html.oi-home-simple .wt-card[data-first-run="new-plan"] { order: 9; flex: 0 0 auto; min-width: 0; width: auto; max-width: none; padding: 5px 10px; gap: 5px; justify-content: center; align-items: center; flex-direction: row !important; position: sticky; right: 0; }
html.oi-home-simple .wt-card[data-first-run="new-plan"] .wt-title { display: none; }
html.oi-home-simple .wt-card[data-first-run="new-plan"] .wt-newshort { font-size: 11.5px; font-weight: 650; white-space: nowrap; }

/* "A bit smaller and on a rotation." Two at a time; the rest wait their turn.
   The rotation stops on hover — a list that moves while you are reading it is
   worse than a long one. */
html.oi-home-simple .welcome-starters { gap: 6px; }
/* FAIL VISIBLE. This hid every starter and let the rotator reveal two, so any
   path that adds one without calling the rotator blanked the row — and there
   is such a path (the trip-specific starters are built and inserted further
   down index.html). Seen live: chips on one load, none on the next. The
   rotator marks what to HIDE; anything it has not seen shows. Too many chips
   is cosmetic, no chips is a broken page. */
html.oi-home-simple .welcome-starter { padding: 9px 13px; font-size: 0.82rem; border-radius: 12px; }
html.oi-home-simple .welcome-starter.is-off { display: none; }
html.oi-home-simple .welcome-starter-icon { width: 26px; height: 26px; }
html.oi-home-simple .welcome-starter-icon svg { width: 15px; height: 15px; }
/* The trip-specific starters carry their sub-label in a <small>, not in
   .welcome-starter-label — two chips side by side, one with a caption and
   one without. */
html.oi-home-simple .welcome-starter-label,
html.oi-home-simple .welcome-starter-text small { display: none; }

/* The way back out, and in. Quiet — it is a switch, not a feature. */
.home-simple-toggle { display: block; margin: 18px auto 4px; background: none; border: 0; padding: 4px 8px; font: inherit; font-size: 11.5px; color: var(--text-3); cursor: pointer; }
.home-simple-toggle:hover { color: var(--accent); }

/* ── The chat's opening screen (simple home, 19 Sep) ──────────────────────
   Cory, with a Claude screenshot beside the live page: the logo and "Good
   morning, Cory" centred at the top, the welcome paragraph gone ("I don't
   read it anymore"), then the daily quote, the suggestions, and the composer
   directly under them — docking to the foot the moment a question is asked.

   The welcome paragraph carried the work sentence ("2 things need you now…").
   Losing it is only safe because Tasks moved to the top of the sidebar this
   morning, where he sees the same rows without being told about them. */

/* THE COLUMN DOES NOT WAIT. Measured from the parent frame at 390px: the
   composer and both its buttons are 0 wide until 4929ms and full size the
   same instant — they are not drawn late, the whole chat column is
   display:none until then, by `#home-view.active ~ #messages`. On a staff
   load the dashboard home is marked active first and the chat only appears
   once the JS chain has decided which home to show. In simple mode that is
   known before paint, so it need not wait. (Cory: "The mic and send icons
   take a long time to load." — twice; my first answer was wrong.) */
html.oi-home-simple #home-view { display: none !important; }
html.oi-home-simple #home-view.active ~ #messages { display: flex !important; }
html.oi-home-simple #welcome-smart { display: none !important; }

/* The greeting IS the logo line — one element, its word swapped, rather than
   a wordmark with a heading under it. */
/* SCREEN AWARE, and never two lines. "Good afternoon, Cory" at 1.9rem wants
   ~300px and a phone gives ~330 minus gutters — it wrapped on his actual
   phone. clamp() ties it to the viewport; nowrap makes wrapping impossible
   rather than unlikely. A greeting that reflows is the same class of thing
   as the page that jumped. */
html.oi-home-simple .welcome-logo { font-size: clamp(1.15rem, 5.2vw, 1.9rem); color: var(--text-1); margin-bottom: 10px; display: flex; align-items: center; justify-content: center; white-space: nowrap; }
html.oi-home-simple .welcome-logo svg { width: 0.62em; height: 1.05em; }
html.oi-home-simple .welcome-logo-word { font-family: var(--font-display); }

/* ANCHORED, NOT CENTRED. Measured on the live page with a MutationObserver:
   the content arrives in five waves (0.3s, 1.9s, 3.7s, 5.5s, 5.9s), and in a
   vertically centred column every wave re-centres the whole stack — the
   greeting, the quote, the chips and the composer all slide. Five layout
   shifts in six seconds reads exactly like a page refreshing itself, which is
   what Cory called it: "the page refreshes every few seconds which makes
   everything jump weird."

   Anchored to the top, a late block can only push what is BELOW it. */
/* PINNED, with a slight pad (Cory). 12vh is a third of a phone screen — a
   viewport-relative pad is not "slight" anywhere small. */
html.oi-home-simple body.composer-inline #messages { justify-content: flex-start; padding-top: 5px; }
html.oi-home-simple body.composer-inline .welcome-msg { margin: 0 auto; }

/* The composer, inline. It is the SAME element that docks — it moves, so the
   send handler and the voice button stay wired to the one composer. */
html.oi-home-simple body.composer-inline #input-area { position: static; border-top: 0; background: transparent; box-shadow: none; padding: 0; margin: 18px auto 0; max-width: 720px; width: 100%; }
/* New / History stay under the box on the empty screen too — History is the
   useful one there, and hiding them made the empty state and the thread
   disagree about where the conversation's controls live. */
html.oi-home-simple body.composer-inline #lore-thread-bar { display: flex; }
/* The starters sit above it, the switch below everything. */
/* "Could the suggestion chips be under the chat" (Cory, 19 Sep). */
html.oi-home-simple body.composer-inline #input-area { order: 1; }
html.oi-home-simple .welcome-starters { order: 3; }
/* My day sits under the box, where the chips were (25 Sep); the chips go
   while the day has something in it. */
html.oi-home-simple #welcome-starters.day-has-items { display: none !important; }
/* NO SUGGESTION CHIPS ON HOME, ever (Cory, 1 Oct: "Those were supposed to be
   gone a long time ago"). Home is the box, the greeting, the quote, the
   schedule, then plans and trips. They showed whenever the day was still
   loading or empty — on a phone, that was every first look. */
html.oi-home-simple .welcome-starters { display: none !important; }
/* The line under the greeting is the day's QUOTE. The stock tagline
   ("Your personal assistant —…") was its placeholder and showed whenever the
   quote was late or missing; now nothing shows until the quote is there. */
html.oi-home-simple #welcome-sub:not(.has-quote) { display: none !important; }
html.oi-home-simple .home-myday { order: 3; width: 100%; max-width: 720px; margin: 18px auto 0; text-align: left; }
html.oi-home-simple .home-simple-toggle { order: 3; }
html.oi-home-simple .welcome-msg { display: flex; flex-direction: column; }
/* THE STRIP ACROSS THE TOP (Cory: "Should the plans span across the very top
   of the page? Bringing the welcome and the chat closer together? As it is
   now it feels disjointed"). He is right about the cause: the strip sat
   between the quote and the composer and pushed the greeting away from the
   box you type in. It is a status line — it belongs above everything. */
/* PINNED AT THE TOP, with room under it (Cory: "I want the plans pinned to
   the top giving the greeting/chat room to breath"). It was already first;
   what it lacked was the gap that turns "above" into "a separate band". */
/* PLANS, QUOTE, GREETING, CHAT (Cory: "the quote should go right under the
   plans and move the chat up right under greeting"). The quote was sitting
   between the greeting and the box you type in, holding them apart; moved
   above, the greeting and the composer read as one unit. */
html.oi-home-simple .welcome-trips { order: -4; margin: 0 0 14px; }
html.oi-home-simple #home-hero { order: -3; }
/* GREETING FIRST, then the box (25 Sep: "get rid of the plans up top, move
   the greeting up"). The plans live in My day's right-hand column now, and
   the quote goes to the foot of the page, where it closes rather than
   separates. */
html.oi-home-simple .welcome-logo { order: -1; }
/* 25 Sep, later: "The quote went away. I like the quote." At the foot it
   was below the fold. Under the box it is seen and still does not come
   between the greeting and the box. */
html.oi-home-simple .welcome-sub { order: 2; margin: 14px auto 0; font-size: 12.5px; opacity: .8; max-width: 600px; }
html.oi-home-simple #welcome-sub { text-align: center; }

/* ONE COLUMN. The countdown strip and the starters live inside `.home-cols`,
   the two-column desktop grid — not as direct children of `.welcome-msg` — so
   the ordering rules written for direct children did nothing to them, and the
   countdown pill sat 500px right of a centred greeting. Measured: the strip
   325px wide at x=897, inside a box starting at x=382.

   A chat's opening screen is one centred column; the two-column grid is the
   dashboard layout it replaces. */
/* display:contents — the plans strip is a GRANDCHILD of the greeting block
   (.welcome-msg > .home-cols > .home-life > .welcome-trips), so its order
   cannot be set from the block that contains it. Dissolving the two dashboard
   wrappers lets their children take part in the greeting block's own
   ordering, which makes moving the strip a re-order rather than a second
   place that builds it.

   It also takes the LINE with it: .home-life carries a 1px left border, the
   divider between the dashboard's two columns. Simple mode collapsed that
   layout to one column and left the divider standing beside the plans — a
   rule separating nothing from nothing (Cory: "There is a line to the left of
   the plans."). */
html.oi-home-simple .home-cols, html.oi-home-simple .home-life { display: contents !important; }
html.oi-home-simple .home-life { border: 0; }
/* The two late arrivals RESERVE their space, so nothing above them moves when
   they land at ~3.7s. Heights measured from the rendered rows. */
/* FOUR, evenly spaced (Cory: "there should always be 4-5 suggestions spaced
   evenly under the chat"). */
html.oi-home-simple .welcome-starters { display: flex; flex-wrap: nowrap; justify-content: space-between; gap: 8px; min-height: 76px; align-items: stretch; }
html.oi-home-simple .welcome-starter { flex: 1 1 0; min-width: 0; text-align: left; }
html.oi-home-simple .welcome-trips { min-height: 37px; }

/* ── The thread, on the simple home (19 Sep) ──────────────────────────────
   Cory: "Yes drop the assistant bubble and per message flame." / "Cap width"
   / "Have the mic inside the chat bubble same as claude?" / "Small text under
   it where the model is have New and History?"

   Both the bubble and the ember avatar were deliberate once — the avatar
   landed 7 Sep, replacing a literal "L". They are what make a reply read as a
   message FROM a correspondent rather than as the page answering you, and
   dropping them is most of why Claude's thread reads calm. The user keeps a
   bubble, because what you said and what it said should not look alike. */

/* No literal border-radius here: bubble-shape.test.js guards every bubble
   selector against hardcoded corners, and it is right to — with no background
   and no border the radius is invisible anyway, so the token stays and the
   rule stays honest. */
/* ── A LORE THREAD, wherever it is ────────────────────────────────────────
   Cory, 19 Sep, on a lead card: "I asked a question and the answer jumped up
   where it was before. It should be just above the chat bar and move the page
   down right?" … "and should behave the same way. No chat bubbles, etc."

   Same root cause as the composer an hour earlier: "a reply from Lore" was
   written twice — .message.assistant under html.oi-home-simple #messages, and
   .fc-msg.fc-ai in the pipeline's own stylesheet — so the home thread lost
   its bubble and its per-message ember and the lead card never heard.

   Both containers are .oi-thread and both mark their replies .oi-reply, so
   this block is the only description of the shape. The two element
   vocabularies (.message.assistant / .fc-msg.fc-ai) are legacy and still
   differ; what they look like no longer does. */
/* TWO SELECTORS, one rule. pipeline.html carries its bubble styling in an
   INLINE <style>, which the browser applies after this linked stylesheet, so
   at equal specificity the page-local rule wins on order — the flame went and
   the bubble stayed, measured on the live page. `.fc-msg.oi-reply` outranks
   `.fc-msg.fc-ai` whatever the order. Not a second implementation: the same
   declarations, addressed to an element that already matches. */
.oi-thread .oi-reply,
.oi-thread .fc-msg.oi-reply {
  background: transparent; border: 0; padding: 2px 0 6px; margin-left: 0;
  max-width: 100%;
}
.oi-thread .oi-reply::before,
.oi-thread .fc-msg.oi-reply::before { display: none; }
/* The thinking line loses its card too, or it reappears between plain replies. */
.oi-thread .message.thinking, .oi-thread .fc-msg-steps { background: transparent; border: 0; margin-left: 0; }
.oi-thread .message.thinking::before, .oi-thread .fc-msg-steps::before { display: none; }
/* What YOU said keeps its bubble — what you said and what it said should not
   look alike. */
.oi-thread .oi-ask { max-width: 85%; }

/* AND IT LANDS ABOVE THE BAR. A reply scrolled to with block:'end' used to
   stop at the bottom of the scroll box, which is underneath the docked
   composer. The dock declares its own height (--oi-dock-h, lore-dock.js);
   with no dock on the page this resolves to 0px and nothing moves. */
.oi-thread > * { scroll-margin-bottom: calc(var(--oi-dock-h, 0px) + 12px); }

/* ONE READING COLUMN, the same width as the composer, so the text and the box
   you answer in line up instead of the text running twice as wide. */
html.oi-home-simple #messages { padding-left: max(16px, calc((100% - 720px) / 2)); padding-right: max(16px, calc((100% - 720px) / 2)); }
html.oi-home-simple body.composer-inline .welcome-msg { max-width: 720px; }

/* ── THE LORE COMPOSER, styled once ───────────────────────────────────────
   Cory, 19 Sep: "Why doesn't ask Lore look the same way as the one we just
   built on the home page? I thought EVERYTHING that can be is global
   ALWAYS?"

   It didn't because the dock carried its own CSS string and its own markup —
   a second implementation of the same box. Home grew a + and a mic inside the
   field; the dock kept a plain pill with a circle beside it, and nothing
   pointed the difference out until the two screens sat side by side.

   Keyed on CLASSES on purpose. Two elements cannot share an id, so an
   id-keyed rule can only ever style one of the two composers, which is
   exactly how they drifted. Anything that is a Lore composer wears .oi-comp
   and gets this.

   The mic goes IN the box. It was a third floating circle beside the send
   button; Claude keeps it inside, where it reads as part of the field rather
   than another thing to hit. */
.oi-comp { position: relative; display: flex; align-items: center; max-width: 720px; margin: 0 auto; width: 100%; }
.oi-comp-input {
  flex: 1; min-width: 0; width: 100%;
  padding: 10px 84px 10px 42px;
  background: var(--surface, var(--bg-card, #fff));
  border: 1px solid var(--border, #d7dbe0);
  border-radius: var(--composer-radius, 12px);
  color: var(--text, #1b1f24);
  font-size: 16px; font-family: inherit; line-height: 1.4;
  outline: none; resize: none; max-height: 120px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .08);
}
.oi-comp-input:focus { border-color: var(--green-border, var(--accent)); }
/* z-index 2, and it is load-bearing: polish.css lifts any FOCUSED field to
   position:relative; z-index:1 for its focus ring — and a text field matches
   :focus-visible on every focus, mouse included. So the moment he clicked
   into the box, the field rose above the +, the mic and the send and they
   vanished under it: "i can't click the +" (Cory, 22 Sep). The controls sit
   above the field, focused or not. */
.oi-comp-attach, .oi-comp-mic, .oi-comp-send { z-index: 2; }
.oi-comp-attach, .oi-comp-mic {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0; background: transparent; box-shadow: none;
  color: var(--text-3, #7a828d); cursor: pointer;
}
.oi-comp-attach { left: 10px; }
/* The same box with fewer controls — a message to a person has no + here,
   a quick reply has no mic. The field simply gives the room back. */
.oi-comp.no-attach .oi-comp-input { padding-left: 14px; }
.oi-comp.no-mic .oi-comp-input { padding-right: 48px; }
.oi-comp.is-single .oi-comp-input { white-space: nowrap; overflow: hidden; }
.oi-comp-mic { right: 48px; }
.oi-comp-attach:hover, .oi-comp-mic:hover { color: var(--accent); }
/* A photo dragged over the box: the box says so. */
.oi-comp.oi-drop-over .oi-comp-input { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft, #eef4ee); }
/* Send wears the mic's style — a quiet outline icon, no filled circle
   (Cory, 23 Sep: "I don't like the green send icon, i feel it should be
   more like the mic style"). It turns accent once there is something to
   send, so the box still says "ready". One rule: every page's box. */
.oi-comp-send {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; flex-shrink: 0;
  border: 0; padding: 0; box-shadow: none;
  background: transparent; color: var(--text-3, #7a828d);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  transition: color .15s;
}
.oi-comp-send:hover { color: var(--accent); }
/* Keyed on the TEXTAREA: in a rich box it is the hidden field that carries
   the words, and it is still the one that knows whether it is empty. */
.oi-comp:has(textarea:not(:placeholder-shown)) .oi-comp-send { color: var(--accent); }
.oi-comp-send:disabled { opacity: .3; cursor: not-allowed; }
/* The formatting bar (Cory, 23 Sep: team-chat formatting on every box, the
   mic kept). "Aa" sits in the box beside the mic; the bar opens as a row
   INSIDE the top of the box (Slack's place for it). Floating above the box
   put it under home's lead lookup, which uses that same spot. */
.oi-comp-fmt {
  position: absolute; top: 50%; transform: translateY(-50%); right: 84px; z-index: 2;
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0; background: transparent; box-shadow: none; border-radius: 8px;
  color: var(--text-3, #7a828d); cursor: pointer;
}
.oi-comp.no-mic .oi-comp-fmt { right: 48px; }
.oi-comp-fmt:hover, .oi-comp-fmt[aria-pressed="true"] { color: var(--accent); }
.oi-comp.has-fmt .oi-comp-input { padding-right: 120px; }
.oi-comp.has-fmt.no-mic .oi-comp-input { padding-right: 84px; }
.oi-comp-tools {
  position: absolute; left: 1px; right: 1px; top: 1px; z-index: 3;
  display: flex; gap: 2px; padding: 4px 6px; overflow-x: auto; scrollbar-width: none;
  /* Opaque, so a long message scrolled up passes UNDER the bar instead of
     showing through it (Cory, 6 Oct: "when you scroll up on a long message
     it garbles the toolbar"). Same surface and corners as the box. */
  background: var(--surface, var(--bg-card, #fff)); border-bottom: 1px solid var(--border, #d7dbe0);
  border-radius: calc(var(--composer-radius, 12px) - 1px) calc(var(--composer-radius, 12px) - 1px) 0 0;
}
.oi-comp.fmt-open .oi-comp-input { padding-top: 46px; max-height: 170px; }
/* With the bar open the controls sit on the text's first line, not the
   middle of a taller box. */
.oi-comp.fmt-open .oi-comp-attach, .oi-comp.fmt-open .oi-comp-mic,
.oi-comp.fmt-open .oi-comp-send, .oi-comp.fmt-open .oi-comp-fmt { top: auto; bottom: 6px; transform: none; }
.oi-comp-tools[hidden] { display: none; }
.oi-comp-tools button.on { color: var(--accent); background: var(--accent-soft, rgba(127, 127, 127, .12)); }
.oi-comp-linkin {
  flex: 1 1 160px; min-width: 120px; height: 30px; margin-left: 4px; padding: 0 10px;
  border: 1px solid var(--border, #d7dbe0); border-radius: 7px; background: var(--bg, #fff);
  color: var(--text, #1b1f24); font: inherit; font-size: 14px; outline: none;
}
.oi-comp-linkin[hidden] { display: none; }
.oi-comp-linkin:focus { border-color: var(--accent); }

/* THE RICH EDITOR (Cory, 23 Sep: "I would like the rich editor"). The box
   you type in is a contenteditable wearing .oi-comp-input, so every rule
   above sizes it; the page's textarea rides along hidden (lore-composer.js
   enhance()). It grows with its words up to the box's max-height. */
.oi-comp-src { display: none !important; }
.oi-comp.fmt-open .oi-comp-ed { min-height: calc(1.4em + 58px); }
.oi-comp-ed {
  position: relative; display: block; min-height: calc(1.4em + 22px); overflow-y: auto; box-sizing: border-box;
  white-space: pre-wrap; overflow-wrap: anywhere; cursor: text; text-align: left;
}
.oi-comp-ed.is-empty::before {
  content: attr(data-placeholder); position: absolute; pointer-events: none;
  color: var(--text-3, #7a828d); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: calc(100% - 140px);
}
.oi-comp-ed > div, .oi-comp-ed p { margin: 0; }
.oi-comp-ed ul, .oi-comp-ed ol { margin: 2px 0; padding-left: 22px; }
.oi-comp-ed blockquote { margin: 2px 0; padding: 0 0 0 10px; border-left: 3px solid var(--border, #d7dbe0); color: var(--text-2, #4a525c); }
.oi-comp-ed code { background: rgba(127, 127, 127, .16); padding: 1px 4px; border-radius: 4px; font-family: ui-monospace, Menlo, monospace; font-size: .9em; }
.oi-comp-ed a { color: var(--accent); text-decoration: underline; }
.oi-comp-tools button {
  width: 32px; height: 30px; flex: 0 0 32px; display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0; background: transparent; border-radius: 7px; color: var(--text-2, #4a525c); cursor: pointer;
}
.oi-comp-tools button:hover { background: var(--hover, rgba(127, 127, 127, .12)); color: var(--accent); }

/* TWO LINES, EVERY BOX (Cory, 1 Oct: "I would like the chat feature to
   always be the one on two lines"). The words get the top line; the bottom
   row is +, then the Chat / Ask Lore switch where a room has one, then Aa,
   mic and send at the right. A one-line reply box (.is-single) stays one. */
.oi-comp.is-two .oi-comp-input { padding-left: 14px; padding-bottom: 46px; }
.oi-comp.is-two.has-fmt .oi-comp-input, .oi-comp.is-two .oi-comp-input { padding-right: 14px; }
.oi-comp.is-two .oi-comp-ed { min-height: calc(1.4em + 58px); }
/* A long message: the box grows to about half the screen before it scrolls (Cory, 6 Oct). */
.oi-comp.is-two .oi-comp-input { max-height: min(45vh, 380px); }
.oi-comp.is-two.fmt-open .oi-comp-input { max-height: min(52vh, 430px); }
.oi-comp.is-two.fmt-open .oi-comp-ed { min-height: calc(1.4em + 94px); }
.oi-comp.is-two .oi-comp-attach, .oi-comp.is-two .oi-comp-mic,
.oi-comp.is-two .oi-comp-send, .oi-comp.is-two .oi-comp-fmt { top: auto; bottom: 7px; transform: none; }
.oi-comp.is-two .oi-comp-ed.is-empty::before { max-width: calc(100% - 28px); }
/* The bottom row (+, Chat / Ask Lore, mic, send) sits on its own strip of the
   box's surface: words scrolled down pass under it, not through it (6 Oct). */
.oi-comp.is-two::after {
  content: ''; position: absolute; left: 1px; right: 1px; bottom: 1px; height: 42px; z-index: 2; pointer-events: none;
  background: var(--surface, var(--bg-card, #fff));
  border-radius: 0 0 calc(var(--composer-radius, 12px) - 1px) calc(var(--composer-radius, 12px) - 1px);
}
.oi-comp.is-two .oi-comp-attach, .oi-comp.is-two .oi-comp-mic, .oi-comp.is-two .oi-comp-send, .oi-comp.is-two .oi-comp-fmt, .oi-comp.is-two .oi-comp-modes { z-index: 3; }
.oi-comp-modes {
  position: absolute; left: 10px; bottom: 8px; z-index: 2;
  display: flex; gap: 2px; padding: 2px; border-radius: 8px;
  background: var(--surface-3, rgba(127, 127, 127, .14));
}
.oi-comp.is-two:not(.no-attach) .oi-comp-modes { left: 44px; }
.oi-comp-modes button {
  border: 0; background: transparent; cursor: pointer; font: inherit;
  font-size: 12.5px; font-weight: 600; line-height: 1; padding: 6px 10px; border-radius: 6px;
  color: var(--text-3, #7a828d);
}
.oi-comp-modes button:hover { color: var(--text, #1b1f24); }
.oi-comp-modes button.on { background: var(--surface, var(--bg-card, #fff)); color: var(--text, #1b1f24); box-shadow: 0 1px 2px rgba(0, 0, 0, .12); }
/* ON A PHONE the bottom row is tight (Cory, 24 Sep: "the chat text ask
   lore toggle scrunches together with the controls on the right"). Everything
   in the row gets a size smaller, and the right-hand controls sit closer. */
@media (max-width: 560px) {
  .oi-comp.is-two .oi-comp-attach, .oi-comp.is-two .oi-comp-mic,
  .oi-comp.is-two .oi-comp-send, .oi-comp.is-two .oi-comp-fmt { width: 26px; height: 26px; }
  .oi-comp.is-two .oi-comp-attach svg, .oi-comp.is-two .oi-comp-mic svg,
  .oi-comp.is-two .oi-comp-send svg, .oi-comp.is-two .oi-comp-fmt svg { width: 16px; height: 16px; }
  .oi-comp.is-two .oi-comp-attach { left: 6px; }
  .oi-comp.is-two .oi-comp-send { right: 6px; }
  .oi-comp.is-two .oi-comp-mic { right: 34px; }
  .oi-comp.is-two .oi-comp-fmt { right: 62px; }
  .oi-comp.is-two.no-mic .oi-comp-fmt { right: 34px; }
  .oi-comp.is-two:not(.no-attach) .oi-comp-modes { left: 34px; }
  .oi-comp-modes button { font-size: 11.5px; padding: 5px 7px; }
}

/* VOICE IN THE BOX (Cory, 1 Oct: "some sort of cool animation"). While the
   mic is live the words line is a row of bars (lore-composer.js voiceViz):
   green with your voice, ember with Lore's, a slow wave while it connects or
   thinks. A light runs round the edge of the box. */
@property --oi-vang { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.oi-comp[data-voice]::before {
  content: ''; position: absolute; inset: -2px; border-radius: calc(var(--composer-radius, 12px) + 2px);
  background: conic-gradient(from var(--oi-vang), transparent 0deg, var(--oi-vc1) 70deg, var(--oi-vc2) 140deg, transparent 220deg, transparent 360deg);
  animation: oi-vspin 2.4s linear infinite; pointer-events: none;
  --oi-vc1: var(--accent, #3c7a4c); --oi-vc2: #8cc7a0;
}
.oi-comp[data-voice="speaking"]::before { --oi-vc1: #e8743b; --oi-vc2: #f6b04a; animation-duration: 1.6s; }
.oi-comp[data-voice="connecting"]::before, .oi-comp[data-voice="thinking"]::before { --oi-vc1: var(--text-3, #9aa1aa); --oi-vc2: var(--accent, #3c7a4c); animation-duration: 1.2s; }
@keyframes oi-vspin { to { --oi-vang: 360deg; } }
.oi-comp[data-voice] .oi-comp-ed, .oi-comp[data-voice] .oi-comp-input { color: transparent; caret-color: transparent; }
.oi-comp[data-voice] .oi-comp-ed.is-empty::before { opacity: 0; }
.oi-comp[data-voice] textarea.oi-comp-input { position: relative; }
.oi-comp-voice {
  position: absolute; z-index: 2; pointer-events: none;
  left: 16px; right: 16px; top: 9px; height: calc(1.4em + 10px);
  display: flex; align-items: center; justify-content: center; gap: 3px;
}
.oi-comp.is-single .oi-comp-voice { top: 0; bottom: 0; height: auto; right: 90px; }
.oi-comp-voice i {
  display: block; flex: 0 1 4px; max-width: 4px; height: 100%; border-radius: 3px;
  transform: scaleY(.1); transform-origin: center; will-change: transform;
  background: linear-gradient(180deg, #8cc7a0, var(--accent, #3c7a4c));
  transition: background .4s;
}
.oi-comp[data-voice="speaking"] .oi-comp-voice i { background: linear-gradient(180deg, #f6b04a, #e8743b); }
.oi-comp[data-voice="connecting"] .oi-comp-voice i, .oi-comp[data-voice="thinking"] .oi-comp-voice i { background: linear-gradient(180deg, var(--text-3, #9aa1aa), var(--accent, #3c7a4c)); opacity: .75; }
@media (prefers-reduced-motion: reduce) { .oi-comp[data-voice]::before { animation: none; } }

/* New / History as a footnote UNDER the box — where Claude puts the model
   name — instead of two buttons floating above it looking like actions on the
   conversation. */
html.oi-home-simple #lore-thread-bar { order: 9; justify-content: flex-end; gap: 14px; padding: 8px 6px 0; max-width: 720px; }
html.oi-home-simple #lore-thread-bar button { border: 0; background: none; padding: 0; font-size: 11.5px; font-weight: 400; color: var(--text-3); }
html.oi-home-simple #lore-thread-bar button:hover { color: var(--accent); border: 0; }
/* align-items: a flex column sizes its items to their CONTENT, so making
   this a column to put New/History under the form collapsed the form to
   243px — measured. A change for two small buttons shrank the thing they
   sit under. */
html.oi-home-simple #input-area { display: flex; flex-direction: column; align-items: center; }
html.oi-home-simple #input-area > * { width: 100%; }
html.oi-home-simple #input-area #input-form { order: 1; }

/* TWO BY TWO ON A PHONE. Four across is a desktop answer: `flex: 1 1 0` with
   no wrapping gives each chip about 78px on a 360px screen once the gaps are
   out, and these chips carry whole sentences. Reasoned from the numbers —
   Chrome would not resize below ~500px here to see it. */
@media (max-width: 720px) {
  html.oi-home-simple .welcome-starters { flex-wrap: wrap; justify-content: center; min-height: 0; }
  html.oi-home-simple .welcome-starter { flex: 1 1 calc(50% - 8px); min-width: 140px; }
  html.oi-home-simple .welcome-trips { justify-content: center; }
  html.oi-home-simple #messages { padding-left: 16px; padding-right: 16px; }
  html.oi-home-simple body.composer-inline #messages { padding-top: 4px; }
}

/* THE FEED PILLS (Planning / My Memories / Entire Feed) are a phone-only row
   that lives OUTSIDE #home-view, which is how they survived everything else
   on the simple home being hidden. Three doors into a feed this home does not
   show, above the greeting, first thing on the screen. Cory: "Those are no
   longer needed."

   Hidden, not deleted — they are the full home's only way to those views on a
   phone, and the full home is one tap away. */
html.oi-home-simple #hv-feed-pills { display: none !important; }

/* The label belongs to the simple strip only; the full home keeps its big
   dashed "Start a new plan" card. */
.wt-newshort { display: none; }
html.oi-home-simple .wt-newshort { display: block; }

/* The + is a 24px block in the card's own inline style — beside a label
   rather than above it, it wants to be a glyph. */
html.oi-home-simple .wt-card[data-first-run="new-plan"] > div:first-child { font-size: 15px !important; line-height: 1 !important; }

/* "Bit more padding between quote and greeting." The quote sits directly
   above the greeting now that it moved out from between the greeting and the
   composer, so its own bottom margin is the gap. */
html.oi-home-simple .welcome-sub { margin: 0 auto 22px !important; }

/* ── The + : something for Lore to look at (Cory, 19 Sep) ──────────────────
   Left of the field, mirroring the mic and send on the right, so the box has
   one control at each end and the text sits between them. */
/* The + was hidden unless the simple home was on — which is how the dock
   came to be a composer without one. A Lore box has a +; .oi-comp-attach
   places it, and there is nothing left to gate. */

#lore-attach-strip { display: none; }
#lore-attach-strip.has-files {
  display: flex; gap: 8px; flex-wrap: wrap;
  max-width: 720px; margin: 0 auto 8px; padding: 0 4px;
}
html.oi-home-simple #input-area #lore-attach-strip { order: 0; }
.lore-attach-thumb { position: relative; display: inline-block; line-height: 0; }
.lore-attach-thumb img {
  width: 54px; height: 54px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--border, #e3e5e8);
}
.lore-attach-thumb button {
  position: absolute; top: -6px; right: -6px; width: 18px; height: 18px;
  border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  background: var(--text-1, #1b1f24); color: #fff;
  font-size: 12px; line-height: 18px; text-align: center;
}

/* ── The name lookup above the Lore bar (Charlie, 19 Sep) ──────────────────
   Fixed and body-level, not inside the bar: the composer is inside an
   overflow-hidden dock on most pages, and a dropdown that clips at its
   parent's edge is the "separate window that does nothing to help" all over
   again. */
.oi-find {
  position: fixed; z-index: 2000; display: none;
  max-height: min(46vh, 340px); overflow-y: auto;
  background: var(--bg-card, #fff);
  border: 1px solid var(--border-2, #d7dbe0);
  border-radius: 12px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .16);
  padding: 4px;
}
.oi-find.on { display: block; }
.oi-find-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px; cursor: pointer;
}
.oi-find-row.on, .oi-find-row:hover { background: var(--accent-soft, #eef4ee); }
.oi-find-main { flex: 1; min-width: 0; }
.oi-find-t {
  font-size: 14px; font-weight: 600; color: var(--text, #1b1f24);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.oi-find-s {
  font-size: 12px; color: var(--text-2, #5a6470); margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.oi-find-meta {
  flex-shrink: 0; text-align: right; display: flex; flex-direction: column; gap: 2px;
}
.oi-find-stage { font-size: 10px; font-weight: 700; color: var(--accent, #3d6b47); letter-spacing: .02em; }
.oi-find-who { font-size: 10px; color: var(--text-3, #7a828d); }
.oi-find-empty { padding: 14px 12px; font-size: 13px; color: var(--text-3, #7a828d); text-align: center; }

/* A phone has no room for the consultant column next to a 40-character trip
   title; the name and the booking are what identify the lead. */
@media (max-width: 480px) {
  .oi-find-who { display: none; }
}

/* THE SHARE BUTTON (Cory, 24 Sep: "more visible, obvious, and intuitive").
   An icon and the word, in the accent, everywhere something can be shared:
   under a Lore answer, on a chat message, on an email, on a card. One look,
   so people learn it once. lore-share.js OiShare.button() writes it. */
.oi-share-btn {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--accent); background: var(--accent-soft, rgba(126, 185, 43, .12)); color: var(--accent);
  border-radius: 999px; padding: 5px 12px; font: inherit; font-size: 12.5px; font-weight: 700; line-height: 1;
  cursor: pointer; white-space: nowrap; transition: background .15s, color .15s;
}
.oi-share-btn:hover { background: var(--accent); color: #fff; }
.oi-share-btn svg { flex-shrink: 0; }
/* In a message's hover bar the button carries its word too. */
.oi-action-bar .oi-action-share { width: auto !important; padding: 0 10px !important; gap: 5px; display: inline-flex; align-items: center; color: var(--accent); font-size: 12px; font-weight: 700; }
.oi-action-bar .oi-action-share:hover { background: var(--accent-soft, rgba(126, 185, 43, .12)); }
/* "They asked you for that" — the offer over your box, only on your screen. */
.oi-share-nudge {
  display: flex; align-items: center; gap: 10px; margin: 0 0 8px; padding: 9px 10px 9px 12px;
  border: 1px solid var(--accent); border-radius: 10px; background: var(--accent-soft, rgba(126, 185, 43, .1));
  font-size: 12.5px; line-height: 1.4; color: var(--text, #1b1f24);
}
.oi-share-nudge-x { border: none; background: none; color: var(--text-3); font-size: 18px; line-height: 1; cursor: pointer; padding: 0 2px; }

/* @TAGS (Cory, 24 Sep — Slack's tag, in Lore). The person's name in a soft
   chip; brighter when it is you. */
.oi-mention[data-uid] { cursor: pointer; }
.oi-mention[data-uid]:hover { text-decoration: underline; }
.oi-mention { background: rgba(29, 155, 209, .12); color: #1264a3; border-radius: 4px; padding: 0 2px; font-weight: 600; }
.oi-mention.is-me { background: rgba(242, 199, 68, .35); color: inherit; }
.oi-mention.is-lore { background: var(--accent-soft, rgba(126, 185, 43, .14)); color: var(--accent); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .oi-mention:not(.is-me):not(.is-lore) { color: #6cb6ef; } }
[data-theme="dark"] .oi-mention:not(.is-me):not(.is-lore) { color: #6cb6ef; }

/* The @ picker, over the box (lore-composer.js setMentions). */
.oi-comp-mention-pop {
  position: absolute; left: 8px; bottom: calc(100% + 6px); z-index: 30; min-width: 220px; max-width: 320px;
  background: var(--surface, var(--bg-card, #fff)); border: 1px solid var(--border, #d7dbe0); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .18); padding: 4px; display: flex; flex-direction: column;
}
.oi-comp-mention-pop[hidden] { display: none; }
.oi-comp-mention-pop button { display: flex; align-items: center; justify-content: space-between; gap: 10px; text-align: left; border: 0; background: none; font: inherit; font-size: 13px; padding: 7px 10px; border-radius: 7px; cursor: pointer; color: var(--text, #1b1f24); }
.oi-comp-mention-pop button span { font-size: 11px; color: var(--text-3, #7a828d); }
.oi-comp-mention-pop button.on, .oi-comp-mention-pop button:hover { background: var(--accent-soft, rgba(126, 185, 43, .14)); }

/* Messages | Shared | Plans over the chat (Cory, 24 Sep — Slack's tabs). */
.oi-ts-roomtabs { display: flex; gap: 2px; padding: 0 14px; border-bottom: 1px solid var(--border, #e3e6ea); flex-shrink: 0; }
.oi-ts-roomtabs button {
  display: inline-flex; align-items: center; gap: 5px; border: 0; background: none; font: inherit; font-size: 12.5px; font-weight: 600;
  color: var(--text-3, #7a828d); padding: 8px 10px 7px; border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer;
}
.oi-ts-roomtabs button span { font-size: 11px; font-weight: 700; color: var(--text-3, #7a828d); }
.oi-ts-roomtabs button:hover { color: var(--text, #1b1f24); }
.oi-ts-roomtabs button.on { color: var(--text, #1b1f24); border-bottom-color: var(--accent); }
.oi-ts-tabpane { position: absolute; left: 0; right: 0; bottom: 0; top: 38px; overflow-y: auto; background: var(--bg, #fff); z-index: 5; padding: 14px 18px; }
.oi-ts-tabpane[hidden] { display: none; }
.oi-ts-tabpane details { max-width: 760px; margin: 0 auto 12px; }
.oi-ts-tabpane details > summary { pointer-events: none; }
.oi-ts-tabpane details > summary button { pointer-events: auto; }

/* ── Home: Upcoming plans + Memories, My day's right column (25 Sep) ──────
   Cory: "upcoming plans on a horizontal slider with countdown timers like we
   had and then under them, memories". The column stacks the plans where it
   is narrow and beside the day; one column (a phone) slides them sideways
   between Today and Tomorrow. The cards are the plans strip's own cards,
   moved here (index.html _mountHomeDay); the countdown is home-blocks.js's,
   ticked by its one shared clock. */
.wt-cd { display: none; }
.md-plans, .md-mem { margin: 0 0 18px; }
.md-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-3); padding: 4px 0 8px; }
.md-h a { font-size: 12px; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--accent); text-decoration: none; }
.md-new { display: inline-flex; align-items: center; gap: 5px; border: 1px solid var(--accent); background: var(--accent-soft); color: var(--text-1); border-radius: 999px; padding: 4px 11px; font: inherit; font-size: 12px; font-weight: 700; letter-spacing: 0; text-transform: none; cursor: pointer; }
.md-new:hover { filter: brightness(1.05); }
.md-empty { display: none; padding: 14px; font-size: 13.5px; color: var(--text-3); border: 1px dashed var(--border); border-radius: 14px; }
.md-try { border: 0; background: none; padding: 0; font: inherit; font-weight: 600; color: var(--accent); cursor: pointer; }
.md-try:hover { text-decoration: underline; }
.md-plans:not(:has(.wt-card:not([data-first-run="new-plan"]))) .md-empty { display: block; }
.md-plans:not(:has(.wt-card:not([data-first-run="new-plan"]))) .welcome-trips { display: none !important; }
.md-mem:has(#welcome-memories[style*="none"]) { display: none; }
/* The + card is the header button here. */
html.oi-home-simple .md-plans .wt-card[data-first-run="new-plan"] { display: none !important; }
/* PLAN CARDS — a slider by default (one column), a stack beside the day. */
html.oi-home-simple .md-plans .welcome-trips { justify-content: flex-start; margin: 0; min-height: 0; gap: 10px; padding-bottom: 4px; scroll-snap-type: x mandatory; scrollbar-width: none; }
html.oi-home-simple .md-plans .welcome-trips::-webkit-scrollbar { display: none; }
html.oi-home-simple .md-plans .wt-card { flex: 0 0 240px; max-width: none; min-height: 0; flex-direction: column; align-items: flex-start; gap: 2px; padding: 12px 14px; border-radius: 14px; background: var(--surface); border: 1px solid var(--border); scroll-snap-align: start; cursor: pointer; }
html.oi-home-simple .md-plans .wt-card:hover { border-color: var(--accent); }
html.oi-home-simple .md-plans .wt-title { font-size: 14px; font-weight: 700; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.oi-home-simple .md-plans .wt-status { display: block !important; font-size: 12px; color: var(--text-3); text-shadow: none; }
html.oi-home-simple .md-plans .wt-when { display: none; }
.md-plans .wt-cd { display: block; margin-top: 8px; }
.md-plans .wt-cd .lhb-hero-count { display: flex; align-items: center; gap: 8px; margin: 0; }
.md-plans .wt-cd .lhb-hero-count b { font-family: var(--font-display, inherit); font-size: 30px; line-height: 1; font-weight: 800; letter-spacing: -.03em; color: var(--accent); font-variant-numeric: tabular-nums; }
.md-plans .wt-cd .lhb-hero-unit { display: flex; flex-direction: column; gap: 1px; }
.md-plans .wt-cd .lhb-hero-count i { font-style: normal; font-size: 12px; font-weight: 600; color: var(--text-2); }
.md-plans .wt-cd .lhb-hero-clock { font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; min-width: 0; }
@container (min-width: 620px) {
  html.oi-home-simple .md-plans .welcome-trips { flex-direction: column; flex-wrap: nowrap !important; overflow: visible; }
  html.oi-home-simple .md-plans .wt-card { flex: 0 0 auto; width: 100%; }
}
/* MEMORIES — three photo tiles, the rest behind "See all". */
html.oi-home-simple .md-mem .welcome-trips { flex-direction: column; flex-wrap: nowrap !important; overflow: visible; margin: 0; min-height: 0; gap: 8px; justify-content: flex-start; }
html.oi-home-simple .md-mem .wt-card { flex: 0 0 auto; width: 100%; max-width: none; min-height: 84px; flex-direction: column; justify-content: flex-end; align-items: flex-start; gap: 1px; padding: 10px 12px; border-radius: 14px; border: 1px solid var(--border); background-color: var(--surface); background-size: cover; background-position: center; cursor: pointer; }
html.oi-home-simple .md-mem .wt-card:nth-child(n+4) { display: none; }
html.oi-home-simple .md-mem .wt-title { font-size: 13.5px; font-weight: 700; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html.oi-home-simple .md-mem .wt-when { display: block; font-size: 11.5px; }
html.oi-home-simple .md-mem .wt-card.wt-photo .wt-title,
html.oi-home-simple .md-mem .wt-card.wt-photo .wt-when { color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.4); }
.wt-cd:empty { display: none !important; }
html.oi-home-simple .md-plans .wt-card:not(:has(.wt-cd:not(:empty))) .wt-when { display: block; margin-top: 4px; }
/* Not "Nothing planned yet" while the plans are still loading. */
.md-plans:has(#welcome-trips[style*="none"]) .md-empty { display: none !important; }
/* "Some indicator that you can click to open it up and plan" (25 Sep). */
.md-plans .wt-card::after { content: 'Open plan \2192'; display: block; margin-top: 10px; font-size: 12.5px; font-weight: 700; color: var(--accent); }
.md-hr { display: inline-flex; align-items: center; gap: 6px; }
.md-all { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); color: var(--text-2); text-decoration: none; }
.md-all:hover { border-color: var(--accent); color: var(--accent); }
.md-plans .md-h > span:first-child { white-space: nowrap; }
.md-new { white-space: nowrap; flex-shrink: 0; }
/* Plans heading on a phone: the words give way before the buttons do. */
.md-plans .md-h > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@container (max-width: 480px) {
  .md-h { gap: 6px; }
  .md-new { padding: 4px 9px; }
  .md-all { width: 26px; height: 26px; }
}
/* PHONE PLAN CARDS (26 Sep: "the plan is weird alignment"). A fixed 240px
   card sat left with a gap beside it. One plan fills the row; several each
   take most of it, so the next one peeks and says "swipe". */
html.oi-home-simple .md-plans .wt-card { flex-basis: min(85%, 320px); }
html.oi-home-simple .md-plans .wt-card[data-first-run="new-plan"] + .wt-card:last-child { flex-basis: 100%; }
@container (min-width: 620px) {
  html.oi-home-simple .md-plans .wt-card { flex-basis: auto; }
}

/* Plan | Chat on a phone — the room's two halves take turns (25 Sep). */
.oi-ts-seg{flex:0 0 auto;display:flex;gap:4px;margin:6px 14px 8px;padding:3px;border-radius:10px;background:var(--bg-2);border:1px solid var(--border-2)}
.oi-ts-seg button{flex:1;border:none;background:none;padding:7px 0;border-radius:7px;font-size:13px;font-weight:700;color:var(--text-3);cursor:pointer}
.oi-ts-seg button.on{background:var(--bg-card);color:var(--text-1);box-shadow:0 1px 2px rgba(0,0,0,.12)}
#oi-ts-room[data-phone="chat"] #oi-ts-partybar{padding:0 10px 8px}
/* The same two tabs on a plan opened from home (2 Oct): the board was the
   last sibling under the composer — chat on top, the box in the middle, a
   strip of plan below. Now each takes the whole screen in turn. */
.oi-ts-seg button{display:inline-flex;align-items:center;justify-content:center;gap:6px}
@media (max-width:767px){
  .oi-ts-host[data-phone] > #oi-trip-board{border-top:none !important}
  .oi-ts-host[data-phone="chat"] > #oi-trip-board{display:none !important}
  .oi-ts-host[data-phone="plan"] > #oi-comms-ch-msgs,
  .oi-ts-host[data-phone="plan"] > .oia-pane,
  .oi-ts-host[data-phone="plan"] > #oi-ch-att-preview,
  .oi-ts-host[data-phone="plan"] > .oi-comms-thread-input{display:none !important}
  .oi-ts-host[data-phone="plan"] > #oi-trip-board{display:block !important;flex:1 1 auto !important;min-height:0;max-height:none !important;height:auto !important;overflow-y:auto;padding-bottom:calc(16px + env(safe-area-inset-bottom,0px))}
}
@media (max-width:600px){
  #oi-ts-statuspill{display:none}
  .oi-ts-topbar{padding:8px 12px 0 !important}
}

/* The seller's mark on the trip card: never over the countdown (25 Sep). */
.oi-ts-herobox{container-type:inline-size}
.oi-ts-sellermark{display:flex;justify-content:flex-end;margin-bottom:6px;pointer-events:none;width:max-content;margin-left:auto}
.oi-ts-sellermark img{height:34px;max-width:140px;object-fit:contain;display:block}
@container (min-width:520px){
  .oi-ts-sellermark{position:absolute;top:0;bottom:0;right:0;z-index:1;align-items:center;margin:0}
  .oi-ts-sellermark img{height:auto;max-height:100%;max-width:190px}
}
/* Narrow card: the countdown stays on one line (days → seconds). */
@container (max-width:340px){
  #oi-ts-clock{gap:4px !important}
  #oi-ts-clock > div{min-width:44px !important}
  #oi-ts-clock > div > span:first-child{font-size:28px !important}
  #oi-ts-clock > span:last-child{flex-basis:100%;margin-left:0 !important;max-width:none !important;margin-top:4px}
}

/* ── Home backdrop (Cory, 2 Oct) ─────────────────────────────────────────
   Today's photo behind the greeting and Lore's box, like a phone's lock
   screen. public/home-backdrop.js sets --hb-h to just past the quote; the
   photo fades into the page there, so the day's cards always sit on the
   plain background in light and dark. Gone the moment a chat opens. */
html.oi-home-simple #messages { position: relative; }
html.oi-home-simple .welcome-msg { position: relative; z-index: 1; }
#home-backdrop { position: absolute; left: 0; right: 0; top: 0; height: var(--hb-h, 360px); z-index: 0; pointer-events: none; overflow: hidden; opacity: 0; transition: opacity .6s ease;
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 110px), transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 110px), transparent 100%); }
#home-backdrop .hb-img { position: absolute; inset: 0; background-size: cover; background-position: center 60%; }
#home-backdrop .hb-scrim { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(0,0,0,.40) 0, rgba(0,0,0,.20) 34%, rgba(0,0,0,.26) 62%, rgba(0,0,0,.36) 100%); }
html.has-backdrop #home-backdrop { opacity: 1; }
#home-backdrop-cap { position: absolute; top: 8px; right: 10px; z-index: 3; display: none; align-items: center; gap: 0; max-width: min(44%, 240px);
  padding: 0 0 0 7px; border-radius: 999px; background: rgba(0,0,0,.2); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); color: #fff; font-size: 9.5px; line-height: 1.2; opacity: .8; }
#home-backdrop-cap:hover, #home-backdrop-cap:focus-within { opacity: 1; }
html.has-backdrop #home-backdrop-cap { display: inline-flex; }
#home-backdrop-cap .hb-cap-text { color: #fff; text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
#home-backdrop-cap a.hb-cap-text:hover { text-decoration: underline; }
#home-backdrop-cap .hb-more { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border: 0; border-radius: 50%; background: transparent; color: #fff; cursor: pointer; padding: 0; }
#home-backdrop-cap .hb-more:hover { background: rgba(255,255,255,.18); }
#home-backdrop-cap .hb-menu { position: absolute; z-index: 5; top: calc(100% + 6px); right: 0; min-width: 220px; padding: 6px; border-radius: 12px; background: var(--surface); border: 1px solid var(--border); box-shadow: 0 8px 28px rgba(0,0,0,.18); display: flex; flex-direction: column; }
#home-backdrop-cap .hb-menu[hidden] { display: none; }
#home-backdrop-cap .hb-menu button { text-align: left; border: 0; background: none; padding: 9px 10px; border-radius: 8px; font-size: 13px; color: var(--text-1); cursor: pointer; }
#home-backdrop-cap .hb-menu button:hover { background: var(--surface-2, rgba(0,0,0,.05)); }
#messages.has-thread #home-backdrop, #messages.has-thread #home-backdrop-cap { display: none !important; }
@media (max-width: 640px) { html.has-backdrop #messages:not(.has-thread) .welcome-msg { padding-top: 34px; } #home-backdrop-cap { max-width: 62%; } }
html.has-backdrop #messages:not(.has-thread) .welcome-logo-word { color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.35), 0 2px 20px rgba(0,0,0,.35); }
html.has-backdrop #messages:not(.has-thread) #welcome-sub.has-quote { color: rgba(255,255,255,.94); text-shadow: 0 1px 2px rgba(0,0,0,.55); }
html.has-backdrop #messages:not(.has-thread) #welcome-sub.has-quote * { color: inherit !important; opacity: .85; }
html.has-backdrop #messages:not(.has-thread) #lore-thread-bar button { color: rgba(255,255,255,.92); text-shadow: 0 1px 2px rgba(0,0,0,.5); }
html.has-backdrop #messages:not(.has-thread) #lore-thread-bar button:hover { color: #fff; }
@media (prefers-reduced-motion: reduce) { #home-backdrop { transition: none; } }
