/* ============================================================
   Platform Chrome: shared navbar, apps drawer, avatar dropdown,
   and the button system every app builds its buttons from.
   ============================================================ */

/* ============================================================
   Buttons (PL-250)

   One button system for the whole platform. Before this, eleven app
   stylesheets each carried their own, which is why a button in Workers and a
   button in vendibles sat at different heights. These values are Workers'
   values, transcribed: it was the only app with a complete set (a base, a
   primary, a small, an icon, a real disabled state and a rule for the glyph
   inside), so it was the extraction point rather than a fresh design.

   An app does not redefine these. It composes them, and anything it adds is a
   modifier that sets colour or spacing on top, never a second base.

   Two notes that are load-bearing:
   - The glyph rule is why an icon and a label line up. A button that puts a
     .material-symbols-outlined inside gets 18px here and needs nothing else.
   - :disabled is the greyed affordance, not a hidden control: the action stays
     readable, and the hover is deliberately held still so nothing invites a
     click that will not land.

   The in-flight spinner for these lives in design.css, keyed on .pf-btn, and
   covers anchors dressed as buttons as well as real ones.
   ============================================================ */
.pf-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: var(--control-h);
  padding: 5px 14px;
  border-radius: var(--control-radius);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  border: 1px solid var(--bs-border-color);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s;
}

.pf-btn:hover {
  background: var(--surface-hover);
}

/* Greyed affordance: the action is visible because the data is readable, but
   it is not permitted. The hover stays put so nothing invites the click. */
.pf-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  color: var(--text-muted);
}

.pf-btn:disabled:hover {
  background: var(--surface);
}

.pf-btn-primary {
  background: var(--brand);
  color: #fff;
  border-color: var(--brand);
}

.pf-btn-primary:hover {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
}

.pf-btn-primary:disabled,
.pf-btn-danger-solid:disabled {
  color: #fff;
}

.pf-btn-sm {
  padding: 4px 10px;
  font-size: 12px;
}

/* Destructive: outlined while it is one option among several, filled once the
   pointer is on it, so the weight arrives at the moment of the decision. */
.pf-btn-danger {
  color: var(--danger);
  border-color: var(--danger);
}

.pf-btn-danger:hover {
  background: var(--danger);
  color: #fff;
}

/* The second step. A destructive action is asked twice: the trigger is the
   outlined one above, and the confirm, the button that actually does it, is
   solid. Settings drew this pattern first and drew it by hand; it is here so
   the next app copies the pattern instead of inventing a red of its own. */
.pf-btn-danger-solid {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

.pf-btn-danger-solid:hover {
  background: var(--danger-dark);
  border-color: var(--danger-dark);
}

/* Ghost: the base without its fill, for an action sitting on a card or a
   toolbar that already has a surface of its own. */
.pf-btn-ghost {
  background: transparent;
}

/* Quiet: an action that has to be available without asking for attention. No
   fill and no visible border, but the border is kept transparent rather than
   removed, so a quiet button and a plain one sitting side by side are the same
   size and their labels line up. */
.pf-btn-quiet {
  background: transparent;
  border-color: transparent;
  color: var(--text-muted);
}

.pf-btn-quiet:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.pf-btn-outline {
  background: transparent;
  border-color: transparent;
  color: var(--brand);
  box-shadow: inset 0 0 0 1.5px var(--brand);
}

.pf-btn-outline:hover,
.pf-btn-outline.active,
.pf-btn-outline[aria-expanded="true"] {
  background: color-mix(in srgb, var(--brand) 8%, transparent);
  color: var(--brand);
}

.pf-btn-outline:disabled {
  color: var(--text-muted);
  box-shadow: inset 0 0 0 1.5px var(--bs-border-color);
}

.pf-btn-outline:disabled:hover {
  background: transparent;
}

.pf-btn .material-symbols-outlined {
  font-size: 18px;
}

/* ------------------------------------------------------------
   The inline confirm (PL-250)

   The pair that appears in place when something asks are you sure: a tick and
   a cross, side by side with the question, no dialogue and nothing to dismiss.
   Seven apps had each written their own, all 28 pixels, all round, all with the
   same hardcoded green, which is what made it the most duplicated control in
   the product. This is that control, taken from the most complete of the seven
   and given the two things only one of them had: a disabled state, because
   these buttons are disabled while the request they fired is in flight, and a
   hover that does nothing while disabled.

   The yes reads --focus, the palette's own green ramp. Those seven copies each
   hardcoded a brighter green; the system already had a green and it is this one.

   It is NOT an icon button. It says yes or no to a question that is already on
   the screen, so it is round, it is smaller, and its colour carries the answer.
   ------------------------------------------------------------ */
.pf-confirm-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pf-confirm-label {
  font-size: 13px;
  color: var(--text-secondary);
  white-space: nowrap;
}

.pf-confirm-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background 0.15s;
}

.pf-confirm-btn:disabled {
  opacity: 0.5;
  cursor: default;
}

.pf-confirm-btn .material-symbols-outlined {
  font-size: 18px;
}

.pf-confirm-yes .material-symbols-outlined {
  color: var(--focus);
}

.pf-confirm-yes:hover:not(:disabled) {
  background: var(--focus-subtle);
}

.pf-confirm-no .material-symbols-outlined {
  color: var(--danger);
}

.pf-confirm-no:hover:not(:disabled) {
  background: var(--danger-subtle);
}

/* The icon button: a glyph with a hit area and no chrome of its own, for row
   actions, toolbars and the navbar. Square by default, because that is what an
   app draws, with one modifier for the platform chrome, which draws circles.

   This is one class where there were two. Workers drew a 32 by 32 square and
   this file drew a 32 by 32 circle under a name of its own, the same control
   with two definitions and two names, which is how a navbar and an app end up
   disagreeing about what an icon button is.

   Two deliberate departures from the Workers original, both small: the
   transition, because .pf-btn already fades its background and an icon button
   that snaps beside one that fades is an inconsistency in the reference itself,
   and the colour on hover, which the chrome did not have and every app did. */
.pf-btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-h);
  height: var(--control-h);
  border-radius: var(--control-radius);
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}

.pf-btn-icon:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.pf-btn-icon:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pf-btn-icon:disabled:hover {
  background: transparent;
  color: var(--text-muted);
}

/* The size a table row and an inline confirm want. Thirteen apps had drawn one
   of these by hand before it was a class, which is thirteen apps filling in an
   absence rather than thirteen apps being wilful. Only the box shrinks: the
   glyph stays the size .pf-btn-icon gives it, because a smaller hit area does
   not mean a smaller symbol. */
.pf-btn-icon-sm {
  width: 28px;
  height: 28px;
}

/* Every button symbol in the system is 18, including the ones inside an icon
   button. This rule was held back once, because the 32 pixel icon button had
   never set a size and was rendering the icon font's own 24 pixel fallback, so
   fixing it changes 28 controls that had shipped that way. The decision was
   taken: consistency wins. The small size inherits this and needs no rule. */
.pf-btn-icon .material-symbols-outlined {
  font-size: 18px;
}

/* Chrome shape: the navbar and the platform's own surfaces draw round. */
.pf-btn-icon-round {
  border-radius: 50%;
  color: var(--text-secondary);
}

.pf-btn-icon-round:hover {
  background: var(--bg-sunken);
  color: var(--text-primary);
}

/* Connected, engaged, recording: the state the glyph itself carries. */
.pf-btn-icon-active { color: var(--brand) !important; }

/* --- Logo switching (light/dark) --- */
.pf-logo-light { display: block; }
.pf-logo-dark { display: none; }
[data-theme="dark"] .pf-logo-light { display: none; }
[data-theme="dark"] .pf-logo-dark { display: block; }

/* --- App identity in navbar --- */
.pf-brand { display: flex; align-items: center; gap: 0.5rem; text-decoration: none; }
.pf-app-badge {
  display: flex; align-items: center; gap: 0.35rem;
  font-size: 0.65rem; font-weight: 600; color: var(--text-muted);
  margin-left: 0.25rem; padding-left: 0.5rem;
  border-left: 1px solid var(--bs-border-color);
}
.pf-app-badge img { border-radius: var(--border-radius); }

/* --- Search bar --- */
.pf-search-group {
  position: absolute; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 0.5rem;
  max-width: 620px; width: 100%;
  padding: 0 1rem;
}
.pf-search-wrapper {
  flex: 1; min-width: 0;
}
.pf-search-form { width: 100%; cursor: pointer; }
.pf-search-form {
  display: flex; align-items: center; gap: 0.5rem;
  background: var(--bg-sunken); border: 1px solid transparent;
  border-radius: var(--border-radius); padding: 0.4rem 0.85rem;
  transition: border-color 0.15s, background 0.15s;
  font-family: inherit;
}
.pf-search-form:hover {
  background: var(--surface); border-color: var(--brand);
}
.pf-search-icon { color: var(--text-muted); flex-shrink: 0; }
.pf-search-input {
  border: none; background: transparent; outline: none;
  font-size: 0.8125rem; color: var(--text-muted);
  width: 100%; text-align: left;
}

/* The apps launcher sits in the search group and reads as part of the search
   control rather than as a free-standing icon, so it takes the search bar's
   sunken fill and its softer corner. The button itself is the shared
   .pf-btn-icon; this is the one place that restyles it, and it is styled by
   where it sits, not by what it does. */
.pf-search-group .pf-btn-icon {
  background: var(--bg-sunken); border-radius: var(--border-radius);
}

/* --- Dark mode toggle --- */
.pf-theme-icon-sun { display: none; }
.pf-theme-icon-moon { display: block; }
[data-theme="dark"] .pf-theme-icon-sun { display: block; }
[data-theme="dark"] .pf-theme-icon-moon { display: none; }

/* --- Avatar button --- */
.pf-avatar {
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.65rem; font-weight: 700; color: #fff;
  text-transform: uppercase; border: 2px solid var(--brand-light);
  cursor: pointer; flex-shrink: 0;
}
.pf-avatar.pf-avatar-img { padding: 0; border: none; overflow: hidden; background: none; }
.pf-avatar-photo { width: 30px; height: 30px; max-width: 30px; max-height: 30px; object-fit: cover; border-radius: 50%; display: block; }

.pf-member-card { text-align: center; padding: 8px 4px 16px; }
.pf-member-avatar { width: 64px; height: 64px; border-radius: 50%; color: #fff; font-size: 1.2rem; font-weight: 700; display: grid; place-items: center; margin: 0 auto 10px; }
.pf-member-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; overflow: hidden; display: block; }
.pf-member-name { font-size: 0.95rem; font-weight: 700; color: var(--text-primary); }
.pf-member-role { font-size: 0.78rem; color: var(--text-muted); margin-bottom: 12px; }
.pf-member-row { display: flex; align-items: center; gap: 9px; justify-content: center; font-size: 0.8rem; color: var(--text-secondary); padding: 5px 0; text-decoration: none; }
.pf-member-row:hover { color: var(--brand-dark); }
.pf-member-row .material-symbols-outlined { font-size: 17px; color: var(--text-muted); }
.pf-member-empty { font-size: 0.8125rem; color: var(--text-muted); padding: 8px 2px 16px; }

/* --- Dropdown base --- */
.pf-dropdown {
  position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--surface); border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius-lg); box-shadow: 0 8px 24px rgba(0,0,0,0.15);
  z-index: 1060; min-width: 200px;
  overflow: hidden;
}
.pf-dropdown-header {
  padding: 0.75rem 1rem 0.5rem; font-size: 0.7rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted);
}
.pf-dropdown-footer {
  padding: 0.5rem 1rem 0.75rem; text-align: center;
  border-top: 1px solid var(--bs-border-color);
}
.pf-dropdown-divider { height: 1px; background: var(--bs-border-color); margin: 0.25rem 0; }
.pf-dropdown-item {
  display: block; padding: 0.45rem 1rem; font-size: 0.8125rem;
  color: var(--text-primary); text-decoration: none;
  transition: background 0.1s;
}
.pf-dropdown-item:hover { background: var(--surface-hover); color: var(--text-primary); }
.pf-dropdown-item-danger { color: var(--danger); }
.pf-dropdown-item-danger:hover { background: var(--danger-subtle); color: var(--danger); }
button.pf-dropdown-item { width: 100%; border: 0; background: none; text-align: start; }
.pf-dropdown-item:where(:has(> .material-symbols-outlined)) { display: flex; align-items: center; gap: 0.5rem; }
.pf-dropdown-item > .material-symbols-outlined { font-size: 18px; }
.pf-dropdown .pf-confirm-row { padding: 0.3rem 1rem; }

.font-picker { position: relative; display: inline-flex; flex-shrink: 0; min-width: 0; }
.font-picker-trigger {
  display: inline-flex; align-items: center; gap: 2px; min-width: 0;
  text-align: start; cursor: pointer;
}
.font-picker-current {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.font-picker-caret { flex-shrink: 0; font-size: 1rem; color: var(--text-secondary); }
.font-picker-menu {
  position: fixed; top: 0; right: auto; z-index: 9999;
  width: 248px; max-height: 360px; flex-direction: column;
}
.font-picker-menu:not(.is-open) { display: none; }
.font-picker-menu.is-open { display: flex; }
.font-picker-search {
  flex-shrink: 0; width: 100%; height: var(--control-h); padding-inline: 0.75rem;
  border: 0; border-bottom: 1px solid var(--bs-border-color);
  background: transparent; color: var(--text-primary);
  font-family: inherit; font-size: 0.8125rem; outline: none;
}
.font-picker-results { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-bottom: 0.25rem; }
.font-picker-group { padding-top: 0.6rem; padding-bottom: 0.25rem; }
.font-picker-option { font-size: 0.875rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.font-picker-option.is-active { background: var(--surface-hover); }
.font-picker-option[aria-selected="true"] { background: var(--brand-subtle); color: var(--brand); }
.font-picker-empty { padding: 0.75rem 1rem; font-size: 0.8125rem; color: var(--text-muted); }

/* Language switcher in the account dropdown. Logical properties throughout so
   the row mirrors itself under dir="rtl" without a flipped stylesheet. */
.pf-lang { padding: 0.45rem 1rem 0.55rem; }
.pf-lang-label {
  display: block; margin-block-end: 0.35rem;
  font-size: 0.65rem; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-muted);
}
.pf-lang-pills { display: flex; gap: 0.25rem; }
.pf-lang-pills.pf-lang-busy { opacity: 0.6; }
.pf-lang-pill {
  flex: 1; padding: 0.3rem 0; border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius); background: transparent;
  font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.03em;
  color: var(--text-muted); cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
}
.pf-lang-pill:hover:not(:disabled) { background: var(--surface-hover); color: var(--text-primary); }
.pf-lang-pill:disabled { cursor: default; }
.pf-lang-pill-on {
  background: var(--brand); border-color: var(--brand); color: #fff;
}
.pf-lang-pill-on:hover:not(:disabled) { background: var(--brand); color: #fff; }

/* ============================================================
   Notification dropdown
   ============================================================ */
.pf-notif-dropdown { width: 360px; max-height: 480px; display: flex; flex-direction: column; }
.pf-notif-badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: var(--danger); color: #fff;
  font-size: 0.6rem; font-weight: 700; line-height: 16px; text-align: center;
  pointer-events: none;
}
.pf-clock-dot {
  position: absolute; top: 4px; right: 4px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--focus); border: 2px solid var(--bg);
  box-sizing: content-box; pointer-events: none;
}
.pf-notif-mark-all {
  border: none; background: none; color: var(--brand); cursor: pointer;
  font-size: 0.7rem; font-weight: 600; padding: 0;
}
.pf-notif-mark-all:hover { text-decoration: underline; }
.pf-notif-search {
  position: relative;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-notif-search-icon {
  position: absolute;
  left: 1.25rem;
  top: 50%;
  transform: translateY(-50%);
  font-size: 16px;
  color: var(--text-muted);
  pointer-events: none;
}
.pf-notif-search-input {
  width: 100%;
  padding: 0.4rem 0.6rem 0.4rem 1.85rem;
  border-radius: var(--border-radius);
  border: 1px solid var(--bs-border-color);
  background: var(--bg);
  color: var(--text-primary);
  font-size: 0.8125rem;
  outline: none;
}
.pf-notif-search-input:focus { border-color: var(--brand); }
.pf-notif-list { overflow-y: auto; flex: 1; }
.pf-notif-row {
  display: flex; align-items: stretch; color: var(--text-primary);
  transition: background 0.1s; border-bottom: 1px solid var(--bs-border-color);
  position: relative;
}
.pf-notif-row:hover { background: var(--surface-hover); color: var(--text-primary); }
.pf-notif-row-link {
  display: flex; align-items: flex-start; gap: 0.6rem;
  padding: 0.6rem 0.5rem 0.6rem 1rem; text-decoration: none;
  color: inherit; flex: 1; min-width: 0;
}
.pf-notif-row-link:hover { color: var(--text-primary); text-decoration: none; }
.pf-notif-delete {
  border: 0; background: transparent; color: var(--text-muted);
  padding: 0.4rem 0.6rem; cursor: pointer; align-self: center;
  border-radius: var(--border-radius); opacity: 0; transition: opacity 0.1s, background 0.1s;
}
.pf-notif-row:hover .pf-notif-delete { opacity: 1; }
.pf-notif-delete:hover { background: var(--surface-hover); color: var(--text-primary); }
.pf-notif-loading { padding: 2rem 1rem; text-align: center; color: var(--text-muted); font-size: 0.8125rem; }
.pf-notif-loading p { margin: 0.5rem 0 0; }
.pf-spin { animation: pf-spin 1s linear infinite; display: inline-block; }
@keyframes pf-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.pf-notif-unread { background: var(--brand-subtle); }
.pf-notif-icon-wrap {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-sunken); color: var(--text-secondary);
}
.pf-notif-content { flex: 1; min-width: 0; }
.pf-notif-title { font-size: 0.8125rem; font-weight: 500; line-height: 1.3; }
.pf-notif-body {
  font-size: 0.75rem; color: var(--text-secondary); line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pf-notif-meta { font-size: 0.65rem; color: var(--text-muted); margin-top: 2px; }
.pf-notif-app { text-transform: capitalize; }
.pf-notif-app::after { content: ' · '; }
.pf-notif-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--brand);
  flex-shrink: 0; margin-top: 6px;
}
.pf-notif-empty { padding: 2rem 1rem; text-align: center; color: var(--text-muted); font-size: 0.8125rem; }
.pf-notif-empty p { margin: 0.5rem 0 0; }
.pf-notif-view-all {
  font-size: 0.75rem; font-weight: 600; color: var(--brand);
  text-decoration: none; border: none; background: none; padding: 0; cursor: pointer;
}
.pf-notif-view-all:hover { text-decoration: underline; }
.pf-notif-footer { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.pf-notif-unread-toggle {
  display: inline-flex; align-items: center; gap: 0.5rem; margin: 0;
  font-size: 0.75rem; color: var(--text-secondary); cursor: pointer;
}
.pf-notif-modal-actions { display: flex; align-items: center; gap: 0.75rem; }
.pf-notif-toolbar {
  display: flex; align-items: center; gap: 1rem; flex-shrink: 0;
  padding-right: 1.25rem; border-bottom: 1px solid var(--bs-border-color);
}
.pf-notif-toolbar .pf-notif-search { flex: 1; border-bottom: none; padding: 0.75rem 0 0.75rem 1.25rem; }
.pf-notif-toolbar .pf-notif-search-icon { left: 1.75rem; }
.pf-notif-modal-body { padding: 0; gap: 0; }
.pf-notif-sentinel { height: 1px; }
@media (max-width: 480px) { .pf-notif-dropdown { width: calc(100vw - 2rem); right: -1rem; } }

/* ============================================================
   App Launcher — full-screen glass modal
   ============================================================ */

/* --- Overlay --- */
.al-overlay {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 8vh;
}
.al-backdrop {
  position: absolute; inset: 0;
  background: var(--veil);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

/* --- Transitions --- */
.al-enter { transition: opacity 0.15s ease; }
.al-enter-start { opacity: 0; }
.al-enter-end { opacity: 1; }
.al-leave { transition: opacity 0.12s ease; }
.al-leave-start { opacity: 1; }
.al-leave-end { opacity: 0; }

/* --- Modal --- */
.al-modal {
  position: relative; z-index: 1;
  width: 100%; max-width: 580px;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
  display: flex; flex-direction: column;
  max-height: 72vh;
  animation: al-slide-in 0.15s ease;
  overflow: hidden;
}
@keyframes al-slide-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* --- Header --- */
.al-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--bs-border-color);
}

/* --- Tabs --- */
.al-tabs { display: flex; gap: 0.25rem; }
.al-tab {
  padding: 0.3rem 0.75rem; border-radius: var(--border-radius);
  font-size: 0.75rem; font-weight: 600;
  border: none; background: transparent;
  color: var(--text-muted); cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.al-tab:hover { background: var(--bg-sunken); color: var(--text-secondary); }
.al-tab.active { background: var(--brand-subtle); color: var(--brand-dark); }

/* --- Close --- */
.al-close {
  width: 28px; height: 28px; border-radius: var(--border-radius);
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent;
  color: var(--text-muted); cursor: pointer;
}
.al-close:hover { background: var(--bg-sunken); color: var(--text-primary); }

/* --- Body --- */
.al-body {
  flex: 1; overflow-y: auto; padding: 1rem;
  scrollbar-width: none; -ms-overflow-style: none;
}
.al-body::-webkit-scrollbar { display: none; }

/* --- Grid --- */
.al-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.375rem;
}

/* --- Tile (shared) --- */
.al-tile {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: 0.3rem; padding: 0.75rem 0.5rem;
  border-radius: var(--border-radius); text-decoration: none;
  color: var(--text-primary);
  transition: background 0.1s;
}
.al-tile:hover { background: var(--surface-hover); color: var(--text-primary); }

.al-tile-icon-wrap {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
}
.al-tile-icon { border-radius: var(--border-radius-lg); }
.al-tile-name {
  font-size: 0.7rem; font-weight: 500; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 100%;
}

/* --- Catalog tile (All Apps) --- */
.al-tile-catalog {
  display: flex; flex-direction: column; align-items: center;
}
.al-tile-link {
  display: flex; flex-direction: column; align-items: center;
  gap: 0.3rem; text-decoration: none; color: var(--text-primary);
}
.al-tile-link:hover { color: var(--text-primary); }
.al-tile-link:focus-visible { outline: none; }
.al-tile-catalog:focus-within {
  background: var(--surface-hover);
  box-shadow: 0 0 0 2px var(--brand);
  border-radius: var(--border-radius);
}

/* --- Pin button --- */
.al-tile-pin {
  position: absolute; top: 4px; right: 4px;
  width: 24px; height: 24px; border-radius: var(--border-radius);
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent;
  color: var(--text-muted); cursor: pointer;
  opacity: 0.35; transition: opacity 0.1s, background 0.1s, color 0.1s;
}
.al-tile-catalog:hover .al-tile-pin { opacity: 1; }
.al-tile-pin:hover { background: var(--bg-sunken); color: var(--brand); }
.al-tile-pinned .al-tile-pin { opacity: 1; color: var(--brand); }

/* --- Unpin button (My Apps tab) --- */
.al-tile-unpin {
  position: absolute; top: 4px; right: 4px;
  width: 20px; height: 20px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: none; background: transparent;
  color: var(--text-muted); cursor: pointer;
  opacity: 0; transition: opacity 0.1s, background 0.1s;
}
.al-tile:hover .al-tile-unpin { opacity: 1; }
.al-tile-unpin:hover { background: var(--bg-sunken); color: var(--danger); }

/* --- Pin hint (All Apps tab) — frozen above the scrolling catalog --- */
.al-hint {
  flex: none;
  margin: 0;
  padding: 0.5rem 1rem 0.55rem;
  border-bottom: 1px solid var(--bs-border-color);
  background: var(--surface);
  font-size: 0.75rem; line-height: 1.5;
  color: var(--text-muted);
}
.al-hint-icon {
  font-size: 16px;
  padding: 0 0.2rem;
  color: var(--brand);
  vertical-align: -0.22em;
}

/* --- Category --- */
.al-category { margin-bottom: 1rem; }
.al-category:last-child { margin-bottom: 0; }
.al-category-label {
  font-size: 0.6875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted);
  padding-bottom: 0.5rem;
}

/* --- Empty state --- */
.al-empty {
  display: flex; flex-direction: column; align-items: center;
  gap: 0.5rem; padding: 2.5rem 1rem;
  text-align: center;
}
.al-empty p {
  margin: 0; font-size: 0.8125rem; color: var(--text-muted);
}
.al-empty-action {
  border: none; background: var(--brand-subtle);
  color: var(--brand-dark); font-size: 0.75rem; font-weight: 600;
  padding: 0.4rem 1rem; border-radius: var(--border-radius); cursor: pointer;
  transition: background 0.15s;
}
.al-empty-action:hover { background: var(--brand); color: #fff; }

/* --- Footer --- */
.al-footer {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.5rem 1rem;
  border-top: 1px solid var(--bs-border-color);
  font-size: 0.65rem; color: var(--text-muted);
}
.al-footer-hints { display: flex; align-items: center; gap: 1rem; flex-shrink: 0; }
.al-footer kbd {
  font-size: 0.6rem; font-weight: 600; font-family: inherit;
  padding: 0.1rem 0.3rem; border-radius: var(--border-radius-sm);
  background: var(--bg-sunken); color: var(--text-muted);
  border: 1px solid var(--bs-border-color);
  margin: 0 0.1rem;
}

/* --- Type-to-filter (no background, no border) --- */
.al-filter {
  display: flex; align-items: center; gap: 0.3rem;
  flex: 1; min-width: 0; overflow: hidden;
  background: none; border: none;
}
.al-filter-icon { font-size: 14px !important; color: var(--text-muted); flex-shrink: 0; }
.al-filter-text {
  font-size: 0.8rem; font-weight: 500; color: var(--text-primary);
  white-space: nowrap;
}
.al-filter-cursor {
  display: inline-block; width: 1px; height: 0.95rem;
  background: var(--text-secondary); flex-shrink: 0;
  animation: al-caret-blink 1.1s step-end infinite;
}
@keyframes al-caret-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
.al-filter-placeholder {
  font-size: 0.8rem; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* --- Responsive --- */
@media (max-width: 768px) {
  .al-modal { max-width: 95vw; max-height: 80vh; }
  .al-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 480px) {
  .al-grid { grid-template-columns: repeat(2, 1fr); }
  .al-overlay { padding-top: 4vh; }
}

/* --- Account card dropdown (Google-style) --- */
.pf-account-card { width: 280px; }
.pf-account-header {
  display: flex; flex-direction: column; align-items: center;
  padding: 1.25rem 1rem 1rem;
}
.pf-account-avatar {
  width: 64px; height: 64px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.25rem; font-weight: 700; color: #fff;
  text-transform: uppercase; margin-bottom: 0.5rem;
}
.pf-account-avatar.pf-account-avatar-img {
  padding: 0; overflow: hidden; background: none;
}
.pf-account-avatar img {
  width: 64px; height: 64px; object-fit: cover; border-radius: 50%; display: block;
}
.pf-account-name {
  font-size: 0.9rem; font-weight: 600; color: var(--text-primary);
  margin-bottom: 0.125rem; text-align: center;
}
.pf-account-email {
  font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.75rem;
  text-align: center;
}
.pf-account-manage-btn {
  display: inline-block; padding: 0.35rem 1rem;
  font-size: 0.75rem; font-weight: 600;
  color: var(--brand-dark); background: var(--brand-subtle);
  border-radius: var(--border-radius); text-decoration: none;
  transition: background 0.15s, color 0.15s;
}
.pf-account-manage-btn:hover { background: var(--brand); color: #fff; }

/* ============================================================
   App Side Navigation — shared icon-strip nav used by apps
   ============================================================ */

/* --- Layout: icon nav + main --- */
.app-layout {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: 0;
  min-height: calc(100vh - var(--nav-height, 49px));
  margin: 0 1rem;
}

@media (max-width: 768px) {
  .app-layout {
    grid-template-columns: 1fr;
  }
  .app-sidebar { display: none; }
}

/* --- Sidebar: icon strip --- */
.app-sidebar {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px 0;
  gap: 4px;
  position: sticky;
  top: var(--nav-height, 49px);
  align-self: start;
  z-index: 10;
}

/* --- Icon nav --- */
.app-sidenav {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.app-sidenav-item {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--border-radius);
  color: var(--text-secondary);
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}

.app-sidenav-item .material-symbols-outlined {
  font-size: 22px;
}

/* A divided item starts a detached group: breathing room plus a hairline
   above it (e.g. the Back to Portal exit at the bottom of an app rail). */
.app-sidenav-item-divided {
  margin-top: 18px;
}

.app-sidenav-item-divided::before {
  content: "";
  position: absolute;
  top: -10px;
  left: 6px;
  right: 6px;
  border-top: 1px solid var(--bs-border-color);
}

.app-sidenav-item:hover {
  color: var(--brand);
}

.app-sidenav-item.active {
  background: var(--brand);
  color: #fff;
}

/* Tooltip */
.app-sidenav-item[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  padding: 4px 10px;
  background: var(--brand);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  border-radius: var(--border-radius);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s;
  z-index: 10;
}

.app-sidenav-item[data-tooltip]:hover::after {
  opacity: 1;
}

/* ------------------------------------------------------------
   In-flight nav items borrow the button spinner.

   Every in-app nav is a set of <a hx-get>, so HTMX puts .htmx-request on the
   item that was clicked and takes it off once the response has swapped in. A
   view that takes a couple of seconds to fetch therefore shows feedback for
   exactly as long as the fetch takes, with nothing to wire up per item and
   nothing to clear by hand. pointer-events are dropped for the duration,
   which kills the second click that would fire a duplicate request and, on
   the icon rail, stops the hover tooltip riding over a loading icon.

   The icon is what spins, so text labels stay readable and the labelled
   strips do not reflow. Selectors cover the shared rail macro plus the four
   apps that roll their own nav (feeds, finance, crm, settings). The
   spin-loading keyframes live in design.css.
   ------------------------------------------------------------ */
.app-sidenav-item.htmx-request,
.finance-nav-item.htmx-request,
.crm-nav-item.htmx-request,
.ws-org-nav-item.htmx-request {
  pointer-events: none;
  opacity: 0.65;
}

/* Hidden rather than transparent so currentColor still resolves to the item's
   own colour: brand on a resting item, white on an active rail item. */
.app-sidenav-item.htmx-request .material-symbols-outlined,
.finance-nav-item.htmx-request .material-symbols-outlined,
.crm-nav-item.htmx-request .material-symbols-outlined,
.ws-org-nav-item.htmx-request .material-symbols-outlined {
  position: relative;
  visibility: hidden;
}

.app-sidenav-item.htmx-request .material-symbols-outlined::after,
.finance-nav-item.htmx-request .material-symbols-outlined::after,
.crm-nav-item.htmx-request .material-symbols-outlined::after,
.ws-org-nav-item.htmx-request .material-symbols-outlined::after {
  content: '';
  visibility: visible;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1em;
  height: 1em;
  margin: -0.5em 0 0 -0.5em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin-loading 0.6s linear infinite;
}

/* --- Billing banner (past-due warning) --- */
.pf-billing-banner {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.5rem 1rem;
  background: var(--danger-subtle);
  color: var(--danger);
  font-size: 0.8rem; font-weight: 500;
  border-bottom: 1px solid var(--danger);
}
.pf-billing-banner-link {
  color: var(--danger-dark);
  font-weight: 600;
  text-decoration: underline;
  margin-left: 0.25rem;
}
.pf-billing-banner-link:hover { color: var(--danger); }

/* ============================================================
   Live Rooms — full-height side panel with blurred backdrop
   ============================================================ */


/* Voice dock: wraps the navbar mic. When connected it reads as one pill
   holding a caret (opens the rooms panel) and the mic (one-click mute). */
.pf-rooms-dock { display: flex; align-items: center; gap: 2px; }
.pf-rooms-dock .pf-btn-icon { position: relative; }
.pf-rooms-dock-caret {
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: var(--control-h); padding: 0;
  border: none; cursor: pointer;
  background: var(--bg-sunken); color: var(--text-muted);
  border-radius: 999px 0 0 999px;
  transition: background 0.12s, color 0.12s;
}
.pf-rooms-dock-caret:hover { background: var(--bs-border-color); color: var(--text-primary); }
.pf-rooms-dock-mic {
  width: var(--control-h); height: var(--control-h);
  background: var(--bg-sunken); color: var(--text-secondary);
  border-radius: 0 999px 999px 0;
}
.pf-rooms-dock-mic:hover { background: var(--bs-border-color); color: var(--text-primary); }


/* Green connected dot on mic icon */
.pf-rooms-connected-dot {
  position: absolute; top: 4px; right: 4px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--focus); border: 2px solid var(--surface);
}

/* Audio blocked banner — browser autoplay policy */
.pf-audio-blocked-banner {
  position: fixed;
  top: var(--nav-height, 49px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 1060;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  background: var(--warning-subtle);
  border: 1px solid var(--warning);
  border-radius: var(--border-radius);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--warning);
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.pf-audio-blocked-banner:hover {
  background: color-mix(in srgb, var(--warning) 22%, var(--warning-subtle));
}

/* --- Offline indicator (warm banner under the navbar) --- */
.pf-offline-banner {
  position: fixed;
  top: var(--nav-height, 49px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 1070;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  background: var(--warning-subtle);
  border: 1px solid var(--warning);
  border-top: none;
  border-radius: 0 0 var(--border-radius) var(--border-radius);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--warning);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.pf-offline-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--warning);
  animation: pf-offline-pulse 1.2s ease-in-out infinite;
}
@keyframes pf-offline-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* --- Upgrade overlay (a deploy is starting) --- */
/* Above everything, including the call overlay and the form drawer: the point
   is that nothing underneath can be clicked into a server that is going away.
   It covers the viewport and changes nothing beneath it, so the page is exactly
   as the person left it when this lifts. */
.pf-frost {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.pf-upgrade-overlay {
  z-index: 2000;
}
/* No card: the mark, the spinner and the words sit straight on the overlay.
   The block only centres them and holds the line length. Type is sized
   against the lobby hero (templates/platform/lobby.html), the shell's own
   largest heading; the clamp is what keeps the title right at a phone width. */
.pf-frost-card {
  max-width: 480px;
  text-align: center;
}
.pf-frost-logo {
  height: 30px;
  width: auto;
  margin: 0 auto 1.5rem;
}
.pf-frost-title {
  margin: 1.25rem 0 0.75rem;
  font-size: clamp(1.5rem, 4.5vw, 1.85rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--text-primary);
}
.pf-frost-body {
  margin: 0 auto;
  max-width: 44ch;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--text-secondary);
}
.pf-upgrade-spinner {
  width: 36px;
  height: 36px;
  margin: 0 auto;
  border: 3px solid var(--bs-border-color);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: pf-upgrade-spin 0.9s linear infinite;
}
@keyframes pf-upgrade-spin {
  to { transform: rotate(360deg); }
}

.pf-prime-card {
  display: flex; flex-direction: column; align-items: stretch;
  width: 100%; max-width: 360px; margin: 0 auto;
}
.pf-prime-title {
  font-size: 1.25rem; font-weight: 600; color: var(--text-primary);
  margin: 0 0 0.5rem 0;
}
.pf-prime-blurb {
  font-size: 0.875rem; color: var(--text-secondary);
  margin: 0 0 1rem 0;
}
.pf-prime-need { color: var(--danger); font-weight: 700; }
.pf-prime-card .pf-btn { justify-content: center; }
.pf-prime-tiles {
  display: flex; justify-content: space-between;
  padding: 0 1rem; margin: 0 0 1.5rem 0;
}
.pf-prime-tile {
  display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
}
.pf-prime-tile img { width: 64px; height: 64px; display: block; }
.pf-prime-tile-label {
  font-size: 0.8125rem; font-weight: 700; color: var(--text-primary);
}
.pf-prime-overlay {
  position: absolute; inset: 0; z-index: 2;
  display: flex; padding: 0.75rem; overflow-y: auto;
  scrollbar-width: none;
  background: var(--surface);
}
.pf-prime-overlay::-webkit-scrollbar { display: none; }
.pf-prime-overlay .pf-prime-card { margin: auto; }
.pf-prime-overlay .pf-prime-title { font-size: 1rem; margin-bottom: 0.25rem; }
.pf-prime-overlay .pf-prime-blurb { font-size: 0.75rem; margin-bottom: 0.5rem; }
.pf-prime-overlay .pf-prime-tiles { margin-bottom: 0.75rem; }
.pf-prime-overlay .pf-prime-tile { gap: 0.25rem; }
.pf-prime-overlay .pf-prime-tile img { width: 48px; height: 48px; }
.pf-prime-overlay .pf-prime-tile-label { font-size: 0.75rem; }

.pf-rooms-devices-card {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 280px; padding: 0.875rem;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.14), 0 1px 4px rgba(0, 0, 0, 0.06);
  z-index: 10;
}
.pf-rooms-devices-card .pf-devices-list {
  max-height: 220px; overflow-y: auto;
}
.pf-rooms-devices-card .pf-devices-title {
  font-size: 0.75rem; font-weight: 700;
  color: var(--text-muted); text-transform: uppercase;
  letter-spacing: 0.04em;
}
.pf-devices-title {
  font-size: 1.25rem; font-weight: 600; color: var(--text-primary);
  margin: 0 0 0.5rem 0;
}
.pf-devices-kinds { display: flex; gap: 0.5rem; margin: 0 0 0.75rem 0; }
.pf-devices-kind {
  padding: 0.25rem 0.75rem;
  border: none; cursor: pointer;
  font-size: 0.75rem; font-weight: 500;
  background: var(--bg-sunken); color: var(--text-primary);
  border-radius: var(--border-radius-sm);
}
.pf-devices-kind:hover { background: var(--bg-hover); }
.pf-devices-kind.active { background: var(--ink); color: var(--ink-on); }
.pf-devices-list { display: flex; flex-direction: column; gap: 0.5rem; }
.pf-devices-row {
  display: flex; align-items: center; gap: 0.5rem;
  width: 100%; padding: 0.5rem 0.625rem;
  font-size: 0.8125rem; text-align: start; cursor: pointer;
  color: var(--text-primary); background: transparent;
  border: 2px solid var(--bs-border-color);
  border-radius: var(--border-radius);
}
.pf-devices-row:hover { background: var(--bg-sunken); }
.pf-devices-row.active {
  background: var(--ink); border-color: var(--ink); color: var(--ink-on);
}
.pf-devices-row .material-symbols-outlined { font-size: 20px; flex-shrink: 0; }
.pf-devices-row-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pf-devices-empty { font-size: 0.75rem; color: var(--text-muted); }

/* Speaking indicator — pulsing circular border when audio is flowing */
.pf-mic-speaking {
  animation: pf-mic-pulse 0.8s ease-in-out infinite;
  border-radius: 50%;
}
@keyframes pf-mic-pulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--brand); }
  50% { box-shadow: 0 0 0 5px var(--brand); }
}

/* Transitions */
.pf-rooms-enter { transition: opacity 0.15s ease, transform 0.15s ease; }
.pf-rooms-enter-start { opacity: 0; transform: translateY(-8px); }
.pf-rooms-enter-end { opacity: 1; transform: translateY(0); }
.pf-rooms-leave { transition: opacity 0.1s ease, transform 0.1s ease; }

/* The panel card — pinned to the right, below navbar, with consistent padding */
.pf-rooms-panel {
  position: fixed;
  top: calc(var(--nav-height) + 0.75rem);   /* the navbar, plus the panel's own padding */
  right: 0.75rem;
  bottom: 0.75rem;
  min-width: 480px;
  z-index: 1050;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius);
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.08),
    0 16px 40px rgba(0, 0, 0, 0.16);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Panel header */
.pf-rooms-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.625rem 0.75rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}

/* Pill tabs */
.pf-rooms-tabs { display: flex; gap: 0.25rem; }
.pf-rooms-tab {
  display: flex; align-items: center; gap: 0.375rem;
  padding: 0.3rem 0.75rem;
  font-size: 0.75rem; font-weight: 600;
  color: var(--text-muted);
  background: none; border: none; border-radius: var(--border-radius);
  cursor: pointer; transition: all 0.12s;
}
.pf-rooms-tab:hover { color: var(--text-primary); background: var(--bg-sunken); }
.pf-rooms-tab.active {
  color: var(--text-primary);
  background: var(--bg-sunken);
}
.pf-rooms-online-count {
  font-size: 0.625rem; font-weight: 700;
  color: var(--focus); background: color-mix(in srgb, var(--focus) 12%, transparent);
  padding: 0.0625rem 0.3125rem; border-radius: var(--border-radius);
  line-height: 1.2;
}

/* Create room button — focus purple pill */
.pf-rooms-add-btn {
  display: flex; align-items: center; gap: 0.3rem;
  padding: 0.3rem 0.75rem;
  font-size: 0.75rem; font-weight: 600;
  background: var(--brand); color: #fff;
  border: none; border-radius: var(--border-radius);
  cursor: pointer; transition: background 0.12s;
  flex-shrink: 0; white-space: nowrap;
}
.pf-rooms-add-btn:hover { background: var(--brand-dark); }

/* Floating create room card */
.pf-rooms-create-card {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 260px; padding: 0.875rem;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.14), 0 1px 4px rgba(0, 0, 0, 0.06);
  display: flex; flex-direction: column; gap: 0.5rem;
  z-index: 10;
}
.pf-rooms-create-card-title {
  font-size: 0.75rem; font-weight: 700;
  color: var(--text-muted); text-transform: uppercase;
  letter-spacing: 0.04em;
}
.pf-rooms-input {
  width: 100%; padding: 0.375rem 0.625rem;
  font-size: 0.8125rem; border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius); background: var(--surface);
  color: var(--text-primary); outline: none;
}
.pf-rooms-input:focus { border-color: var(--brand); }

/* Public/Private toggle */
.pf-rooms-type-toggle {
  display: flex; gap: 0;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius); overflow: hidden;
}
.pf-rooms-type-opt {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 0.25rem;
  padding: 0.3rem 0.5rem;
  font-size: 0.75rem; font-weight: 500;
  color: var(--text-muted);
  background: none; border: none; cursor: pointer;
  transition: all 0.12s;
}
.pf-rooms-type-opt:first-child { border-right: 1px solid var(--bs-border-color); }
.pf-rooms-type-opt:hover { color: var(--text-primary); background: var(--bg-sunken); }
.pf-rooms-type-opt.active {
  color: var(--text-primary); font-weight: 600;
  background: var(--bg-sunken);
}

/* Active room (connected) */
.pf-rooms-active {
  padding: 0.75rem 1rem;
  background: var(--bg-sunken);
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-active-header {
  display: flex; align-items: center; gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.pf-rooms-active-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--focus); flex-shrink: 0;
}
.pf-rooms-active-name {
  font-size: 0.8125rem; font-weight: 600;
  color: var(--text-primary);
}
.pf-rooms-active-participants {
  display: flex; flex-wrap: wrap; gap: 0.375rem;
  margin-bottom: 0.5rem;
}
.pf-rooms-participant {
  display: flex; align-items: center; gap: 0.25rem;
}

/* Avatar circles */
.pf-rooms-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--brand); color: #fff;
  font-size: 0.625rem; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.pf-rooms-avatar-sm {
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--brand); color: #fff;
  font-size: 0.5625rem; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; transition: box-shadow 0.2s;
}
.pf-rooms-avatar-sm.speaking {
  box-shadow: 0 0 0 2px var(--focus);
}
.pf-rooms-away {
  opacity: 0.4; filter: grayscale(0.5);
}

/* Speaking indicator */
.pf-rooms-speaking { color: var(--focus); display: flex; align-items: center; }
.pf-rooms-speaking.speaking { animation: pulse-speak 1s infinite; }
@keyframes pulse-speak {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

/* Controls */
.pf-rooms-active-controls {
  display: flex; gap: 0.5rem;
}
.pf-rooms-mute-btn, .pf-rooms-leave-btn {
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 50%;
  border: none; cursor: pointer;
  background: var(--surface); color: var(--text-primary);
  transition: background 0.15s, color 0.15s;
}
.pf-rooms-mute-btn:hover { background: var(--bs-border-color); }
.pf-rooms-mute-btn.muted { color: var(--danger); }
.pf-rooms-leave-btn { color: var(--danger); }
.pf-rooms-leave-btn:hover { background: color-mix(in srgb, var(--danger) 14%, transparent); }

/* Room list — scrollable, fills remaining space */
.pf-rooms-list {
  padding: 0.25rem 0;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.pf-rooms-row {
  padding: 0.5rem 1rem;
  cursor: pointer; transition: background 0.1s;
}
.pf-rooms-row:hover { background: var(--bg-sunken); }
.pf-rooms-row-active { background: var(--bg-sunken); }

.pf-rooms-row-header {
  display: flex; align-items: center; gap: 0.375rem;
}
.pf-rooms-row-name {
  font-size: 0.8125rem; font-weight: 500;
  color: var(--text-primary); flex: 1;
}
.pf-rooms-row-count {
  font-size: 0.6875rem; font-weight: 600;
  color: var(--focus); background: color-mix(in srgb, var(--focus) 12%, transparent);
  padding: 0.125rem 0.375rem; border-radius: var(--border-radius);
}
.pf-rooms-row-count.pf-rooms-row-count-idle {
  color: var(--text-muted); background: var(--bg-sunken);
}

.pf-rooms-row-members {
  display: flex; flex-wrap: wrap; gap: 0.25rem;
  margin-top: 0.375rem; padding-left: 1.375rem;
}

.pf-rooms-empty {
  padding: 2rem 1rem; text-align: center;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  flex: 1;
}
.pf-rooms-empty p {
  font-size: 0.8125rem; margin: 0;
}

/* Body wrapper — fills remaining space as flex column */
.pf-rooms-body {
  display: flex; flex-direction: column;
  flex: 1; min-height: 0; overflow: hidden;
}

/* Search bar */
.pf-rooms-search {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-search-icon { color: var(--text-muted); flex-shrink: 0; }
.pf-rooms-search-input {
  flex: 1; border: none; outline: none;
  font-size: 0.8125rem; background: none;
  color: var(--text-primary);
}
.pf-rooms-search-input::placeholder { color: var(--text-muted); }

/* Pagination footer */
.pf-rooms-pagination {
  display: flex; align-items: center; justify-content: center; gap: 0.75rem;
  padding: 0.5rem 1rem;
  background: var(--bg-sunken);
  border-top: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-page-btn {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--border-radius);
  border: 1px solid var(--bs-border-color);
  background: var(--surface); color: var(--text-primary);
  cursor: pointer; transition: background 0.1s;
}
.pf-rooms-page-btn:hover:not(:disabled) { background: var(--bg-sunken); }
.pf-rooms-page-btn:disabled { opacity: 0.4; cursor: default; }
.pf-rooms-page-info {
  font-size: 0.75rem; color: var(--text-muted); font-weight: 500;
}

/* --- Room detail view --- */
.pf-rooms-detail-header {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.625rem 0.75rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-back-btn {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--border-radius);
  border: none; background: none; cursor: pointer;
  color: var(--text-muted); transition: all 0.1s;
}
.pf-rooms-back-btn:hover { color: var(--text-primary); background: var(--bg-sunken); }
.pf-rooms-detail-info { flex: 1; min-width: 0; }
.pf-rooms-detail-name {
  font-size: 0.875rem; font-weight: 600; color: var(--text-primary);
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pf-rooms-detail-type {
  font-size: 0.6875rem; color: var(--text-muted); text-transform: capitalize;
}
.pf-rooms-settings-btn {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--border-radius);
  border: none; background: none; cursor: pointer;
  color: var(--text-muted); transition: all 0.1s;
}
.pf-rooms-settings-btn:hover { color: var(--text-primary); background: var(--bg-sunken); }

/* Audio controls bar */
.pf-rooms-detail-controls {
  display: flex; align-items: center;
  padding: 0.625rem 1rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-join-btn {
  display: flex; align-items: center; gap: 0.375rem;
  width: 100%; justify-content: center;
  padding: 0.5rem 1rem;
  font-size: 0.8125rem; font-weight: 600;
  background: var(--brand); color: #fff;
  border: none; border-radius: var(--border-radius);
  cursor: pointer; transition: background 0.12s;
}
.pf-rooms-join-btn:hover { background: var(--brand-dark); }

/* Settings panel */
.pf-rooms-settings-panel {
  padding: 0.625rem 1rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-settings-row { margin-bottom: 0.5rem; }
.pf-rooms-settings-row:last-child { margin-bottom: 0; }

/* Members header */
.pf-rooms-detail-members-header {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.7rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-invite-btn {
  margin-left: auto;
  display: flex; align-items: center; gap: 0.25rem;
  padding: 0.2rem 0.5rem;
  font-size: 0.6875rem; font-weight: 600;
  color: var(--brand); background: none;
  border: 1px solid var(--brand); border-radius: var(--border-radius);
  cursor: pointer; transition: all 0.1s;
}
.pf-rooms-invite-btn:hover { background: var(--brand-subtle); }

/* Invite bar */
.pf-rooms-invite-bar {
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}
.pf-rooms-invite-wrap { position: relative; }
.pf-rooms-invite-dropdown {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 20;
  background: var(--surface); border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius-lg); box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  max-height: 200px; overflow-y: auto; margin-top: 0.25rem;
}
.pf-rooms-invite-item {
  display: flex; align-items: center; gap: 0.5rem; width: 100%;
  padding: 0.375rem 0.625rem; border: none; background: none;
  cursor: pointer; text-align: left; color: var(--text-primary);
}
.pf-rooms-invite-item:hover { background: var(--bg-hover); }
.pf-rooms-invite-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.65rem; font-weight: 600; color: #fff;
}
.pf-rooms-invite-info { display: flex; flex-direction: column; min-width: 0; }
.pf-rooms-invite-name { font-size: 0.75rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-rooms-invite-email { font-size: 0.65rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-rooms-invite-empty { padding: 0.5rem 0.625rem; font-size: 0.75rem; color: var(--text-muted); text-align: center; }

/* Member row in detail view */
.pf-rooms-member-row {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.5rem 1rem;
  transition: background 0.1s;
}
.pf-rooms-member-row:hover { background: var(--bg-sunken); }
.pf-rooms-detail-role {
  font-size: 0.625rem; font-weight: 600;
  color: var(--focus); background: var(--focus-subtle);
  padding: 0.0625rem 0.375rem; border-radius: var(--border-radius);
  margin-left: 0.25rem;
  align-self: flex-start;
}
.pf-rooms-connected-badge {
  font-size: 0.625rem; color: var(--focus);
  background: color-mix(in srgb, var(--focus) 12%, transparent);
  padding: 0.0625rem 0.375rem; border-radius: var(--border-radius);
  margin-left: auto;
}
.pf-rooms-kick-btn {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: var(--border-radius);
  border: none; background: none; cursor: pointer;
  color: var(--text-muted); opacity: 0;
  transition: all 0.1s;
}
.pf-rooms-member-row:hover .pf-rooms-kick-btn { opacity: 1; }
.pf-rooms-kick-btn:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }

/* Online tab — member rows */
.pf-rooms-online-row {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.5rem 1rem;
  transition: background 0.1s;
}
.pf-rooms-online-row:hover { background: var(--bg-sunken); }
.pf-rooms-online-info {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
}
.pf-rooms-online-name {
  font-size: 0.8125rem; font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pf-rooms-online-room {
  font-size: 0.6875rem; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Responsive — on smaller screens, panel takes more width */
@media (max-width: 576px) {
  .pf-rooms-panel {
    min-width: unset;
    width: calc(100vw - 1.5rem);
    left: 0.75rem;
  }
}

/* --- Main content --- */
.app-main {
  padding: 1rem 1.5rem;
  min-height: calc(100vh - var(--nav-height, 49px));
}

/* --- Normalized app tab group (pill style) ---
   The canonical tab-group pattern for app pages, factored out of leaves' .leaves-tab so
   new surfaces share one look instead of each reinventing it. Server- or Alpine-driven:
   mark the current tab with .is-active. */
.app-tabs {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: var(--surface-hover);
  border-radius: var(--border-radius);
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
}
.app-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: var(--border-radius);
  border: none;
  background: none;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s, color 0.15s;
  text-decoration: none;
}
.app-tab:hover:not(:disabled) {
  background: var(--surface);
  color: var(--text-primary);
}
.app-tab.is-active {
  background: var(--surface);
  color: var(--text-primary);
  font-weight: 600;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
.app-tab:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* --- Call ringing overlay (platform-wide) --- */
.pf-ringing-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--veil);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: pf-ringing-fadein 0.2s;
}
@keyframes pf-ringing-fadein {
  from { opacity: 0; }
  to { opacity: 1; }
}
.pf-ringing-card {
  background: var(--surface);
  border-radius: var(--border-radius-lg);
  padding: 2.5rem 3rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.3);
  position: relative;
}
.pf-ringing-avatar {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  font-weight: 700;
  color: #fff;
  overflow: hidden;
  z-index: 2;
  position: relative;
}
.pf-ringing-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.pf-ringing-pulse {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 96px;
  height: 96px;
  margin-top: -48px;
  margin-left: -48px;
  border-radius: 50%;
  border: 2px solid var(--brand);
  animation: pf-ringing-pulse-anim 1.5s ease-out infinite;
  z-index: 1;
}
@keyframes pf-ringing-pulse-anim {
  0% { transform: scale(1); opacity: 0.6; }
  100% { transform: scale(1.8); opacity: 0; }
}
.pf-ringing-name {
  margin: 1.25rem 0 0.25rem;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-primary);
}
.pf-ringing-label {
  margin: 0 0 1.5rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.pf-ringing-actions {
  display: flex;
  gap: 2rem;
}
.pf-ringing-btn {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  transition: transform 0.15s;
}
.pf-ringing-btn:hover {
  transform: scale(1.1);
}
.pf-ringing-btn .material-symbols-outlined {
  font-size: 28px;
}
.pf-ringing-decline {
  background: var(--danger);
}
.pf-ringing-accept {
  background: var(--focus);
}

/* ===================================================================
   Access wall — permission-denied / page-not-found workscreen card
   Shown when a tab load fails with 403 or 404.
   =================================================================== */
.access-wall {
  display: flex; align-items: center; justify-content: center;
  min-height: 100%;
  padding: 2rem;
}
.access-wall-card {
  max-width: 440px;
  width: 100%;
  text-align: center;
  padding: 2.5rem 2rem;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius);
  box-shadow: 0 1px 2px rgba(20, 18, 16, 0.06);
}
[data-theme="dark"] .access-wall-card {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.access-wall-icon {
  width: 64px; height: 64px;
  margin: 0 auto 1rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--brand-subtle);
  color: var(--brand-dark);
}
.access-wall-icon .material-symbols-outlined {
  font-size: 32px;
}
.access-wall-title {
  font-size: 1.125rem;
  font-weight: 600;
  margin: 0 0 0.5rem;
  color: var(--text-primary);
}
.access-wall-body {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0 0 1.5rem;
  line-height: 1.5;
}
.access-wall-request {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  text-align: left;
}
.access-wall-message {
  width: 100%;
  min-height: 72px;
  padding: 0.6rem 0.75rem;
  font: inherit;
  font-size: 0.8125rem;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--border-radius);
  resize: vertical;
  background: var(--bg-sunken);
  color: var(--text-primary);
}
.access-wall-message:focus {
  outline: none;
  border-color: var(--brand);
  background: var(--surface);
}
.access-wall-actions {
  display: flex;
  justify-content: flex-end;
}
.access-wall-btn {
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  padding: 0.5rem 1.1rem;
  border-radius: var(--border-radius);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.access-wall-btn:disabled { opacity: 0.6; cursor: wait; }
.access-wall-btn-primary {
  background: var(--brand);
  color: #fff;
}
.access-wall-btn-primary:hover:not(:disabled) {
  background: var(--brand-dark);
}
.access-wall-error {
  margin: 0;
  font-size: 0.75rem;
  color: var(--danger);
}
.access-wall-sent {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.6rem 0.75rem;
  border-radius: var(--border-radius);
  background: var(--focus-subtle);
  color: var(--focus-dark);
  font-size: 0.8125rem;
  font-weight: 500;
}
[data-theme="dark"] .access-wall-sent {
  color: var(--focus);
}
.access-wall-sent .material-symbols-outlined {
  font-size: 18px;
}
