/* ============================================================
   App shell — Operator Console
   Navigation lives in a persistent rail, never inside the status
   bar, so it can never be clipped. Three adaptive states:

     >  1280px  full rail   (icon + label, 236px)
     768-1280   icon rail   (76px, label via tooltip)
     <  768px   bottom bar  (all destinations, equal width)

   768 rather than 900 is where the bottom bar starts, because a
   tablet held upright is ~800px wide: at 900 it was handed the
   phone layout and lost the side-by-side till for no reason.

   The status bar carries state only (shift, scanner, clock,
   language, theme, store) and never competes for nav space.
   ============================================================ */

.app { display: flex; min-height: 100dvh; }

/* ---------- navigation rail ---------- */
.rail {
  flex: none;
  width: var(--rail-w);
  height: 100dvh;
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  padding: var(--s4) var(--s3);
  background: var(--surface);
  border-right: 1px solid var(--border);
}

/* brand */
.rail-brand {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s1) var(--s2) var(--s5);
  color: var(--text); min-width: 0;
}
.brand-logo { width: 34px; height: 34px; flex: none; display: block; }
.brand-name {
  font-size: var(--fs-lg); font-weight: 800; letter-spacing: -.02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}

/* destinations */
.rail-nav { display: flex; flex-direction: column; gap: 2px; }
.nav-btn {
  display: flex; align-items: center; gap: var(--s3);
  min-height: var(--tap); padding: 0 var(--s3);
  border: none; background: transparent;
  color: var(--text-2); font-weight: 600; font-size: var(--fs-base);
  border-radius: var(--r); white-space: nowrap; text-align: start;
  position: relative;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.nav-btn .ic { width: 22px; height: 22px; flex: none; }
.nav-btn:hover { background: var(--surface-2); color: var(--text); }
.nav-btn.active { background: var(--accent-weak); color: var(--accent); }
/* "You are here" marker — reads without relying on color alone */
.nav-btn.active::before {
  content: ""; position: absolute; inset-inline-start: 0; top: 50%;
  translate: 0 -50%; width: 3px; height: 22px;
  border-radius: 0 3px 3px 0; background: var(--accent);
}

/* account block pinned to the bottom of the rail */
.rail-foot { margin-top: auto; padding-top: var(--s3); border-top: 1px solid var(--border); }
.user-chip {
  display: flex; align-items: center; gap: var(--s2);
  min-height: var(--tap); padding: 0 var(--s2);
  font-weight: 600; font-size: var(--fs-sm); color: var(--text-2); min-width: 0;
}
.user-chip #userName {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.user-avatar {
  width: 30px; height: 30px; flex: none; border-radius: var(--r-full);
  display: grid; place-items: center;
  background: var(--accent-weak); color: var(--accent);
  font-weight: 800; font-size: var(--fs-sm); text-transform: uppercase;
}

/* ---------- main column ---------- */
.app-main {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  height: 100dvh;
}

/* status bar — state only, no navigation */
.topbar {
  flex: none; height: var(--topbar-h);
  display: flex; align-items: center; gap: var(--s3);
  padding: 0 var(--s4);
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.topbar .spacer { flex: 1 1 auto; }

/* scrolling content region */
.app-body { flex: 1; min-height: 0; overflow-y: auto; }

/* ---------- adaptive: icon-only rail ----------
   1280 rather than 1199, so a tablet on its side (1280x800) hands its 160px of
   navigation labels back to the till, where they buy a column of products. */
@media (max-width: 1280px) {
  .rail { width: var(--rail-w-collapsed); padding-inline: var(--s2); align-items: stretch; }
  .rail-brand { justify-content: center; padding-inline: 0; }
  .brand-name { display: none; }
  .nav-btn { justify-content: center; padding-inline: 0; gap: 0; }
  .nav-btn span { display: none; }
  .user-chip { justify-content: center; padding-inline: 0; }
  .user-chip #userName { display: none; }
}

/* ---------- adaptive: bottom bar ---------- */
@media (max-width: 767px) {
  .app { flex-direction: column; }

  .rail {
    order: 2;
    position: fixed; inset: auto 0 0 0;
    width: auto; height: auto;
    flex-direction: row; gap: 0;
    padding: 0 var(--s1);
    padding-bottom: env(safe-area-inset-bottom, 0);
    border-right: none; border-top: 1px solid var(--border);
    box-shadow: var(--shadow-2);
  }
  /* brand and account move into the top bar's territory on small screens */
  .rail-brand, .rail-foot { display: none; }

  .rail-nav {
    flex: 1; flex-direction: row; gap: 0;
    justify-content: space-around;
  }
  .nav-btn {
    flex: 1 1 0; min-width: 0;
    flex-direction: column; gap: 2px;
    min-height: var(--bottombar-h); padding: var(--s1) 2px;
    font-size: 10px; font-weight: 700; letter-spacing: -.01em;
    border-radius: var(--r-sm);
  }
  /* labels return at the smallest size — they are the only affordance left */
  .nav-btn span {
    display: block; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .nav-btn.active { background: transparent; }
  .nav-btn.active::before {
    inset-inline-start: 50%; top: 4px; translate: -50% 0;
    width: 22px; height: 3px; border-radius: 0 0 3px 3px;
  }

  .app-main { height: auto; min-height: 100dvh; padding-bottom: var(--bottombar-h); }
  .topbar { position: sticky; top: 0; z-index: var(--z-sticky); }
  .app-body { overflow: visible; }

  /* compact status bar: keep only the load-bearing indicators */
  #clock, .scan-status .scan-label { display: none; }
  .topbar { gap: var(--s2); padding: 0 var(--s3); }
}

/* A tablet keeps the rail, but the clock is the first thing worth dropping when
   the status bar starts to crowd. */
@media (max-width: 1023px) {
  #clock { display: none; }
}

/* Narrow phones: keep every status-bar control reachable instead of letting the
   row overflow its own width.

   These selectors are qualified with .topbar on purpose. components.css loads
   after this file and sets max-width on the same two classes, so an unqualified
   rule here loses the cascade at equal specificity and the caps never applied —
   the language select stayed at its full 166px and pushed the row 149px wide at
   320px. */
@media (max-width: 480px) {
  .topbar { gap: var(--s1); }
  .topbar .store-switch { max-width: 104px; }
  .topbar .lang-switch { max-width: 104px; }
  #shiftPill { padding-inline: var(--s2); font-size: var(--fs-xs); }
}

/* Below this even the trimmed controls do not fit together. The language switch
   is the one that is duplicated elsewhere — Pengaturan has the same setting — so
   it is the one that goes. */
@media (max-width: 400px) {
  .topbar .lang-switch { display: none; }
}

/* The mark also fronts the login card, a little larger there. */
.login-brand .brand-logo { width: 40px; height: 40px; }

