/* JNY shell — phone-first. Tablet & desktop tweaks at the bottom. */

* { box-sizing: border-box; }

/* Build Edition theme tints — body[data-edition] set by app.js so users
   see which Edition they're on without reading the URL. */
body[data-edition="jf"]  .status-strip { border-bottom-color: #6cd6c0; }
body[data-edition="jnf"] .status-strip { border-bottom-color: #ff8c66; }
body[data-edition="jf"]  .status-strip::after,
body[data-edition="jnf"] .status-strip::after {
  position: absolute; right: 10px; top: 4px;
  font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .5px;
}
body[data-edition="jf"]  .status-strip::after { content: "Journey Friends"; color: #6cd6c0; }
body[data-edition="jnf"] .status-strip::after { content: "First Responder"; color: #ff8c66; }
.status-strip { position: relative; }


/* ─── Theme tokens — three modes for varying light conditions ──────────────
   DARK:    indoor/evening default. Low-fatigue.
   OUTDOOR: bright-sun, glare-resistant. Near-white text on near-black bg,
            saturated high-chroma accents, heavier type weight, thicker
            scrollbars + focus rings. Built for a grandparent on a park bench
            in July noon.
   LIGHT:   full-sun alternative. Dark text on bright bg — sometimes reads
            better than dark-mode+glare since bright screens at max nit
            beat reflected skylight. User picks.

   Toggle cycles dark → outdoor → light and sets data-theme on <html>.
   prefers-contrast: more auto-upgrades dark → outdoor. prefers-color-scheme:
   light auto-picks light when the OS says so (user can still override). */

:root, html[data-theme="dark"] {
  --bg:             #070812;
  --surface:        #0f1226;
  --surface-2:      #171a33;
  --text:           #e9eaf2;
  --text-dim:       #a7a9bd;
  --border:         rgba(255,255,255,0.08);
  --accent:         #8c8ff0;
  --accent-strong:  #a7aaff;
  --danger:         #ff6b7a;
  --success:        #4ad29a;
  --focus-ring:     0 0 0 2px rgba(167, 170, 255, 0.5);
  --jny-scroll-thumb:       rgba(180, 170, 220, 0.28);
  --jny-scroll-thumb-hover: rgba(200, 190, 240, 0.52);
  --jny-scroll-thumb-active:rgba(220, 210, 250, 0.75);
  --jny-scroll-track:       transparent;
  /* Chrome (status-strip / flip-bar / comm-bar) — dark mode keeps the dark navy band. */
  --chrome-bg:      #1a1f3a;
  --chrome-bg-2:    #252b4a;
  --chrome-text:    #e8eaf5;
  --chrome-text-dim:#c9cce8;
  --chrome-border:  #252b4a;
  --chrome-accent:  #D4A84B;  /* Honey, per gm-brand-tokens */
  --emer-bg:        #b03a2e;  /* button bg — solid red */
  --emer-fg:        #ff8a7a;  /* heading on dark surfaces */
}

html[data-theme="outdoor"] {
  /* WCAG AAA-target contrast. Pure white on pure black. Wider borders,
     thicker focus, heavier scrollbars. No subtle grays that wash to white
     under direct sunlight. */
  --bg:             #000000;
  --surface:        #0b0b14;
  --surface-2:      #151525;
  --text:           #ffffff;
  --text-dim:       #e0e2ef;
  --border:         rgba(255,255,255,0.24);
  --accent:         #b9bcff;     /* brighter — survives glare */
  --accent-strong:  #d8dbff;
  --danger:         #ff9ea6;
  --success:        #7fffbd;
  --focus-ring:     0 0 0 3px #ffffff, 0 0 0 6px #000000;
  --jny-scroll-thumb:       rgba(255,255,255,0.6);
  --jny-scroll-thumb-hover: rgba(255,255,255,0.85);
  --jny-scroll-thumb-active:#ffffff;
  --jny-scroll-track:       rgba(255,255,255,0.1);
  /* Chrome — outdoor mode is pure-black/pure-white extremes for sun glare */
  --chrome-bg:      #000000;
  --chrome-bg-2:    #151525;
  --chrome-text:    #ffffff;
  --chrome-text-dim:#e0e2ef;
  --chrome-border:  rgba(255,255,255,0.4);
  --chrome-accent:  #E8C977;  /* Honey-light for outdoor visibility */
  --emer-bg:        #b03a2e;
  --emer-fg:        #ffb0a4;  /* lighter for outdoor glare */
}

html[data-theme="light"] {
  /* L1 Midnight Pearl — luxury light theme. Navy/ink on pearl/white.
     WCAG-verified: body/heading AAA, muted AA. See _CANON/brand/README.md. */
  --bg:             #fbf9e4;   /* pearl ground */
  --surface:        #ffffff;
  --surface-2:      #f2ead7;
  --text:           #14171f;   /* ink — AAA */
  --text-dim:       #5b6473;   /* muted — AA */
  --border:         #e7e3d3;
  --accent:         #122c4f;   /* deep navy */
  --accent-strong:  #1b3a66;
  --danger:         #b3261e;
  --success:        #1e7d4f;
  --focus-ring:     0 0 0 2px rgba(18,44,79,0.55);
  --jny-scroll-thumb:       rgba(18,44,79,0.30);
  --jny-scroll-thumb-hover: rgba(18,44,79,0.52);
  --jny-scroll-thumb-active:rgba(18,44,79,0.78);
  --jny-scroll-track:       rgba(18,44,79,0.06);
  /* Chrome — navy band, white text, ocean accent (no honey/indigo). */
  --chrome-bg:      #122c4f;
  --chrome-bg-2:    #1b3a66;
  --chrome-text:    #ffffff;
  --chrome-text-dim:#c8d0dc;
  --chrome-border:  rgba(255,255,255,0.12);
  --chrome-accent:  #5b88b2;   /* ocean */
  --emer-bg:        #b3261e;
  --emer-fg:        #b3261e;
}

/* Auto-upgrade dark → outdoor when the OS asks for high contrast. User's
   explicit toggle still wins (because they'd have set data-theme). */
@media (prefers-contrast: more) {
  :root:not([data-theme]) {
    --bg:             #000000;
    --surface:        #0b0b14;
    --surface-2:      #151525;
    --text:           #ffffff;
    --text-dim:       #e0e2ef;
    --border:         rgba(255,255,255,0.24);
    --accent:         #b9bcff;
    --accent-strong:  #d8dbff;
    --danger:         #ff9ea6;
    --success:        #7fffbd;
    --focus-ring:     0 0 0 3px #ffffff, 0 0 0 6px #000000;
    --jny-scroll-thumb:       rgba(255,255,255,0.6);
    --jny-scroll-thumb-hover: rgba(255,255,255,0.85);
    --jny-scroll-thumb-active:#ffffff;
    --jny-scroll-track:       rgba(255,255,255,0.1);
  }
}

/* ─── Scrollbars (use the tokens above) ───────────────────────────────────── */
html { scrollbar-width: thin; scrollbar-color: var(--jny-scroll-thumb) var(--jny-scroll-track); }
*::-webkit-scrollbar        { width: 8px; height: 8px; }
*::-webkit-scrollbar-track  { background: var(--jny-scroll-track); }
*::-webkit-scrollbar-thumb  {
  background: var(--jny-scroll-thumb);
  border-radius: 8px;
  border: 2px solid transparent;      /* visual breathing room inside the 8px lane */
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover  { background: var(--jny-scroll-thumb-hover); background-clip: padding-box; }
*::-webkit-scrollbar-thumb:active { background: var(--jny-scroll-thumb-active); background-clip: padding-box; }
*::-webkit-scrollbar-corner { background: transparent; }
/* Don't draw a scrollbar lane just for overflow-x on mobile — looks noisy. */
@media (pointer: coarse) {
  *::-webkit-scrollbar        { width: 3px; height: 3px; }
  *::-webkit-scrollbar-thumb  { border: 0; background-clip: border-box; }
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  overflow-x: hidden;
  overscroll-behavior: contain;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

/* App frame: phone-width on all viewports. Web = phone-in-a-window, not expanded desktop. */
body {
  display: flex;
  align-items: stretch;
  justify-content: center;
}

.shell {
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  width: 100%;
  max-width: 420px;      /* phone baseline */
  /* Use svh (small viewport height) so our layout fits WITH Safari's URL bar
     visible. dvh shrinks/grows as the bar appears, causing jumpy content.
     On keyboard-open, --jny-kbd-h is set by wireKeyboardLayout() so the
     shell shrinks enough to keep the compose bar above the keyboard. */
  height: calc(100svh - var(--jny-kbd-h, 0px));
  max-height: calc(100svh - var(--jny-kbd-h, 0px));
  background: var(--surface);
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  box-shadow: 0 0 48px rgba(0,0,0,.5);
  overflow-x: hidden;    /* prevent any child from forcing horizontal scroll */
  transition: height 180ms ease-out, max-height 180ms ease-out;
}
/* When the keyboard is open, suppress the status strip animation noise
   and lock the comm panel to max, so typing surface is always visible. */
body.kbd-open .status-strip { position: relative; }

/* Grid-item min-width gotcha: grid children default to min-width:auto,
   which lets content expand tracks and push past the shell. Force 0. */
.shell > * { min-width: 0; }

/* iOS Safari (not standalone) — Safari's URL bar + bottom-controls bar aren't
   captured by safe-area insets. Give ourselves explicit breathing room. */
body.is-ios.mode-browser .shell {
  padding-top: max(env(safe-area-inset-top), 12px);
  /* Safari's bottom URL/tab bar can be up to 50px; if safe-area is 0, use a
     comfortable fallback so our comm-icons don't sit under it. */
  padding-bottom: max(env(safe-area-inset-bottom), 20px);
}
/* In standalone (installed PWA) on iOS, safe-area-inset-bottom captures the
   home indicator; no fallback needed. */
body.mode-standalone .shell {
  height: 100dvh;
  max-height: 100dvh;
}

/* ─── Theme toggle — cycles dark ☾ / outdoor ◉ / light ☀ ─── */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: 8px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: background 120ms, border-color 120ms, transform 120ms;
  -webkit-tap-highlight-color: transparent;
}
.theme-toggle:hover { border-color: var(--accent); }
.theme-toggle:active { transform: scale(0.94); }
.theme-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); }
html[data-theme="dark"]    .theme-toggle::after { content: "☾"; }   /* moon */
html[data-theme="outdoor"] .theme-toggle::after { content: "◉"; }   /* high-contrast dot */
html[data-theme="light"]   .theme-toggle::after { content: "☀"; }  /* sun */
/* When no theme explicitly set: show the dark moon (matches root defaults). */
html:not([data-theme])     .theme-toggle::after { content: "☾"; }

/* ─── Force-refresh button — always visible, always works ─── */
/* Persistent escape hatch: if the user thinks the app is stuck on an old
   version (no update pill shown, but something feels wrong), one tap here
   unregisters service workers, deletes all caches, and reloads with a
   cache-bust query. Distinct from the update pill which only shows when
   a NEW SW is waiting. */
.force-refresh {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: 6px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: background 120ms, border-color 120ms, transform 120ms;
  -webkit-tap-highlight-color: transparent;
  flex: 0 0 auto;
}
.force-refresh:hover { border-color: var(--accent); }
.force-refresh:active { transform: rotate(180deg); }
.force-refresh:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.force-refresh.is-working { animation: jny-refresh-spin 0.8s linear infinite; pointer-events: none; }
@keyframes jny-refresh-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* ─── EMER button (placeholder, concept-stage)
   Capability-aware progressive enhancement — see GMX7/GVR/.
   No tech stack wired yet; tap opens an info modal. ─── */
.emer-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 6px;
  padding: 4px 10px;
  border: none;
  border-radius: 12px;
  background: var(--emer-bg);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  cursor: pointer;
  box-shadow: 0 0 0 2px rgba(232, 90, 79, 0.25);
  -webkit-tap-highlight-color: transparent;
  flex: 0 0 auto;
}
.emer-btn:hover { filter: brightness(1.08); }
.emer-btn:active { transform: scale(0.96); }
.emer-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(232, 90, 79, 0.5); }

.emer-modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex; align-items: center; justify-content: center;
  z-index: 9999;
  padding: 20px;
}
.emer-modal {
  background: var(--surface-2, #1a2030);
  color: var(--text, #e8edf5);
  border: 1px solid var(--border, #2c3550);
  border-radius: 16px;
  max-width: 440px;
  width: 100%;
  max-height: 86vh;
  overflow-y: auto;
  padding: 20px 22px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
}
.emer-modal h2 {
  margin: 0 0 4px;
  color: var(--emer-fg);
  font-size: 18px;
}
.emer-modal .sub {
  color: var(--text-dim, #8a93a8);
  font-size: 12px;
  margin: 0 0 14px;
}
.emer-modal h3 {
  font-size: 13px;
  margin: 16px 0 6px;
  color: var(--accent, #6cd6c0);
}
.emer-modal p, .emer-modal li {
  font-size: 13px;
  line-height: 1.5;
  margin: 6px 0;
}
.emer-modal ol { padding-left: 20px; margin: 6px 0; }
.emer-modal .pill {
  display: inline-block;
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(176, 58, 46, 0.10);
  color: #b03a2e;
  border: 1px solid rgba(176, 58, 46, 0.35);
  margin-bottom: 8px;
  font-weight: 600;
}
.emer-modal .close-btn {
  display: block;
  width: 100%;
  margin-top: 16px;
  padding: 12px;
  border: 1px solid var(--border, #2c3550);
  background: var(--surface, #232b3e);
  color: var(--text, #e8edf5);
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.theme-toggle              { color: transparent; }   /* hide the fallback glyph */
.theme-toggle::after       { color: var(--text); }

/* ─── Status strip ─── */
.status-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(8px + env(safe-area-inset-top, 0px)) calc(14px + env(safe-area-inset-right, 0px)) 8px calc(14px + env(safe-area-inset-left, 0px));
  background: var(--chrome-bg);
  color: var(--chrome-text);
  font-size: 12px;
  letter-spacing: 0.02em;
  border-bottom: 1px solid var(--chrome-border);
}
/* Children inherit chrome-text token instead of body --text (which is near-black in light mode and would be invisible on the dark chrome). */
.status-strip .identity,
.status-strip .circle,
.status-strip .theme-toggle,
.status-strip .theme-toggle::after,
.status-strip .force-refresh,
.status-strip .force-refresh::before { color: var(--chrome-text); }
.identity { font-weight: 600; opacity: .85; min-width: 0; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.circle { opacity: .85; color: var(--chrome-text-dim); min-width: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.circle:hover { color: var(--chrome-text); }

/* Circle picker dropdown */
/* Device settings overlay */
.device-settings {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 20px;
}
.ds-card {
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 20px;
  color: var(--text);
}
.ds-card h2 { margin: 0 0 6px; font-size: 18px; }
.ds-card h3.ds-section { margin: 20px 0 6px; font-size: 13px; opacity: .7; text-transform: uppercase; letter-spacing: .08em; }
.ds-label { display: block; margin: 12px 0 6px; font-size: 12px; opacity: .7; }
.ds-card input[type="text"] {
  width: 100%;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
  outline: none;
}
.ds-card input[type="text"]:focus { border-color: var(--accent); }
.ds-row { display: flex; gap: 8px; margin-top: 10px; }
.ds-row-wrap { flex-wrap: wrap; }
.ds-row-right { justify-content: flex-end; margin-top: 16px; }
.ds-btn {
  padding: 8px 14px;
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  font-size: 13px;
  font-family: inherit;
}
.ds-btn:hover { background: var(--accent); }
.ds-btn-ghost { background: transparent; color: var(--text-dim); border: 1px solid var(--border); }
.ds-btn-ghost:hover { color: #c9cce8; background: rgba(80,98,199,.1); }

/* Identity menu (click on name in status strip) */
.identity-menu {
  position: fixed;
  top: max(44px, calc(env(safe-area-inset-top) + 8px));
  left: 10px;
  right: auto;
  background: var(--chrome-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0,0,0,.5);
  z-index: 100;
  min-width: 260px;
  max-width: min(90vw, 360px);
  padding: 8px;
  color: var(--text);
  font-size: 14px;
  /* drawerscroll 2026-06-11: long account lists were clipped (Sign out unreachable).
     Bound height to the viewport below the top offset and scroll the overflow. */
  max-height: calc(100vh - max(44px, calc(env(safe-area-inset-top) + 8px)) - 12px);
  max-height: calc(100dvh - max(44px, calc(env(safe-area-inset-top) + 8px)) - 12px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.im-header {
  padding: 10px 10px 12px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 6px;
}
.im-name { font-weight: 600; font-size: 15px; }
.im-device { font-size: 12px; opacity: .65; margin-top: 2px; }
.im-section-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  opacity: .45;
  padding: 8px 10px 4px;
}
.im-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: var(--text);
  cursor: pointer;
  font-size: 14px;
  text-align: left;
  font-family: inherit;
}
.im-item:hover { background: var(--surface-2); }
.im-item span:first-child { font-size: 16px; line-height: 1; }
.im-signout { color: #d87b7b; }
.im-signout:hover { background: rgba(216,123,123,0.1); }
.im-muted { opacity: .55; font-size: 11px; }
.im-device-list { padding: 4px 0; }
.im-device-row {
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 13px;
}
.im-device-row.is-this { background: rgba(80,98,199,0.15); }
.im-device-name { display: flex; align-items: center; gap: 7px; }
/* D005 P1 — presence/recency dot + last-seen meta */
.im-device-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: rgba(140,150,170,0.45);   /* dim = idle/offline */
  flex: 0 0 auto;
}
.im-device-dot.is-active { background: #4caf72; }  /* green = recently active */
.im-device-meta { padding: 1px 0 0 15px; }

.circle-menu {
  position: fixed;
  top: 44px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--chrome-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0,0,0,.5);
  z-index: 99;
  min-width: 220px;
  padding: 6px;
  /* drawerscroll 2026-06-11: same clip fix as .identity-menu for long circle lists. */
  max-height: calc(100vh - 44px - 12px);
  max-height: calc(100dvh - 44px - 12px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.circle-opt {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: var(--text);
  cursor: pointer;
  font-size: 14px;
  text-align: left;
}
.circle-opt:hover { background: var(--surface-2); }
.circle-opt.is-active { background: rgba(80,98,199,.2); color: #ffffff; }
.co-room { font-size: 12px; opacity: .6; }
.conn {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  background: #2a2a2a;
  color: #aaa;
}
.conn[data-state="online"]  { background: #1d3a2a; color: #7bd89a; }
.conn[data-state="offline"] { background: #3a1d1d; color: #d87b7b; }
.conn[data-state="pending"] { background: #2a2a3a; color: var(--text-dim); }

/* ─── Stage (L2/L3 swap area) ─── */
.stage {
  overflow-y: auto;
  padding: 16px;
  background: var(--surface-2);
}
.stage .loading { opacity: .6; text-align: center; padding: 48px 0; }
.stage h1 { margin: 0 0 12px; font-size: 20px; }
.stage h2 { margin: 0 0 8px; font-size: 16px; }
.stage p  { margin: 0 0 12px; opacity: .8; line-height: 1.4; }

.stage .card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px;
  margin-bottom: 12px;
  display: flex;
  gap: 12px;
  align-items: center;
}
.stage .card-art {
  width: 60px; height: 60px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--accent-strong), var(--accent));
  display: flex; align-items: center; justify-content: center;
  font-size: 28px;
  flex-shrink: 0;
}
.stage .card-meta { flex: 1; min-width: 0; }
.stage .card-meta h2 { margin: 0 0 2px; font-size: 15px; }
.stage .card-meta p  { margin: 0; font-size: 13px; opacity: .65; }
.stage button.card.game-card {
  width: 100%;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.stage button.card.game-card:hover {
  background: var(--surface-2);
  border-color: var(--accent-strong);
}

/* Tic-Tac-Toe */
.game-back {
  background: transparent;
  color: var(--text-dim);
  border: 0;
  font-size: 13px;
  padding: 4px 0 10px;
  cursor: pointer;
}
.game-back:hover { color: #c9cce8; }
.game-title { font-size: 18px; margin: 0 0 6px; }
.game-status { font-size: 13px; opacity: .7; margin-bottom: 12px; }
.ttt-board {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  max-width: 280px;
}
.ttt-cell {
  aspect-ratio: 1 / 1;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  font-size: 40px;
  font-weight: 700;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.ttt-cell:hover:not(:disabled) { background: var(--surface-2); }
.ttt-cell:disabled { cursor: default; }
.ttt-cell.is-win { background: #3a4e2a; border-color: #7bd89a; color: #7bd89a; }
.game-reset {
  margin-top: 14px;
  padding: 8px 16px;
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  font-size: 14px;
}
.game-reset:hover { background: var(--accent); }

/* ─── Flip bar ─── */
.flip-bar {
  display: flex;
  background: var(--chrome-bg);
  border-top: 1px solid var(--chrome-border);
  border-bottom: 1px solid var(--chrome-border);
}
.flip-btn {
  flex: 1;
  padding: 10px 8px;
  background: transparent;
  border: 0;
  color: var(--text-dim);
  font-size: 13px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  cursor: pointer;
  transition: color 120ms ease, background 120ms ease;
}
.flip-btn .flip-icon { font-size: 20px; line-height: 1; }
.flip-btn:hover { color: #c9cce8; }
.flip-btn.is-active {
  color: #ffffff;
  background: linear-gradient(180deg, rgba(80,98,199,.15), rgba(80,98,199,.0));
  box-shadow: inset 0 2px 0 var(--accent);
}

/* ─── Comm bar (bottom, fixed) ─── */
.comm-bar {
  height: 38vh;
  min-height: 260px;
  max-height: 50vh;
  border-top: 1px solid var(--chrome-border);
  background: #0c0f1e;
}
.comm-bar iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* ─── In-app Jitsi call overlay (Phase C tier-2) ─── */
.jny-call-overlay {
  position: fixed;
  inset: 0;
  z-index: 11000;                /* above login overlay (9999) and popovers (10000) */
  background: #0a0d1a;
  color: #eaecff;
  display: flex;
  flex-direction: column;
}
.jny-call-overlay[hidden] { display: none !important; }

/* Global hidden-attribute override — beats any explicit display: rule.
   Without this, elements like .emer-modal-backdrop with display:flex
   stay visible even when their `hidden` attribute is set. */
[hidden] { display: none !important; }
.jny-call-header {
  display: flex;
  align-items: center;
  padding: 10px 14px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  padding-top: max(10px, env(safe-area-inset-top));
  flex: 0 0 auto;
}
.jny-call-title {
  flex: 1;
  font-weight: 600;
  font-size: 15px;
  color: #c9cce8;
}
.jny-call-hangup {
  padding: 8px 14px;
  border: 0;
  border-radius: 8px;
  background: #c53030;
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  font-size: 13px;
}
.jny-call-hangup:hover { filter: brightness(1.1); }
.jny-call-timer {
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: var(--text-dim, #a7a9bd);
  margin-right: 10px;
  min-width: 38px;
  text-align: right;
}
.jny-call-min {
  width: 32px;
  height: 32px;
  border: 1px solid var(--border, rgba(255,255,255,0.08));
  border-radius: 8px;
  background: transparent;
  color: var(--text, var(--text));
  font-size: 16px;
  cursor: pointer;
  margin-right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.jny-call-min:hover { background: rgba(255,255,255,0.06); }
.jny-call-frame {
  flex: 1 1 auto;
  min-height: 0;
  background: #000;
  position: relative;
}

/* Minimized banner mode — fixed strip at top, rest of app fully usable.
   Iframe stays attached (visibility: hidden) so audio keeps flowing. */
.jny-call-overlay.is-mini {
  inset: auto 0 auto 0;          /* top-anchored only */
  top: 0;
  height: auto;
  z-index: 11000;
  background: #0a0d1a;
  border-bottom: 1px solid var(--border);
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
}
.jny-call-overlay.is-mini .jny-call-header {
  padding-top: max(8px, env(safe-area-inset-top));
  padding-bottom: 8px;
}
.jny-call-overlay.is-mini .jny-call-title {
  cursor: pointer;                /* tap title to expand */
}
.jny-call-overlay.is-mini .jny-call-title::before {
  content: "🔊 ";
}
.jny-call-overlay.is-mini .jny-call-frame {
  flex: 0 0 auto;
  height: 1px;                    /* effectively invisible */
  visibility: hidden;             /* keep iframe alive — audio stays connected */
  overflow: hidden;
}
.jny-call-overlay.is-mini .jny-call-status,
.jny-call-overlay.is-mini .jny-call-vm-cta,
.jny-call-overlay.is-mini .jny-call-vm-mount {
  display: none;                  /* banner mode is bare-bones; expand for VM */
}

/* When call is mini, push the rest of the app down so the banner doesn't
   cover content. Approximate header height. */
body.has-mini-call {
  padding-top: 48px;
}
/* The iframe Jitsi injects fills the frame box */
.jny-call-frame iframe {
  width: 100% !important;
  height: 100% !important;
  border: 0 !important;
}
.jny-call-status {
  padding: 10px 14px;
  background: #3a1d1d;
  color: #ffb4b4;
  font-size: 13px;
  flex: 0 0 auto;
}

/* ─── Login overlay ─── */
.jny-login {
  position: fixed;
  inset: 0;
  background: #070812;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
  padding: 24px;
}
.jny-login-card {
  width: 100%;
  max-width: 360px;
  background: var(--chrome-bg);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 28px 24px;
  color: var(--text);
  box-shadow: 0 20px 60px rgba(0,0,0,.6);
}
.jny-login-card h1 {
  margin: 0 0 2px;
  font-size: 32px;
  letter-spacing: 0.04em;
  display: flex;
  align-items: center;
  gap: 6px;
}
.j-wordmark {
  background: linear-gradient(135deg, #c9cce8, var(--accent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 700;
}
.j-mark {
  font-size: 24px;
  color: #ffd166;
  margin-left: 2px;
  text-shadow: 0 0 8px rgba(255, 209, 102, .3);
}
.jny-login-card .j-tag {
  margin: 0 0 16px;
  font-size: 11px;
  opacity: .55;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.jny-login-card p { margin: 0 0 18px; opacity: .7; font-size: 14px; }
.jny-login-card input {
  display: block;
  width: 100%;
  padding: 12px 14px;
  margin-bottom: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  font-size: 15px;
  font-family: inherit;
  outline: none;
}
.jny-login-card input:focus { border-color: var(--accent); }
.jny-login-card button {
  display: block;
  width: 100%;
  padding: 12px;
  margin-top: 6px;
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  color: #ffffff;
  border: 0;
  border-radius: 10px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.jny-login-card button:hover { filter: brightness(1.1); }
/* Primary OIDC button (anchor tag) — matches the gradient button style */
.jny-login-card .kc-btn {
  display: block;
  width: 100%;
  padding: 14px 12px;
  margin-top: 6px;
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  color: #ffffff !important;
  border: 0;
  border-radius: 10px;
  font-size: 16px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  box-sizing: border-box;
  transition: filter 120ms, transform 120ms;
  -webkit-tap-highlight-color: transparent;
}
.jny-login-card .kc-btn:hover { filter: brightness(1.1); }
.jny-login-card .kc-btn:active { transform: scale(0.98); }
.jny-login-card .kc-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.pw-wrap {
  position: relative;
  margin-bottom: 10px;
}
.pw-wrap input {
  padding-right: 44px !important;
  margin-bottom: 0 !important;
}
.pw-toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: 0;
  color: var(--text-dim);
  font-size: 18px;
  padding: 6px 8px;
  margin: 0 !important;
  width: auto !important;
  cursor: pointer;
}

.jny-login-err {
  margin: 10px 0 0;
  padding: 8px 10px;
  background: #3a1d1d;
  color: #ffb4b4;
  border-radius: 8px;
  font-size: 13px;
}
.jny-login-msg {
  margin: 10px 0 0;
  padding: 8px 10px;
  background: #1d3a2a;
  color: #7bd89a;
  border-radius: 8px;
  font-size: 13px;
}
.magic-btn {
  display: block;
  width: 100%;
  padding: 10px !important;
  margin-top: 8px !important;
  background: transparent !important;
  color: var(--text-dim) !important;
  border: 1px solid var(--border) !important;
  font-size: 13px !important;
}
.magic-btn:hover { color: #c9cce8 !important; border-color: var(--accent-strong) !important; }

.jny-login-footer {
  margin: 16px 0 0;
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
}
.jny-login-footer a {
  color: #c9cce8;
  text-decoration: none;
  border-bottom: 1px dotted var(--accent-strong);
  padding-bottom: 1px;
}
.jny-login-footer a:hover { color: #ffffff; border-bottom-color: var(--accent); }

/* Join-free CTA — standalone, prominent, a couple lines below sign-in.
   Free membership is the biggest top-of-funnel CTA; surfaced (not buried in prose).
   Brand floor: Navy Luxe, warm/giver, multigenerational-legible. MARK owns final copy/treatment/A-B. */
.jny-join-cta {
  margin: 20px 0 0;
  padding: 18px 0 4px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.jny-join-line {
  margin: 0 0 12px !important;
  font-size: 16px !important;
  font-weight: 600;
  color: var(--text) !important;
  opacity: 1 !important;
  letter-spacing: 0.01em;
}
.jny-login-card a.jny-join-btn {
  display: block;
  width: 100%;
  padding: 14px 12px;
  margin: 0 auto;
  max-width: 100%;
  background: transparent;
  color: #ffffff !important;
  border: 1.5px solid var(--accent-strong);
  border-radius: 10px;
  font-size: 16px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  box-sizing: border-box;
  transition: background 120ms, filter 120ms, transform 120ms;
  -webkit-tap-highlight-color: transparent;
}
.jny-login-card a.jny-join-btn:hover {
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  filter: brightness(1.05);
}
.jny-login-card a.jny-join-btn:active { transform: scale(0.98); }
.jny-login-card a.jny-join-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.jny-join-sub {
  margin: 12px 0 0 !important;
  font-size: 13px !important;
  line-height: 1.5;
  color: var(--text-dim) !important;
  opacity: 1 !important;
}

/* iOS "Add to Home Screen" hint */
.ios-install-hint {
  position: fixed;
  /* Anchored to the TOP (under the status strip) so it can never cover the
     bottom comm bar / nav on phone. Was bottom-anchored and overlapped the
     comm bar until dismissed (QA 2026-05-24). */
  top: max(12px, env(safe-area-inset-top));
  left: 20px;
  right: 20px;
  background: var(--chrome-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  font-size: 13px;
  z-index: 100;
  box-shadow: 0 8px 24px rgba(0,0,0,.5);
}
.ios-install-hint button {
  /* a11y 2026-05-25: white-on-lavender (--accent #8c8ff0) was 2.87:1 (WCAG 1.4.3).
     Pin to deep navy bg + white text — theme-independent, ~13:1 in every theme. */
  background: #122c4f;
  color: #fff;
  border: 0;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 12px;
  margin-left: 8px;
  cursor: pointer;
}
body.mode-standalone .ios-install-hint { display: none; }

/* Tablet — keep phone width, just a touch more comfort */
@media (min-width: 768px) {
  .shell { max-width: 480px; }
  .stage h1 { font-size: 22px; }
}

/* Landscape layout: two-column (stage | comm) for any landscape-oriented
   device wide enough to make sense — covers phone landscape, tablet
   landscape (iPad, Android tablets), and small desktop windows.
   Portrait on any size stays single-column phone-width. */
@media (orientation: landscape) and (min-width: 720px) {
  .shell {
    max-width: min(1200px, 100vw);
    width: 100%;
    max-height: 100dvh;
    grid-template-columns: 1fr minmax(320px, 420px);
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
      "status status"
      "stage  comm"
      "flip   comm";
    box-shadow: 0 0 48px rgba(0,0,0,.5);
  }
  .status-strip { grid-area: status; }
  .stage { grid-area: stage; }
  .flip-bar { grid-area: flip; }
  .comm-bar {
    grid-area: comm;
    max-height: none !important;
    border-top: 0;
    border-left: 1px solid var(--border);
  }
}

/* Phone landscape (short, not wide enough for side-by-side comm):
   single-column, comm stays at the bottom, shell fills viewport. */
@media (orientation: landscape) and (max-width: 719px) and (max-height: 520px) {
  .shell {
    max-width: none;
    width: 100%;
    max-height: 100dvh;
    box-shadow: none;
  }
}

/* Utility: a surface can opt OUT of phone-width lock and fill the viewport
   (e.g., a game or video that wants landscape). Add class `.landscape-free`
   to <body> while that surface is active, remove when done. */
body.landscape-free .shell {
  max-width: none;
  width: 100%;
  box-shadow: none;
}

/* ─── Partial-render modes (via ?part= query param) ─── */
/* Shell applies a data-part attribute based on URL; CSS below shows only that region. */

/* iOS-tab redesign 2026-04-29: flip-bar (Play / Journey) is hidden globally.
 * Per project_jny1_is_production_jny2_stays_spike.md + Martin 2026-04-29:
 * Play and Journey are Minis on the JNY circle's WHAT'S HERE grid, not modes
 * forced onto every screen. The bottom is the iOS-style 4-tab comm rail
 * (Call / Video / Chat / All DMs) — see comm.css .comm-icons-ios. */
.flip-bar { display: none !important; }

body[data-part="comm"] .status-strip,
body[data-part="comm"] .stage,
body[data-part="comm"] .flip-bar { display: none; }
body[data-part="comm"] .shell { grid-template-rows: 1fr; max-width: none; box-shadow: none; }
body[data-part="comm"] .comm-bar { height: 100dvh; max-height: none; min-height: 0; }

body[data-part="stage"] .status-strip,
body[data-part="stage"] .flip-bar,
body[data-part="stage"] .comm-bar { display: none; }
body[data-part="stage"] .shell { grid-template-rows: 1fr; max-width: none; box-shadow: none; }

body[data-part="flip"] .status-strip,
body[data-part="flip"] .comm-bar { display: none; }
body[data-part="flip"] .shell { grid-template-rows: 1fr auto; max-width: none; box-shadow: none; }

/* Update-available pill — lives inside the status strip next to the conn
   chip, never escapes the phone-width shell. Tap to open a small popover
   anchored to the pill with Update / Later. */
.jny-update-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin: 0 6px;
  padding: 0;
  border: 1px solid var(--accent);
  border-radius: 11px;
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  animation: jny-update-pulse 1.8s ease-in-out infinite;
  -webkit-tap-highlight-color: transparent;
  flex: 0 0 auto;
}
.jny-update-pill:focus-visible { outline: none; box-shadow: var(--focus-ring); }
html[data-theme="light"] .jny-update-pill { color: #fff; }
@keyframes jny-update-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(140, 143, 240, 0); }
  50%      { transform: scale(1.08); box-shadow: 0 0 0 4px rgba(140, 143, 240, 0.22); }
}
@media (prefers-reduced-motion: reduce) {
  .jny-update-pill { animation: none; }
}

.jny-update-pop {
  position: fixed;
  z-index: 10000;
  width: 220px;
  padding: 12px 14px;
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 10px 28px rgba(0,0,0,.45);
  font-size: 14px;
}
.jny-update-pop-msg   { margin-bottom: 10px; line-height: 1.35; }
.jny-update-pop-actions { display: flex; justify-content: flex-end; gap: 8px; }
.jny-update-pop button {
  border: none;
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.jny-update-later { background: transparent; color: var(--text-dim); }
.jny-update-now   { background: var(--accent); color: #fff; }
html[data-theme="light"] .jny-update-now { background: var(--accent-strong); }

/* Global incognito/private-window banner — one warning across all L3s. */
.jny-incog-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: max(10px, env(safe-area-inset-top)) 14px 10px;
  background: #3a2a12;
  color: #ffe8c7;
  border-bottom: 1px solid #6a4a1e;
  font-size: 13px;
  line-height: 1.35;
}
.jny-incog-banner button {
  margin-left: auto;
  background: transparent;
  border: none;
  color: #ffe8c7;
  font-size: 18px;
  cursor: pointer;
  padding: 0 4px;
}

/* ============================================================================
   SETTINGS overlay + slimmed top-bar chrome   (2026-05-25)
   - #setQuick = page-set quick selector (replaced the off-page circle picker)
   - .theme-toggle is hidden unless the user pins it (Settings → Appearance)
   - .comm-bar is hidden (interim) until the Comm hub ships — nothing dials direct
   - .jny-settings = the Settings "card" overlay (app.js openSettings())
   ============================================================================ */

/* Top-bar PAGE-SET quick selector. Keeps the browser's native dropdown arrow. */
.status-strip .set-quick {
  margin: 0 6px;
  padding: 4px 8px;
  border: 1px solid rgba(255,255,255,0.42);
  border-radius: 999px;
  background: rgba(255,255,255,0.14);
  color: #f4f1ea;
  font: 600 12.5px/1.2 inherit;
  max-width: 44%;
  cursor: pointer;
}
.status-strip .set-quick option { color: #1a1f3a; background: #ffffff; }
.status-strip .set-quick:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Theme toggle: the [hidden] attribute must beat `.theme-toggle { display:inline-flex }`. */
.theme-toggle[hidden] { display: none !important; }

/* INTERIM (2026-05-25): in-app comm is OFF until the Comm hub ships. Hide the bottom
   comm bar everywhere so nothing dials direct. Delete this rule to restore comm. */
.comm-bar { display: none !important; }

/* ---- Settings card overlay (phone-bounded inside .shell) ----
   LIGHT Navy-Luxe treatment (ink on pearl), matching the springboard home, so the
   multi-word body copy is NOT reversed text. Ogilvy rule: >1-2 words of light-on-dark
   reading text fatigues the eyes and gets skipped unless the user opted into dark mode.
   Reversed is limited here to ≤1-2-word controls (active segmented button, filled CTA). */
.jny-settings {
  position: absolute; inset: 0; z-index: 200;
  display: flex; flex-direction: column;
  background: #fbf9e4; color: #14171f;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, system-ui, sans-serif;
  animation: jny-set-in 160ms ease;
}
@keyframes jny-set-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .jny-settings { animation: none; } }
/* .set-head = the Settings overlay's own L0 status-strip. Mirrors shell
   /app/app.css .status-strip exactly (--chrome-bg #1a1f3a, --chrome-text #e8eaf5,
   border #252b4a, 12px) so Settings reads as just another JNY card-with-L0, not
   a separate cream modal. (WKR1 2026-06-06, operator 'settings lost its L0' QA.) */
.jny-settings .set-head {
  display: flex; align-items: center; gap: 10px;
  padding: max(8px, env(safe-area-inset-top)) 14px 8px;
  background: #1a1f3a; color: #e8eaf5;
  border-bottom: 1px solid #252b4a;
  font-size: 12px; letter-spacing: 0.02em;
}
/* New L0 elements injected by openSettings 2026-06-06 — match shell Self/Kin-Board L0:
   [‹ back] [⌂ home] [identity dim] [Settings TITLE bold] ...spacer... [online pill] [✕ close] */
.jny-settings .set-l0-nav {
  color: #e8eaf5; text-decoration: none;
  font-size: 16px; line-height: 1; opacity: .9;
  padding: 2px 4px;
}
.jny-settings .set-l0-nav:hover, .jny-settings .set-l0-nav:focus { opacity: 1; outline: none; }
.jny-settings .set-l0-identity {
  font-weight: 500; opacity: .75; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 30%;
}
.jny-settings .set-l0-flex { flex: 1 1 auto; }
.jny-settings .set-l0-conn {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(80,200,120,.16); color: #7ee082;
  border: 1px solid rgba(126,224,130,.32); border-radius: 999px;
  padding: 3px 9px; font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
}
.jny-settings .set-l0-conn::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: #7ee082; display: inline-block;
}
.jny-settings .set-head h2 {
  margin: 0; font-size: 13px; font-weight: 700; opacity: 1;
  color: #e8eaf5; letter-spacing: 0.02em;
}
.jny-settings .set-close {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; min-height: 28px; border-radius: 7px;
  border: 1px solid rgba(255,255,255,.14);
  background: transparent; color: #e8eaf5;
  font-size: 16px; line-height: 1; cursor: pointer;
  transition: background .12s;
}
.jny-settings .set-close:hover { background: rgba(255,255,255,.08); }
.jny-settings .set-close:focus-visible { outline: none; background: rgba(255,255,255,.10); box-shadow: 0 0 0 2px rgba(255,255,255,.20); }
.jny-settings .set-tabs {
  display: flex; gap: 2px; padding: 6px 10px 0; overflow-x: auto;
  border-bottom: 1px solid #e7e3d3;
}
.jny-settings .set-tab {
  flex: 0 0 auto; border: none; background: transparent; color: #5b6473;
  font-weight: 700; font-size: 13px; padding: 10px 12px; min-height: 44px;
  border-bottom: 2.5px solid transparent; cursor: pointer; white-space: nowrap;
}
.jny-settings .set-tab[aria-selected="true"] { color: #122c4f; border-bottom-color: #122c4f; }
.jny-settings .set-body { flex: 1; overflow-y: auto; padding: 16px; }
.jny-settings .set-pane[hidden] { display: none; }
.jny-settings .set-pane h3 { margin: 0 0 6px; font-size: 14px; font-weight: 700; color: #122c4f; }
.jny-settings .set-muted { color: #5b6473; font-size: 13px; line-height: 1.5; margin: 0 0 14px; }
.jny-settings .set-soon { color: #5b6473; font-size: 12px; font-style: italic; margin: 14px 0 0; }
/* segmented theme control */
.jny-settings .set-seg { display: inline-flex; border: 1px solid #e7e3d3; border-radius: 999px; overflow: hidden; margin-bottom: 18px; background: #fff; }
.jny-settings .set-seg button {
  border: none; background: #fff; color: #14171f;
  font-weight: 600; font-size: 13px; padding: 9px 18px; min-height: 44px; cursor: pointer;
}
.jny-settings .set-seg button[aria-pressed="true"] { background: #122c4f; color: #fff; }
/* switch row */
.jny-settings .set-switch { display: flex; align-items: flex-start; gap: 10px; font-size: 13.5px; line-height: 1.4; cursor: pointer; color: #14171f; }
.jny-settings .set-switch input { width: 20px; height: 20px; margin-top: 1px; flex: 0 0 auto; accent-color: #122c4f; }
.jny-settings .set-switch small { display: block; color: #5b6473; font-size: 12px; }
/* action buttons */
.jny-settings .set-btn {
  display: block; width: 100%; text-align: left; margin: 0 0 10px;
  border: 1px solid #e7e3d3; border-radius: 12px; background: #fff;
  color: #14171f; font-weight: 600; font-size: 14px; padding: 13px 15px; min-height: 48px; cursor: pointer;
}
.jny-settings .set-btn small { color: #5b6473; font-weight: 400; }
.jny-settings .set-btn.primary { background: #122c4f; color: #fff; border-color: #122c4f; }
.jny-settings .set-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(18,44,79,.55); }

/* ---- Dropdown menus → LIGHT (Ogilvy reverse-text rule) ----
   The identity menu + circle-picker were dark (var(--chrome-bg)) with stacks of light-on-dark
   labels. Flip to Navy-Luxe ink-on-pearl so the menu reads easily. Appended last so these win
   by source order over the dark base rules above. */
.identity-menu, .circle-menu {
  background: #fbf9e4;
  border-color: #e7e3d3;
  color: #14171f;
  box-shadow: 0 14px 44px rgba(7,11,18,.28);
}
.identity-menu .im-header { border-bottom-color: #e7e3d3; }
.identity-menu .im-name { color: #122c4f; }
.identity-menu .im-device,
.identity-menu .im-section-label,
.identity-menu .im-muted { color: #5b6473; opacity: 1; }
.identity-menu .im-item,
.circle-menu .circle-opt { color: #14171f; }
.identity-menu .im-item:hover,
.circle-menu .circle-opt:hover { background: #efe9d2; }
.identity-menu .im-signout { color: #b3261e; }
.identity-menu .im-signout:hover { background: rgba(179,38,30,.10); }
.identity-menu .im-device-row.is-this { background: rgba(18,44,79,.10); }
.circle-menu .circle-opt.is-active { background: rgba(18,44,79,.12); color: #122c4f; }
.circle-menu .co-room { color: #5b6473; opacity: 1; }

/* ===== IDENTITY-SWAP P1 (additive) — swap slots in the account menu + manager ===== */
.im-swapset { padding: 2px 0 4px; display: flex; flex-direction: column; gap: 2px; }
.im-slot.is-active { background: rgba(80,98,199,0.15); }
.im-slot .im-muted { margin-left: auto; }
.identity-menu .im-slot.is-active { background: rgba(18,44,79,0.10); }
/* manager (reuses .device-settings backdrop + .ds-card sheet) */
.identity-manager .idm-sheet { max-width: 440px; }
.idm-head { display: flex; align-items: center; justify-content: space-between; }
.idm-close { padding: 4px 10px; }
.idm-list { display: flex; flex-direction: column; gap: 10px; margin: 10px 0; }
.idm-row { border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; }
.idm-name { font-size: 14px; font-weight: 600; }
.idm-meta { font-size: 11px; opacity: .6; margin: 2px 0 8px; }
.idm-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.idm-btn {
  font-family: inherit; font-size: 12px; padding: 6px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text); cursor: pointer;
}
.idm-btn:hover { filter: brightness(1.08); }
.idm-danger { color: #d87b7b; border-color: rgba(216,123,123,.4); }
.idm-add { width: 100%; }
.self-tag { font-size: 10px; opacity: .6; }

/* ===== caretfix global guard (2026-06-06) =====
   Clickable chrome is a single SURFACE: no text caret, no selection. Every card benefits.
   Inputs are re-enabled BELOW so they ALWAYS keep their caret + selection (last rule wins). */
.app, .hit, .ic, .lbl, .tile, [role="button"], button:not(input) {
  -webkit-user-select: none;
  user-select: none;
}
button, [role="button"], .app, .tile {
  caret-color: transparent;
}
/* re-enable real fields — never harm input (placed last + targets form controls) */
input, textarea, select, [contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
  caret-color: auto;
  pointer-events: auto;
}
