/* 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: "Jenny's 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"] {
  /* Full-sun mode. Dark text, bright bg. Max-nit screen beats reflected
     skylight — the opposite choice from dark mode for the same problem. */
  --bg:             #fafbff;
  --surface:        #ffffff;
  --surface-2:      #eef0f8;
  --text:           #0b0c1a;
  --text-dim:       #3a3d55;
  --border:         rgba(0,0,0,0.14);
  --accent:         #3a3dd6;
  --accent-strong:  #1e21b0;
  --danger:         #c0312c;
  --success:        #1f7a4e;
  --focus-ring:     0 0 0 3px #000000, 0 0 0 6px #ffffff;
  --jny-scroll-thumb:       rgba(30, 32, 80, 0.38);
  --jny-scroll-thumb-hover: rgba(30, 32, 80, 0.62);
  --jny-scroll-thumb-active:rgba(30, 32, 80, 0.85);
  --jny-scroll-track:       rgba(0,0,0,0.04);
  /* Chrome — light mode uses Indigo Deep + Honey from canonical brand palette
     (gm-brand-tokens.css). White chrome would clash with cream body and lose
     definition; Indigo Deep keeps brand identity while passing AA. */
  --chrome-bg:      #2B2D5E;        /* Indigo Deep */
  --chrome-bg-2:    #3a3d75;        /* Indigo Deep, +12% lightness */
  --chrome-text:    #F0EEE9;        /* Cloud (canonical light text on indigo) */
  --chrome-text-dim:#C9CDE3;        /* dimmed cloud */
  --chrome-border:  rgba(255,255,255,0.10);
  --chrome-accent:  #D4A84B;        /* Honey accent */
  --emer-bg:        #b03a2e;
  --emer-fg:        #b03a2e;        /* same as bg — used for headings on light cards */
}

/* 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: 8px 14px;
  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(--chrome-bg);
  border: 1px solid #2d3463;
  border-radius: 14px;
  padding: 20px;
  color: #e9eaf2;
}
.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 #2d3463;
  border-radius: 8px;
  color: #e9eaf2;
  font-size: 14px;
  font-family: inherit;
  outline: none;
}
.ds-card input[type="text"]:focus { border-color: #5062c7; }
.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: #5062c7;
  color: #fff;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  font-size: 13px;
  font-family: inherit;
}
.ds-btn:hover { background: #6172d9; }
.ds-btn-ghost { background: transparent; color: #9aa0c0; border: 1px solid #2d3463; }
.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 #2d3463;
  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: #e9eaf2;
  font-size: 14px;
}
.im-header {
  padding: 10px 10px 12px;
  border-bottom: 1px solid #2d3463;
  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: #e9eaf2;
  cursor: pointer;
  font-size: 14px;
  text-align: left;
  font-family: inherit;
}
.im-item:hover { background: #262b55; }
.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 { }

.circle-menu {
  position: fixed;
  top: 44px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--chrome-bg);
  border: 1px solid #2d3463;
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0,0,0,.5);
  z-index: 99;
  min-width: 220px;
  padding: 6px;
}
.circle-opt {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: #e9eaf2;
  cursor: pointer;
  font-size: 14px;
  text-align: left;
}
.circle-opt:hover { background: #262b55; }
.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: #9aa0c0; }

/* ─── 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: #1f2345;
  border: 1px solid #2d3463;
  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, #3c4a8a, #5062c7);
  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: #262b55;
  border-color: #3c4a8a;
}

/* Tic-Tac-Toe */
.game-back {
  background: transparent;
  color: #9aa0c0;
  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: #1f2345;
  border: 1px solid #2d3463;
  border-radius: 10px;
  color: #e9eaf2;
  font-size: 40px;
  font-weight: 700;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.ttt-cell:hover:not(:disabled) { background: #262b55; }
.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: #5062c7;
  color: #fff;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  font-size: 14px;
}
.game-reset:hover { background: #6172d9; }

/* ─── 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: #9aa0c0;
  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 #5062c7;
}

/* ─── 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 #2d3463;
  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, #e9eaf2);
  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 #2d3463;
  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 #2d3463;
  border-radius: 16px;
  padding: 28px 24px;
  color: #e9eaf2;
  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, #5062c7);
  -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 #2d3463;
  border-radius: 10px;
  color: #e9eaf2;
  font-size: 15px;
  font-family: inherit;
  outline: none;
}
.jny-login-card input:focus { border-color: #5062c7; }
.jny-login-card button {
  display: block;
  width: 100%;
  padding: 12px;
  margin-top: 6px;
  background: linear-gradient(135deg, #5062c7, #3c4a8a);
  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, #5062c7, #3c4a8a);
  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: #9aa0c0;
  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: #9aa0c0 !important;
  border: 1px solid #2d3463 !important;
  font-size: 13px !important;
}
.magic-btn:hover { color: #c9cce8 !important; border-color: #3c4a8a !important; }

.jny-login-footer {
  margin: 16px 0 0;
  text-align: center;
  font-size: 13px;
  color: #9aa0c0;
}
.jny-login-footer a {
  color: #c9cce8;
  text-decoration: none;
  border-bottom: 1px dotted #3c4a8a;
  padding-bottom: 1px;
}
.jny-login-footer a:hover { color: #ffffff; border-bottom-color: #5062c7; }

/* iOS "Add to Home Screen" hint */
.ios-install-hint {
  position: fixed;
  bottom: max(20px, env(safe-area-inset-bottom));
  left: 20px;
  right: 20px;
  background: var(--chrome-bg);
  color: #e9eaf2;
  border: 1px solid #2d3463;
  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 {
  background: #5062c7;
  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;
}
