/* Post-bundle theme layer. Loaded after the compiled Tailwind stylesheet
 * to remap v4 palette tokens without rebuilding the React source.
 * To revert: remove the <link> tag in index.html and delete this file. */

:root {
  /* Layered warm-dark palette */
  --loaf-surface-0: #0b0b10;
  --loaf-surface-1: #13131a;
  --loaf-surface-2: #1b1b24;
  --loaf-surface-3: #222230;

  --loaf-border-subtle:  rgba(255, 255, 255, 0.04);
  --loaf-border-default: rgba(255, 255, 255, 0.08);
  --loaf-border-strong:  rgba(255, 255, 255, 0.14);

  --loaf-text-primary:   #f2f2f5;
  --loaf-text-secondary: #b8b8c2;
  --loaf-text-tertiary:  #72727e;
  --loaf-text-disabled:  #4a4a55;

  /* Remap bundle tokens onto the new layers. */
  --color-bg-primary:   var(--loaf-surface-0);
  --color-bg-secondary: var(--loaf-surface-1);
  --color-bg-tertiary:  var(--loaf-surface-2);
  --color-bg-elevated:  var(--loaf-surface-2);
  --color-bg-overlay:   var(--loaf-surface-3);

  --color-card-bg:       var(--loaf-surface-1);
  --color-card-elevated: var(--loaf-surface-2);
  --color-card-inner:    var(--loaf-surface-0);

  --color-input-bg:          var(--loaf-surface-1);
  --color-input-border:      var(--loaf-border-default);
  --color-input-placeholder: var(--loaf-text-tertiary);

  --color-sidebar-bg:           var(--loaf-surface-1);
  --color-sidebar-active:       var(--loaf-surface-2);
  --color-sidebar-hover:        var(--loaf-surface-2);
  --color-sidebar-border:       var(--loaf-border-subtle);
  --color-sidebar-divider:      var(--loaf-border-subtle);
  --color-sidebar-footer-bg:    var(--loaf-surface-1);
  --color-sidebar-text:         var(--loaf-text-secondary);
  --color-sidebar-text-active:  var(--loaf-text-primary);
  --color-sidebar-section:      var(--loaf-text-tertiary);
  --color-sidebar-section-text: var(--loaf-text-tertiary);

  --color-border-muted:   var(--loaf-border-subtle);
  --color-border-default: var(--loaf-border-default);

  --color-text-primary:   var(--loaf-text-primary);
  --color-text-secondary: var(--loaf-text-secondary);
  --color-text-tertiary:  var(--loaf-text-tertiary);

  /* Muted semantic palette — dial saturation back from web defaults */
  --color-status-success: #4ade80;
  --color-status-warning: #e0a23f;
  --color-status-error:   #e06565;
  --color-status-info:    #6b9adf;

  /* Power controls — desaturated flat fills */
  --color-power-start:   #2d7a4f;
  --color-power-restart: #b8751f;
  --color-power-stop:    #8a6e2a;
  --color-power-kill:    #a04545;

  /* Quieter hero surface */
  --color-hero-from: #15151c;
  --color-hero-via:  #1a1a24;
  --color-hero-to:   #0b0b10;
}

html, body {
  background-color: var(--loaf-surface-0);
  color: var(--loaf-text-primary);
}

/* Page-level warm glow + static grain. Pseudo-layers sit under #root
 * so content stays interactive. color-mix falls back gracefully if the
 * accent var isn't set yet. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    60vw 60vh at 0% 100%,
    color-mix(in oklch, var(--color-accent-500, #7c5cff) 30%, transparent) 0%,
    transparent 62%
  );
  opacity: 0.16;
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.022;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.65 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 180px 180px;
}
#root { position: relative; z-index: 1; }

/* Inner top-edge highlight — simulates light hitting the card's top lip.
 * Uses inset box-shadow so it stacks with any existing borders without
 * nudging layout. */
[class*="bg-card-bg"],
[class*="bg-bg-secondary"],
[class*="bg-bg-tertiary"],
[class*="bg-bg-elevated"],
[class*="bg-bg-overlay"],
[class*="bg-card-elevated"],
[class*="bg-sidebar-footer-bg"] {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.045);
}

/* Sidebar active item: 2px accent left-stripe, inset so it doesn't
 * shift width. The surface fill comes from --color-sidebar-active above. */
[class*="bg-sidebar-active"] {
  box-shadow:
    inset 2px 0 0 var(--color-accent-500, #7c5cff),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

/* Soften stacked borders: if an element is a surface AND has an explicit
 * border utility, halve its visual weight by relying on elevation. */
[class*="bg-card-bg"][class*="border"],
[class*="bg-bg-secondary"][class*="border"] {
  border-color: var(--loaf-border-subtle) !important;
}

/* Typography: lighter heading weight + slight negative tracking.
 * Scoped to headings that receive the bold/extrabold utilities so we
 * don't touch body copy. */
h1.font-extrabold,
h1.font-bold,
h2.font-extrabold,
h2.font-bold {
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Uppercase eyebrow labels — tighten Tailwind's default wider tracking */
.uppercase.tracking-wider,
.uppercase.tracking-widest {
  letter-spacing: 0.055em !important;
}

/* Numeric stat readouts — tabular alignment so values don't jitter */
.font-mono, [class*="font-mono"] { font-variant-numeric: tabular-nums; }

/* Input focus — subtle accent glow instead of ring */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[contenteditable="true"]:focus-visible {
  outline: none;
  border-color: var(--color-accent-500, #7c5cff) !important;
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-accent-500, #7c5cff) 18%, transparent);
}

/* Narrow micro-interaction transitions — only on interactive elements,
 * never on spinners or SVG internals. */
a, button, [role="button"], [role="link"], [role="menuitem"], [role="tab"],
input, select, textarea, summary, label[for] {
  transition-property: background-color, border-color, color, box-shadow, transform;
  transition-duration: 150ms;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.animate-spin, .animate-pulse { transition: none !important; }

/* Clickable-card lift: apply only when a card surface sits inside a
 * link or button (i.e. actually clickable), never on static cards. */
a:hover > [class*="bg-card-bg"],
a:hover [class*="bg-card-bg"],
button:hover > [class*="bg-card-bg"],
button:hover [class*="bg-card-bg"] {
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 0 0 1px color-mix(in oklch, var(--color-accent-500, #7c5cff) 24%, transparent);
}

/* Terminal / console viewport: deepen fill to surface-0 so it reads as
 * recessed. Matches the `.bg-card-inner` the bundle already uses. */
[class*="bg-card-inner"] {
  background-color: var(--loaf-surface-0) !important;
  box-shadow: inset 0 0 0 1px var(--loaf-border-subtle);
}

/* Status pills using semantic bg+text — tint backgrounds at low opacity
 * so pills feel calm rather than shouted. Works by scoping to classes
 * that combine a status background with the paired text color. */
[class*="bg-status-success"]:not([class*="text-"]),
[class*="bg-green-"]:not([class*="text-"]) {
  background-color: color-mix(in oklch, var(--color-status-success) 14%, transparent) !important;
  color: var(--color-status-success) !important;
}
[class*="bg-status-error"]:not([class*="text-"]),
[class*="bg-red-"]:not([class*="text-"]) {
  background-color: color-mix(in oklch, var(--color-status-error) 14%, transparent) !important;
  color: var(--color-status-error) !important;
}
[class*="bg-status-warning"]:not([class*="text-"]) {
  background-color: color-mix(in oklch, var(--color-status-warning) 14%, transparent) !important;
  color: var(--color-status-warning) !important;
}

/* Crisp live-chat bubble — keep it out of the accent's way */
#crisp-chatbox iframe { color-scheme: dark; }

/* ─────────────────────────────────────────────────────────────────────
 * Collapsed-sidebar tooltips.
 * The sidebar renders `<span class="sidebar-item-text">Label</span>` inside
 * each nav item; when `.loaf-sidebar.collapsed` is set, that span gets
 * `display:none`. We echo the same label on `.sidebar-nav-item[data-loaf-tip]`
 * (stamped by loaf-theme-helpers.js) and show it as a ::after pill after a
 * 200ms hover delay.
 *
 * Footer icon buttons (`.sidebar-footer-btn`) are always icon-only, so their
 * tooltip fires regardless of `.collapsed` — the helper stamps them too.
 *
 * Tooltip uses position:fixed + JS-set --loaf-tip-{x,y} so it escapes any
 * ancestor overflow / transform. */
/* v5.0.67 — tooltip rendered as a portaled DOM element in helpers.js
 * (see [data-loaf-tip-portal] below) so the tooltip is never clipped by
 * the sidebar's scroll container or any other stacking context. The
 * ::after-based rules that used to live here have been removed. */

/* Suppress footer tooltips on mobile — the drawer is full-width so there's
 * no room to the side for a pill, and the footer icons already have visible
 * labels in the expanded mobile drawer. */
@media (max-width: 767px) {
  .sidebar-footer-btn[data-loaf-tip]::after { display: none; }
}

/* ─────────────────────────────────────────────────────────────────────
 * Mobile drawer overflow fix (sidebarphonebug.png).
 *
 * `.loaf-sidebar` is `flex h-screen flex-col pb-24` with no scroll on its
 * nav list wrapper (`<div class="flex-1 py-2">`). When the nav is longer
 * than the viewport, items spill out of the bottom and the sidebar-footer
 * (position:fixed bottom:0) sits on top of them.
 *
 * Fix: let the `.flex-1` nav wrapper scroll, and reserve space for the
 * fixed footer so the scroll range stops above it. */
@media (max-width: 767px) {
  .loaf-sidebar.mobile-open {
    /* Make room for mobile topbar (56px) so the drawer header isn't
     * hidden behind it. */
    padding-top: 56px;
    /* pb-24 (96px) already gives footer room; keep it. */
  }
  /* The sidebar's body is the lone `.flex-1` direct child of the aside.
   * Give it its own scroll so overflowing items stay within the drawer. */
  .loaf-sidebar.mobile-open > .flex-1 {
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 12px;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * Tour callout + halo always above the drawer overlay (z:51/52).
 * The tour bundle already uses z-index:110/112 but reinforce here in case
 * another overlay (modal, chat widget) crowds the stack. */
.loaf-tour-overlay,
.loaf-tour-halo { z-index: 200 !important; }
.loaf-tour-callout { z-index: 201 !important; }

/* ─────────────────────────────────────────────────────────────────────
 * SFTP modal layout fix (sftpspace.png — big empty stretch in the left
 * column because the intro text only fills ~25% of the height while the
 * right column holds 3 fields + warning + buttons + helper paragraph).
 *
 * Strategy: helpers.js stamps [data-loaf-sftp-modal] on the dialog root.
 * On desktop we align the left column to the top so its content doesn't
 * stretch, and relocate the long helper paragraph underneath the intro so
 * the vertical balance improves. On mobile we collapse to a single
 * column. */
[data-loaf-sftp-modal] {
  /* The modal body uses inline grid; override column sizing to bias
   * toward the right (fields) column. */
  grid-template-columns: minmax(180px, 0.9fr) minmax(280px, 1.1fr) !important;
  align-items: start !important;
}
[data-loaf-sftp-modal] > div:first-of-type { align-self: start !important; }

@media (max-width: 767px) {
  [data-loaf-sftp-modal] {
    display: flex !important;
    flex-direction: column !important;
    gap: 18px !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * Mobile viewport safety net (<768px).
 *
 * Symptoms (overflowactivity.png, cutoff1.png, cutoff2.png):
 *   - activity rows stack icon + title + actor + tag + IP horizontally
 *     and overlap because row width is narrower than the sum of parts
 *   - quick-action tile grids overflow horizontally past the viewport
 *   - hero cards truncate with "…" when they could wrap
 *   - various buttons and toolbars don't wrap cleanly
 *
 * Approach: scoped @media block that:
 *   1. Clamps the page root so nothing escapes viewport width.
 *   2. Forces `min-width: 0` on common flex children so text-overflow
 *      doesn't cascade into layout breakage.
 *   3. Allows flex rows to wrap where a "wrap" modifier was never set.
 *   4. Activity log rows stack their sub-regions vertically.
 */
@media (max-width: 767px) {
  /* Kill horizontal scroll at the page root. */
  html, body, #root { max-width: 100vw; overflow-x: hidden; }

  /* Main content area: let it breathe to the edges without forcing a
   * desktop min-width. */
  .loaf-main-content {
    padding-left: 14px !important;
    padding-right: 14px !important;
  }

  /* `min-width: 0` on flex children prevents text-overflow:ellipsis
   * children from blowing out the flex basis of their parent. This is
   * what causes the "Welcome to Loaf Panel v5.0.60" banner + status
   * cards to overflow on small screens. */
  .loaf-main-content * { min-width: 0; }

  /* Hero / welcome banner: drop the giant padding and let it wrap. */
  [class*="loaf-dash-hero"],
  [class*="loaf-welcome"],
  [class*="loaf-dash-welcome"] {
    padding: 18px 16px !important;
  }
  [class*="loaf-dash-hero"] h1,
  [class*="loaf-welcome"] h1 { font-size: 22px !important; line-height: 1.15 !important; }

  /* Generic grid columns that were `repeat(2, 1fr)` on desktop collapse
   * to a single column on mobile so nothing overflows. Covers "Billing
   * Links", "Quick actions", "Status + Maintenance" style pairs. */
  [class*="loaf-dash-"][class*="grid"],
  [class*="quick-access-grid"],
  [class*="dash-grid"],
  [class*="grid-2"],
  [class*="grid-3"],
  [class*="grid-4"] {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }

  /* Generic row-of-buttons: allow wrapping. Targets any flex row with
   * 2+ buttons as children (toolbars, action rows, button strips). */
  [class*="loaf-"] > div[style*="display: flex"]:has(> button + button) { flex-wrap: wrap !important; }

  /* Page-title hero strips — wrap instead of overflow. */
  [class*="loaf-hero"] { flex-wrap: wrap !important; gap: 10px !important; }

  /* Activity log row (overflowactivity.png) — its grid columns collapse
   * to vertical stack. Selector matches the canonical activity-row
   * structure used in Account Activity, Server Activity, and the bench
   * Activity Feed widget. */
  [class*="loaf-activity-row"],
  [class*="activity-row"],
  [data-loaf-activity-row] {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 6px !important;
    padding: 12px 14px !important;
  }
  [class*="loaf-activity-row"] > *,
  [class*="activity-row"] > *,
  [data-loaf-activity-row] > * {
    width: 100% !important;
    max-width: 100% !important;
  }
  /* The event-type pill (e.g. "server.mod.reorder") was overlapping the
   * title. Give it its own line and shrink the font so long event names
   * don't wrap awkwardly. */
  [class*="loaf-activity-row"] [class*="event-tag"],
  [class*="activity-row"] [class*="event-tag"],
  [class*="loaf-activity-row"] [class*="event-pill"],
  [class*="activity-row"] [class*="event-pill"] {
    display: inline-block !important;
    font-size: 10px !important;
    padding: 2px 6px !important;
    max-width: 100% !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
  }

  /* Power-control popover (powerbuttonbug.png): the dropdown shouldn't
   * sit directly over the server header. Nudge it down a hair so it's
   * clearly separated from the button strip. */
  [class*="loaf-power-menu"],
  [class*="power-control-popover"] { margin-top: 6px !important; }

  /* Mobile topbar: hide the footer tooltip pill (already handled) and
   * ensure the topbar title truncates instead of wrapping. */
  .loaf-mobile-topbar-title {
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
    min-width: 0 !important;
    flex: 1 1 auto !important;
  }

  /* Tables: make them horizontally scrollable inside a container instead
   * of blowing out the viewport. */
  .loaf-main-content table { display: block; max-width: 100%; overflow-x: auto; }

  /* Long raw text blocks (log snippets, JSON previews) should wrap. */
  .loaf-main-content pre,
  .loaf-main-content code { white-space: pre-wrap !important; word-break: break-word !important; }
}

/* ─────────────────────────────────────────────────────────────────────
 * Mobile file editor UX (very mobile-friendly per request).
 *
 * The Monaco-based file editor on phone was unusable: toolbar icons
 * crammed into a single row, no room for content, save buttons hidden,
 * and the editor area itself was sub-viewport.
 *
 * Strategy:
 *   1. helpers.js stamps [data-loaf-file-editor-mobile] on the editor
 *      wrapper so our CSS is scoped.
 *   2. Sticky header with large touch targets (44px min).
 *   3. Editor fills the remaining viewport.
 *   4. Sticky "Save" footer bar always in reach of the thumb.
 *   5. Font size bumped to 14px so code is readable.
 *   6. Editor toolbar wraps and buttons get proper tap size.
 */
@media (max-width: 767px) {
  /* Editor page header (back + Save + Save & Close) — sticky to the top
   * of the viewport so they're always reachable. */
  [data-loaf-file-editor-mobile] [class*="file-editor-header"],
  [data-loaf-file-editor-mobile] > header,
  .loaf-file-editor-root > header {
    position: sticky !important;
    top: 56px !important; /* clear the mobile topbar */
    z-index: 40 !important;
    background: var(--color-bg-primary, #13131a) !important;
    padding: 10px 14px !important;
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 8px !important;
    border-bottom: 1px solid var(--color-border-default, #2b2b36) !important;
  }

  /* All header buttons: 44px min tap target, equal flex so they fit
   * neatly in a wrapped row. */
  [data-loaf-file-editor-mobile] button,
  .loaf-file-editor-root button {
    min-height: 44px !important;
    min-width: 44px !important;
    font-size: 13px !important;
    padding: 8px 12px !important;
  }

  /* The Monaco editor container itself — fill the remaining viewport
   * minus topbar (56px) + sticky header (~60px) + sticky save footer
   * (60px). Using dvh so iOS Safari's dynamic viewport math is right. */
  [data-loaf-file-editor-mobile] .monaco-editor,
  .loaf-file-editor-root .monaco-editor {
    min-height: calc(100dvh - 180px) !important;
    font-size: 14px !important;
  }

  /* Bump Monaco's default text size for on-screen readability. */
  [data-loaf-file-editor-mobile] .monaco-editor .view-line,
  [data-loaf-file-editor-mobile] .monaco-editor .inputarea {
    font-size: 14px !important;
  }

  /* Any "Save" floating action / bar injected by the app: pin to the
   * bottom edge so it's always reachable. */
  [data-loaf-file-editor-mobile] [class*="save-bar"],
  [data-loaf-file-editor-mobile] [class*="editor-footer"],
  .loaf-file-editor-root [class*="save-bar"] {
    position: sticky !important;
    bottom: 0 !important;
    z-index: 40 !important;
    background: var(--color-bg-primary, #13131a) !important;
    border-top: 1px solid var(--color-border-default, #2b2b36) !important;
    padding: 10px 14px env(safe-area-inset-bottom, 10px) 14px !important;
  }

  /* Breadcrumb / path row above the editor — truncate long paths,
   * wrap if needed. */
  [data-loaf-file-editor-mobile] [class*="breadcrumb"] {
    flex-wrap: wrap !important;
    font-size: 12px !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * Console font-size toolbar (fontsizebug.png) — the A+/A- controls had
 * no label, just raw icons in a tight row. Give them room to breathe on
 * mobile and add a subtle divider between tool clusters. */
@media (max-width: 767px) {
  [class*="loaf-console-toolbar"],
  [class*="console-toolbar"] {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 4px !important;
    padding: 6px !important;
  }
  [class*="loaf-console-toolbar"] button,
  [class*="console-toolbar"] button {
    min-width: 36px !important;
    min-height: 36px !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * Global Seasonings toggle button (helpers.js injects it into the
 * mobile topbar / sidebar footer). */
.loaf-global-seasonings-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  border-radius: 8px;
  border: 1px solid var(--color-border-default);
  background: var(--color-card-inner, rgba(255,255,255,0.03));
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.loaf-global-seasonings-toggle:hover { background: var(--color-sidebar-hover); color: var(--color-text-primary); }
.loaf-global-seasonings-toggle[aria-pressed="true"] {
  background: color-mix(in srgb, var(--color-accent-600) 25%, transparent);
  border-color: var(--color-accent-600);
  color: var(--color-accent-400);
}
.loaf-global-seasonings-canvas {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  z-index: 0;
}

/* ─────────────────────────────────────────────────────────────────────
 * Toast container reposition (blockedlog.png — toasts were landing
 * bottom-right directly under the Crisp chat bubble). The bundle uses
 * `.fixed.bottom-4.right-4.z-[100]` for the container. Re-anchor to
 * bottom-center so the chat widget never covers them. */
div.fixed.bottom-4.right-4.z-\[100\] {
  right: 50% !important;
  bottom: 24px !important;
  transform: translateX(50%) !important;
  max-width: min(440px, calc(100vw - 24px));
  align-items: center;
}
/* Belt-and-braces: any fixed element whose className starts with the
 * same trio (in case Tailwind reorders). */
div[class~="fixed"][class~="bottom-4"][class~="right-4"] {
  right: 50% !important;
  bottom: 24px !important;
  transform: translateX(50%) !important;
  max-width: min(440px, calc(100vw - 24px));
  align-items: center;
}
@media (max-width: 767px) {
  div.fixed.bottom-4.right-4.z-\[100\],
  div[class~="fixed"][class~="bottom-4"][class~="right-4"] {
    bottom: 88px !important; /* clear Crisp bubble + safe area */
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * Server page + server-card mobile cleanup (yourserversbug.png,
 * consoleoverflow.png, filemanagermobile.png).
 *
 * Shared cause: server header stats strip + server cards + toolbars were
 * all built for desktop row layouts and collapse badly below ~500px.
 * Fixes are scoped to <768px and use class-name-adjacent selectors
 * ([class*=...]) because many parts of the bundle are inline-styled.
 */
@media (max-width: 767px) {
  /* Server cards grid on Your Servers page (className stamped in source
   * at v5.0.63 so CSS can override the inline gridTemplateColumns). */
  .loaf-servers-cards-grid {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }
  /* Per-card stat tiles (CPU / RAM / DISK) — keep 3 columns but tighten
   * padding + font so nothing overflows on a single-column mobile card. */
  .loaf-server-card-stats {
    padding: 10px !important;
    gap: 6px !important;
  }
  .loaf-server-card-stats > * {
    font-size: 11px !important;
    min-width: 0;
    overflow: hidden;
  }
  /* Server card internals: stat row (CPU / RAM / DISK) stacks cleanly
   * when the card has breathing room. Ensure the stat labels + values
   * are truncated if the card gets really narrow. */
  [class*="server-card"] [class*="stat"] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* Card bottom action row — let the server name + Manage button wrap
   * rather than overlap. */
  [class*="server-card"] [class*="card-footer"],
  [class*="server-card"] [class*="card-actions"] {
    flex-wrap: wrap !important;
    gap: 8px !important;
  }

  /* ServerHeaderBar — top grid (title + actions) stacks vertically on
   * mobile so the action icons don't push the title off-screen. */
  .loaf-server-header-grid {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }
  /* Bottom inline-stat row (Uptime · CPU · RAM · Disk · Players) — was
   * gap:22px in a flex row and overflowed at <380px. Wrap + shrink. */
  .loaf-server-header-stats {
    flex-wrap: wrap !important;
    gap: 8px 14px !important;
    font-size: 11px !important;
  }
  .loaf-server-header-stats > * {
    min-width: 0;
  }

  /* Server header's power action chip strip (Start/Restart/Stop/Kill) —
   * push to its own row, allow wrapping, shrink chips so they all fit. */
  .loaf-server-power-row,
  [class*="power-action-row"],
  [class*="loaf-power-"] {
    flex-wrap: wrap !important;
    gap: 6px !important;
  }
  .loaf-server-power-row button,
  [class*="power-action-row"] button,
  [class*="loaf-power-"] button {
    flex: 1 1 auto;
    min-width: 0 !important;
    font-size: 11px !important;
    padding: 6px 10px !important;
  }

  /* File Manager toolbar (SFTP / Upload / New Folder / New File / Menu). */
  .loaf-filemanager-toolbar {
    flex-wrap: wrap !important;
    gap: 6px !important;
    align-items: stretch !important;
  }
  .loaf-filemanager-toolbar button {
    flex: 0 1 auto;
    font-size: 11px !important;
    padding: 6px 10px !important;
    white-space: nowrap;
  }

  /* SortLink row in FileManager. Was gap:24px in a flex-row which forced
   * the labels to wrap mid-word at <380px. Let the row wrap + keep each
   * label no-wrap. */
  .loaf-filemanager-sort {
    flex-wrap: wrap !important;
    gap: 8px 12px !important;
    padding: 12px !important;
  }
  .loaf-filemanager-sort > * {
    white-space: nowrap !important;
  }

  /* Console body — terminal area should have room to breathe on mobile
   * (user complained lines get cut off). Bump height + ensure wrap. */
  [class*="loaf-console-viewport"],
  [class*="console-viewport"],
  [class*="xterm-screen"] {
    min-height: calc(100dvh - 280px) !important;
  }
  [class*="xterm-rows"] {
    font-size: 12px !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * File editor route — unblock tap-to-open.
 *
 * Ensure nothing we added upstream (e.g. overflow:hidden on the file row,
 * overly-aggressive pointer-events:none on the safety-net CSS) blocks the
 * click handler wired to the file row.
 */
@media (max-width: 767px) {
  [class*="file-row"],
  [class*="FileRow"] {
    pointer-events: auto !important;
  }
  [class*="file-row"] * {
    pointer-events: auto !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * v5.0.64 — real classNames stamped in source. These override the inline
 * `display: grid; gridTemplateColumns: …` styles that desktop-default
 * layouts bake in.
 */
@media (max-width: 767px) {

  /* ── FILE ROW ── names were invisible because a 9-col grid with 508px
   * of fixed-width columns left the `1fr` name column at zero width on
   * a 375px viewport. Collapse to a flex row: name takes all remaining
   * space, metadata columns hide, actions wrap into a compact trailing
   * group. */
  .loaf-file-row {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    gap: 10px !important;
    padding: 12px 14px !important;
  }
  .loaf-file-row-name {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    font-size: 13px !important;
    order: 2;
  }
  .loaf-file-row-size,
  .loaf-file-row-modified {
    display: none !important;
  }

  /* ── Mass-actions bar ── fit within the viewport + wrap if needed. */
  .loaf-filemanager-mass-bar {
    flex-wrap: wrap !important;
    gap: 6px 10px !important;
    padding: 10px 12px !important;
    left: 12px !important;
    right: 12px !important;
    transform: none !important;
    max-width: none !important;
  }
  .loaf-filemanager-mass-bar > span {
    flex-basis: 100%;
    font-size: 11px !important;
    margin-bottom: 2px;
  }
  .loaf-filemanager-mass-bar > button {
    font-size: 11px !important;
    padding: 6px 10px !important;
    flex: 1 1 auto;
    min-height: 36px;
  }

  /* ── Server header ── players label is noisy on narrow screens.
   * Replace "Players have joined" with just "Players". */
  .loaf-stat-players-label {
    font-size: 0 !important;      /* hide the long label */
  }
  .loaf-stat-players-label::after {
    content: 'Players';
    font-size: 11px;               /* restore size for our shorter copy */
    color: var(--color-text-tertiary);
  }

  /* ── Startup page ── single column on mobile. */
  .loaf-startup-vars-grid {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }
  .loaf-startup-cmd-card {
    padding: 16px !important;
  }

  /* ── Server Settings ── SFTP Details + Debug Information grids go
   * single column so values don't clip. */
  .loaf-server-settings-grid {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }

  /* ── Schedules ── Current schedules + Preset column split stacks
   * vertically. Per-row grid collapses so preset/schedule titles don't
   * bleed into each other. */
  .loaf-schedules-main-grid {
    grid-template-columns: 1fr !important;
    gap: 14px !important;
  }
  .loaf-schedules-row {
    grid-template-columns: 36px 1fr !important;
    grid-auto-flow: row;
    gap: 8px 12px !important;
    padding: 12px !important;
  }
  .loaf-schedules-row > *:nth-child(n+3) {
    grid-column: 2 !important;
  }

  /* ── Network & Ports ── allocation row collapses so IP, port, and
   * note fields stack vertically. */
  .loaf-network-alloc-row {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
  }

  /* ── Server Activity ── filter bar + row grid. */
  .loaf-activity-filter-bar {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
    padding: 12px !important;
  }
  .loaf-activity-row-grid {
    grid-template-columns: 36px 1fr !important;
    grid-auto-flow: row;
    gap: 4px 10px !important;
  }
  .loaf-activity-row-grid > *:nth-child(n+3) {
    grid-column: 2 !important;
    font-size: 11px !important;
    color: var(--color-text-tertiary) !important;
  }

  /* ── Console power button row ── Start / Restart / Stop / Kill fit a
   * 2×2 grid so nothing overflows. */
  .loaf-console-power-row {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 6px !important;
    width: 100%;
  }
  .loaf-console-power-row > button {
    min-width: 0;
  }

  /* ── File Editor ── full-width, trimmer padding. Breadcrumb truncates
   * from the left so the filename stays visible. Toolbar sticky + save
   * stays reachable. */
  .loaf-file-editor-root {
    padding: 12px !important;
  }
  .loaf-file-editor-header {
    padding-bottom: 10px !important;
    gap: 8px !important;
  }
  .loaf-file-editor-header h1 {
    font-size: 16px !important;
  }
  .loaf-file-editor-header p {
    direction: rtl;     /* truncate from the left so filename stays visible */
    text-align: left;
    font-size: 11px !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * v5.0.66 — subusers + permissions + file manager refinements.
 *
 * Permission picker (PermissionTree) defaults its two-pane layout to
 * mobile = tabs, desktop = left category list + right permissions. The
 * tab bar is always present in markup; on desktop we HIDE it so the
 * left category list drives navigation, and on mobile we hide the left
 * list so the tab bar drives navigation.
 */
.loaf-permission-picker-tabs {
  display: none;   /* hidden on desktop */
  gap: 6px;
  overflow-x: auto;
  padding: 4px 2px;
  scrollbar-width: thin;
}
@media (max-width: 767px) {
  .loaf-permission-picker-tabs { display: flex; }
  .loaf-permission-picker-body {
    grid-template-columns: 1fr !important;
  }
  .loaf-permission-picker-catlist {
    display: none !important;
  }
  .loaf-permission-picker-header {
    flex-wrap: wrap !important;
  }
}

/* Subusers: List of Sub Users action row — 2-col grid on mobile so the
 * four buttons don't crush the heading. */
@media (max-width: 767px) {
  .loaf-subusers-list-header {
    flex-direction: column !important;
    align-items: stretch !important;
  }
  .loaf-subusers-list-actions {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 8px !important;
  }
  .loaf-subusers-list-actions > * {
    min-width: 0 !important;
    width: 100% !important;
  }
  .loaf-subusers-list-actions > button,
  .loaf-subusers-list-actions > a {
    font-size: 12px !important;
    height: 40px !important;
    padding: 6px 10px !important;
  }
}

/* New subuser email form — stack label/description above input, submit
 * full-width below. */
@media (max-width: 767px) {
  .loaf-new-subuser-email-card {
    padding: 18px !important;
  }
  .loaf-new-subuser-email-header {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 10px !important;
  }
  .loaf-new-subuser-submit {
    width: 100% !important;
    min-width: 0 !important;
  }
  .loaf-new-subuser-email-card input[type="email"] {
    margin-top: 10px !important;
  }
}

/* Role preview cards (Owner/Operator/Admin/Member/Custom) — flex layout
 * on mobile, badge aligned with title, description flows naturally. */
.loaf-role-card-body-wrap { display: flex; gap: 14px; }
@media (max-width: 767px) {
  .loaf-role-card-body-wrap {
    flex-direction: row !important;
    gap: 10px !important;
  }
}

/* File Manager header grid — stack breadcrumb + toolbar on mobile so
 * the action buttons don't overlap the folder path. */
@media (max-width: 767px) {
  .loaf-filemanager-header-grid {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
    padding: 14px !important;
  }
  .loaf-filemanager-header-grid > div:first-child {
    min-width: 0;
    overflow-x: auto;
    padding-bottom: 2px;
  }
}

/* File row — single row on mobile: checkbox + icon + name + overflow.
 * (Refines the v5.0.64 layout.) */
@media (max-width: 767px) {
  .loaf-file-row {
    flex-wrap: nowrap !important;
    gap: 8px !important;
    padding: 10px 12px !important;
  }
  .loaf-file-row-name {
    order: 0 !important;
    flex: 1 1 auto !important;
  }
  /* Hide star icon when not starred (filled). The star button itself
   * stays in the DOM but becomes visually none when its SVG has
   * fill:none. Keep starred stars visible via fill-amber detection. */
  .loaf-file-row svg.lucide-star:not([fill]),
  .loaf-file-row svg.lucide-star[fill="none"] {
    display: none;
  }
  /* Also hide lock / folder-open / menu-grip icons — move them into
   * overflow via the existing three-dot button. We keep checkbox + icon
   * + name + overflow button visible. */
  .loaf-file-row [data-loaf-fileicon="secondary"] {
    display: none !important;
  }
}

/* Network Test — summary row stacks vertically on mobile, test list
 * collapses to single column. */
@media (max-width: 767px) {
  .loaf-nettest-summary {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }
  .loaf-nettest-summary > div:last-child {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 10px !important;
  }
  .loaf-nettest-body {
    grid-template-columns: 1fr !important;
  }
  .loaf-nettest-card {
    grid-template-columns: 36px 1fr auto !important;
    gap: 8px !important;
  }
  .loaf-nettest-card > *:nth-child(n+5) {
    grid-column: 1 / -1 !important;
    padding-left: 44px;
  }
}

/* Activity Log expanded detail — stack label above value on mobile so
 * long paths and JSON payloads get full width. */
@media (max-width: 767px) {
  .loaf-activity-row-detail {
    padding-left: 14px !important;
    padding-right: 14px !important;
  }
  .loaf-activity-row-detail-grid {
    grid-template-columns: 1fr !important;
    gap: 2px 0 !important;
  }
  .loaf-activity-row-detail-grid > span:nth-child(odd) {
    font-size: 10px !important;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-top: 8px;
  }
  .loaf-activity-row-detail pre {
    overflow-x: auto;
  }
}
