:root{
  --ink:#101823;
  --steel:#1E2C3A;
  --slate:#3B4C5F;
  --paper:#E6E9ED;
  --card:#FFFFFF;
  --manila:#C08423;
  --manila-soft:#F5E7CC;
  --signal:#0E7C66;
  --signal-soft:#D8EDE7;
  --rule:#C4CCD4;
  --muted:#5C6B7A;
  --danger:#A63B2A;
  --shadow:0 1px 0 rgba(16,24,35,.06), 0 6px 20px -12px rgba(16,24,35,.5);
  /* No web fonts: nothing is fetched from a CDN, so the app renders the same
     on the plant LAN, on mobile data, and offline. Condensed faces are tried
     first for the display type, falling back through the system stack. */
  --disp:"Roboto Condensed","Arial Narrow","Helvetica Neue Condensed",
         "Liberation Sans Narrow",system-ui,-apple-system,"Segoe UI",sans-serif;
  --body:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
  /* Height of the phone tab bar, including the gesture area. */
  --tabbar:calc(56px + env(safe-area-inset-bottom, 0px));
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--body);
  background:var(--paper);
  color:var(--ink);
  -webkit-font-smoothing:antialiased;
  line-height:1.45;
}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer}
:focus-visible{outline:2.5px solid var(--signal);outline-offset:2px}
.hidden{display:none !important}

/* ---------- shared bits ---------- */
.eyebrow{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);
}
.btn{
  border:1px solid var(--slate);background:var(--slate);color:#fff;
  padding:9px 16px;border-radius:2px;font-weight:500;font-size:14px;
  transition:background .15s,border-color .15s,transform .05s;
}
.btn:hover{background:var(--ink);border-color:var(--ink)}
.btn:active{transform:translateY(1px)}
.btn.primary{background:var(--signal);border-color:var(--signal)}
.btn.primary:hover{background:#0a6553;border-color:#0a6553}
.btn.ghost{background:transparent;color:var(--slate);border-color:var(--rule)}
.btn.ghost:hover{background:#fff;color:var(--ink);border-color:var(--slate)}
.btn.tiny{padding:5px 10px;font-size:12.5px}
.btn.danger{background:transparent;color:var(--danger);border-color:#E0C2BB}
.btn.danger:hover{background:var(--danger);color:#fff;border-color:var(--danger)}
.field{display:block;margin-bottom:14px}
.field > span{
  display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);margin-bottom:5px;
}
.field input,.field select,.field textarea{
  width:100%;padding:10px 12px;border:1px solid var(--rule);border-radius:2px;
  background:#fff;font-size:15px;
}
.field input:focus,.field select:focus{border-color:var(--slate)}
mark{background:var(--manila-soft);color:inherit;padding:0 1px;border-radius:1px}

/* ---------- login ---------- */
#login{
  min-height:100dvh;display:grid;place-items:center;padding:24px;
  background:
    linear-gradient(180deg, #16222E 0%, #0D141C 100%);
}
.drawer{
  width:100%;max-width:430px;background:var(--card);border-radius:3px;
  box-shadow:0 24px 60px -20px rgba(0,0,0,.7);overflow:hidden;
}
.drawer-front{
  background:var(--steel);padding:26px 28px 22px;position:relative;
  border-bottom:3px solid var(--manila);
}
.plate{
  display:inline-block;background:#0C131A;border:1px solid #35485A;
  padding:4px 10px;border-radius:1px;
}
.plate span{font-family:var(--mono);font-size:10px;letter-spacing:.18em;color:#8FA3B5;text-transform:uppercase}
.drawer-front h1{
  font-family:var(--disp);font-weight:600;font-size:38px;line-height:1;
  letter-spacing:.01em;color:#fff;margin:14px 0 6px;text-transform:uppercase;
}
.drawer-front p{margin:0;color:#9BADBD;font-size:13.5px}
.pull{
  position:absolute;right:28px;top:50%;width:54px;height:9px;border-radius:5px;
  background:linear-gradient(180deg,#4A5F73,#2A3947);box-shadow:inset 0 1px 0 #6C8298;
}
.drawer-body{padding:26px 28px 24px}
.note{
  margin-top:16px;padding:11px 13px;background:#F4F6F8;border-left:3px solid var(--manila);
  font-size:12.5px;color:var(--muted);
}
.err{
  margin-bottom:14px;padding:10px 13px;background:#FBEDEA;border-left:3px solid var(--danger);
  font-size:13.5px;color:#7E2C1E;
}

/* ---------- app shell ---------- */
#app{min-height:100dvh;display:flex;flex-direction:column}
header.top{
  background:var(--steel);color:#fff;padding:12px 22px;
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  border-bottom:3px solid var(--manila);position:sticky;top:0;z-index:20;
}
.brand{font-family:var(--disp);font-weight:600;font-size:21px;letter-spacing:.02em;text-transform:uppercase;white-space:nowrap}
.brand small{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;color:#8FA3B5;font-weight:400;text-transform:uppercase}
.top .spacer{flex:1}
.who{font-family:var(--mono);font-size:11.5px;color:#9BADBD;text-align:right;line-height:1.3}
.who b{color:#fff;font-weight:500;display:block;font-size:12.5px}
.top .btn.ghost{color:#CBD6E0;border-color:#3E5265}
.top .btn.ghost:hover{background:#0D141C;color:#fff;border-color:#5A7086}

/* search band */
.band{background:var(--ink);padding:22px 22px 26px}
.band-inner{max-width:1180px;margin:0 auto}
.searchwrap{position:relative;display:flex;align-items:center;gap:0}
.searchwrap svg{position:absolute;left:16px;width:19px;height:19px;stroke:#7E93A6;fill:none;stroke-width:2}
#q{
  width:100%;padding:16px 120px 16px 46px;border:1px solid #35485A;border-radius:2px;
  background:#0A1017;color:#fff;font-size:17px;font-family:var(--body);
}
#q::placeholder{color:#5E7285}
#q:focus{border-color:var(--signal);background:#0C141C}
#clearq{
  position:absolute;right:10px;background:transparent;border:1px solid #35485A;
  color:#8FA3B5;padding:6px 12px;border-radius:2px;font-size:12.5px;
}
#clearq:hover{color:#fff;border-color:#5A7086}
.hintrow{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px;align-items:center}
.hintrow .eyebrow{color:#6F8296;margin-right:2px}
.chip{
  background:transparent;border:1px solid #35485A;color:#B9C7D3;
  padding:4px 11px;border-radius:99px;font-size:12.5px;font-family:var(--mono);
}
.chip:hover{border-color:var(--manila);color:#F0D6A3}

/* main columns */
main{flex:1;max-width:1180px;width:100%;margin:0 auto;padding:24px 22px 60px;
  display:grid;grid-template-columns:290px 1fr;gap:30px;align-items:start}
@media(max-width:880px){main{grid-template-columns:1fr;gap:22px}}

/* rack map — the signature element */
.rackmap{position:sticky;top:74px}
@media(max-width:880px){.rackmap{position:static}}
.rackmap h2{font-family:var(--disp);text-transform:uppercase;font-size:15px;letter-spacing:.08em;margin:0 0 3px}
.rackmap .sub{font-size:12px;color:var(--muted);margin:0 0 14px}
.cabinet{margin-bottom:14px;background:var(--card);border:1px solid var(--rule);border-radius:2px;box-shadow:var(--shadow);overflow:hidden}
.cabinet-label{
  background:#DDE2E8;padding:6px 11px;font-family:var(--mono);font-size:10.5px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--slate);
  border-bottom:1px solid var(--rule);display:flex;justify-content:space-between;
}
.shelf{
  display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  padding:9px 11px;background:#fff;border:0;border-bottom:1px solid #EDF0F3;
  font-size:13.5px;color:var(--ink);transition:background .12s;
}
.shelf:last-child{border-bottom:0}
.shelf:hover{background:#F4F6F8}
.slat{width:5px;height:22px;border-radius:1px;background:var(--rule);flex:none}
.shelf .nm{flex:1}
.shelf .ct{font-family:var(--mono);font-size:11.5px;color:var(--muted)}
.shelf.hit{background:var(--signal-soft)}
.shelf.hit .slat{background:var(--signal)}
.shelf.hit .ct{color:var(--signal);font-weight:600}
.shelf.hit .nm{font-weight:600}
.shelf.dim{opacity:.42}
.shelf.sel{background:var(--ink);color:#fff}
.shelf.sel .ct{color:#9BADBD}
.shelf.sel .slat{background:var(--manila)}

/* results */
.resulthead{display:flex;align-items:baseline;gap:12px;margin-bottom:14px;flex-wrap:wrap}
.resulthead h2{font-family:var(--disp);text-transform:uppercase;font-size:17px;letter-spacing:.06em;margin:0}
.resulthead .count{font-family:var(--mono);font-size:12px;color:var(--muted)}
.filterpill{
  background:var(--ink);color:#fff;border:0;padding:4px 10px;border-radius:99px;
  font-family:var(--mono);font-size:11.5px;
}
.filterpill:hover{background:var(--danger)}

.rec{
  background:var(--card);border:1px solid var(--rule);border-left:4px solid var(--slate);
  border-radius:2px;padding:13px 15px;margin-bottom:9px;box-shadow:var(--shadow);
  display:grid;grid-template-columns:1fr auto;gap:6px 16px;align-items:start;
}
.rec.weak{border-left-color:var(--manila);background:#FDFCF9}
.rec .sno{font-family:var(--mono);font-size:11px;color:var(--muted);letter-spacing:.06em}
.rec .desc{font-size:15.5px;font-weight:500;line-height:1.35;margin:2px 0 6px}
.rec .meta{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.tag{
  font-family:var(--mono);font-size:11px;background:var(--manila-soft);color:#6B4708;
  padding:2px 8px;border-radius:99px;
}
.loc{
  text-align:right;font-family:var(--disp);text-transform:uppercase;
  font-size:19px;line-height:1.1;letter-spacing:.02em;color:var(--signal);white-space:nowrap;
}
.loc small{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;color:var(--muted);margin-bottom:2px}
.rec .acts{grid-column:1/-1;display:flex;gap:7px;margin-top:4px}
@media(max-width:520px){
  .rec{grid-template-columns:1fr}
  .loc{text-align:left}
}

.empty{
  background:var(--card);border:1px dashed var(--rule);border-radius:2px;
  padding:34px 26px;text-align:center;
}
.empty h3{font-family:var(--disp);text-transform:uppercase;letter-spacing:.06em;margin:0 0 6px;font-size:18px}
.empty p{margin:0 0 16px;color:var(--muted);font-size:14px}
.empty .chips{display:flex;gap:7px;flex-wrap:wrap;justify-content:center}
.empty .chip{border-color:var(--rule);color:var(--slate);background:#fff}
.empty .chip:hover{border-color:var(--slate);color:var(--ink)}

.divider{
  display:flex;align-items:center;gap:11px;margin:22px 0 13px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.divider::after{content:"";flex:1;height:1px;background:var(--rule)}

/* admin */
.panel{background:var(--card);border:1px solid var(--rule);border-radius:2px;box-shadow:var(--shadow);margin-bottom:20px}
.panel > h3{
  font-family:var(--disp);text-transform:uppercase;letter-spacing:.07em;font-size:15px;
  margin:0;padding:12px 18px;border-bottom:1px solid var(--rule);background:#F4F6F8;
}
.panel .body{padding:18px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 16px}
@media(max-width:640px){.grid2{grid-template-columns:1fr}}
table{width:100%;border-collapse:collapse;font-size:14px}
th{
  text-align:left;font-family:var(--mono);font-size:10px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--muted);padding:7px 10px;border-bottom:1px solid var(--rule);
}
td{padding:9px 10px;border-bottom:1px solid #EDF0F3;vertical-align:middle}
tr:last-child td{border-bottom:0}
.rolebadge{font-family:var(--mono);font-size:10.5px;padding:2px 8px;border-radius:99px;background:#E4E8EC;color:var(--slate)}
.rolebadge.admin{background:var(--ink);color:#fff}
.toast{
  position:fixed;left:50%;bottom:26px;transform:translateX(-50%);
  background:var(--ink);color:#fff;padding:11px 20px;border-radius:2px;font-size:14px;
  box-shadow:0 12px 30px -10px rgba(0,0,0,.6);z-index:60;border-left:3px solid var(--signal);
}
.warnbar{background:#FBEDEA;color:#7E2C1E;padding:8px 22px;font-size:13px;border-bottom:1px solid #E0C2BB}
@media (prefers-reduced-motion:reduce){*{transition:none !important;animation:none !important}}

/* ---------- additions for the PHP build ---------- */
a.btn{display:inline-block;text-decoration:none}
.top a.btn.ghost{color:#CBD6E0;border-color:#3E5265}
.top a.btn.ghost:hover{background:#0D141C;color:#fff;border-color:#5A7086}
.flash{
  max-width:1180px;margin:16px auto -4px;padding:11px 16px;border-radius:2px;
  font-size:14px;background:var(--signal-soft);border-left:3px solid var(--signal);color:#0A5342;
}
.flash.bad{background:#FBEDEA;border-left-color:var(--danger);color:#7E2C1E}
main.single{grid-template-columns:1fr;max-width:1000px}
.searchform{display:contents}
.rec form{display:inline}
.count-note{font-family:var(--mono);font-size:11.5px;color:var(--muted)}
.loginwrap{min-height:100dvh}

/* ═══════════════════════════════════════════════════════════════════════
   Installed app + phone layout
   ═══════════════════════════════════════════════════════════════════════ */

/* Standalone windows draw under the status bar, so pad for the notch. */
.top{
  padding-left:max(22px, env(safe-area-inset-left, 0px));
  padding-right:max(22px, env(safe-area-inset-right, 0px));
  padding-top:calc(12px + env(safe-area-inset-top, 0px));
}
.topnav{display:flex;gap:7px;align-items:center}

/* Bottom tab bar — phones only. */
.tabbar{display:none}
.tab svg{width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}

/* Stop iOS zooming the page when a field is focused. */
@media (max-width:880px){
  .field input,.field select,.field textarea{font-size:16px}
}

@media (max-width:880px){

  /* --- header shrinks to a title bar; the tab bar takes over navigation --- */
  header.top{position:static;gap:10px;padding-top:calc(10px + env(safe-area-inset-top,0px));
    padding-bottom:10px}
  .brand{font-size:18px}
  .brand small{font-size:9px;letter-spacing:.12em}
  .who{font-size:10.5px;line-height:1.25}
  .who b{font-size:11.5px}
  .topnav{display:none}

  body{padding-bottom:var(--tabbar)}

  .tabbar{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:40;
    background:var(--steel);border-top:1px solid #35485A;
    padding-bottom:env(safe-area-inset-bottom,0px);
    box-shadow:0 -6px 20px -12px rgba(0,0,0,.8);
  }
  .tab{
    flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:3px;min-height:56px;text-decoration:none;color:#8FA3B5;
    font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
    -webkit-tap-highlight-color:transparent;
  }
  .tab.on{color:#fff;box-shadow:inset 0 -3px 0 var(--manila)}
  .tab:active{background:#0D141C}

  /* --- the search box stays in reach while scrolling results --- */
  .band{
    position:sticky;top:0;z-index:30;padding:14px 16px 16px;
    padding-left:max(16px, env(safe-area-inset-left,0px));
    padding-right:max(16px, env(safe-area-inset-right,0px));
  }
  #q{padding:14px 96px 14px 42px;font-size:16px}
  .searchwrap svg{left:13px;width:17px;height:17px}
  #clearq{padding:7px 11px}
  .hintrow{margin-top:10px;flex-wrap:nowrap;overflow-x:auto;padding-bottom:3px;
    scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .hintrow::-webkit-scrollbar{display:none}
  .hintrow .chip{flex:none;padding:7px 13px}

  /* --- results first; the rack map is for browsing, so it follows --- */
  main{padding:16px 16px 28px;gap:24px;
    padding-left:max(16px, env(safe-area-inset-left,0px));
    padding-right:max(16px, env(safe-area-inset-right,0px))}
  main > section{order:1}
  .rackmap{order:2;border-top:1px solid var(--rule);padding-top:20px}
  #cabinets{display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:start}
  .cabinet{margin-bottom:0}

  /* Bigger touch targets everywhere. */
  .shelf{padding:12px 11px;font-size:14px;min-height:46px}
  .btn{padding:11px 16px}
  .btn.tiny{padding:8px 13px;font-size:13px;min-height:38px}
  .chip{padding:7px 13px}
  .filterpill{padding:7px 13px}

  .resulthead h2{font-size:16px}
  .panel .body{padding:15px}
  .panel > h3{padding:12px 15px;font-size:14px}
  .flash{margin:12px 16px -6px}
}

/* --- one-column result cards on small screens --- */
@media (max-width:560px){
  .rec{
    grid-template-columns:1fr;gap:0;padding:0;overflow:hidden;
    border-left-width:4px;
  }
  .rec > div:first-child{padding:13px 15px 11px}
  .rec .desc{font-size:16px}
  /* The rack name is the answer, so it gets its own band at the foot. */
  .rec .loc{
    grid-row:3;text-align:left;font-size:17px;
    background:var(--signal-soft);color:#0A5342;
    padding:9px 15px;border-top:1px solid #C7E2DA;
  }
  .rec.weak .loc{background:#F6EFE2;color:#6B4708;border-top-color:#E8DCC4}
  .rec .loc small{display:inline;margin:0 6px 0 0;font-size:9.5px;vertical-align:1px}
  .rec .acts{grid-row:2;padding:0 15px 13px;margin:0}
  .empty{padding:26px 18px}
}

/* --- admin tables scroll sideways rather than squashing --- */
@media (max-width:700px){
  .panel table{min-width:520px}
  .panel .body > div[style*="overflow-x"]{-webkit-overflow-scrolling:touch}
  .panel form[style*="inline"]{display:inline-flex;flex-wrap:wrap;gap:6px;align-items:center}
  main.single{padding-bottom:28px}
}

/* --- landscape phones: keep the tab bar off the content --- */
@media (max-height:460px) and (max-width:900px){
  .tab{min-height:46px;font-size:9px}
  .tab svg{width:18px;height:18px}
  .band{position:static}
}

/* --- login screen on a phone --- */
@media (max-width:560px){
  #login{padding:18px;padding-top:max(18px, env(safe-area-inset-top,0px));
    padding-bottom:max(18px, env(safe-area-inset-bottom,0px))}
  .drawer-front{padding:22px 22px 18px}
  .drawer-front h1{font-size:32px}
  .drawer-body{padding:22px}
  .pull{right:22px;width:44px}
}

/* Installed windows have no browser chrome to scroll away, so the app
   should not rubber-band the whole page behind the tab bar. */
@media (display-mode:standalone){
  body{overscroll-behavior-y:none}
  .top{padding-top:calc(14px + env(safe-area-inset-top, 0px))}
}

/* ── Grid children default to min-width:auto, which means a wide table
      refuses to shrink and pushes the whole page sideways. Let the columns
      shrink so the table scrolls inside its own wrapper instead. ── */
main > *,
main > * > *,
.panel,
.panel .body{min-width:0}
.panel .body > div[style*="overflow-x"]{max-width:100%}

@media (max-width:880px){
  /* 34px was under the 36px minimum for a comfortable thumb. */
  .chip{padding:8px 14px}
  .hintrow .chip{padding:8px 14px}
}

/* ── Phone reading order ────────────────────────────────────────────────
   Opening the app with no query is browsing, so the rack map leads — it is
   the compact way in. The moment something is typed, results lead and the
   map drops below, because the answer is what the person came for. With the
   whole register listed the map would otherwise sit thousands of pixels
   down the page, out of reach.  Desktop is unaffected: the map is a column. */
@media (max-width:880px){
  main.browsing  > section{order:2}
  main.browsing  .rackmap{order:1;border-top:0;padding-top:0;
    border-bottom:1px solid var(--rule);padding-bottom:20px}
  main.searching > section{order:1}
  main.searching .rackmap{order:2;border-top:1px solid var(--rule);padding-top:20px;
    border-bottom:0;padding-bottom:0}
}

/* The active tab reads better marked at the top — and the gesture bar at
   the foot of the phone would otherwise sit on top of the indicator. */
.tab.on{box-shadow:inset 0 3px 0 var(--manila)}

/* A datalist is not rendered, but some engines still give it a box. */
datalist{display:none}

/* ── Header must never overflow ──────────────────────────────────────────
   The bar holds a title, the signed-in name, an Install button and the nav.
   On a narrow window those used to push each other out of shape, so the bar
   is allowed to wrap and the subtitle truncates rather than forcing width. */
header.top{flex-wrap:wrap;row-gap:8px}
.top .spacer{flex:1 1 auto;min-width:0}
.brand{min-width:0;max-width:100%}
.brand small{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.who{min-width:0}
.topnav{flex:none}
