:root{
  --bg: #F3F2F2;
  --ground: #EAE9E9;
  --surface: #ffffff;
  --ink: #201E1D;
  --ink-soft: #6B6864;
  --ink-faint: #9C9994;
  --line: #E3E1E0;
  --brand: #0088B0;
  --brand-dark: #006D8D;
  --brand-tint: rgba(0,136,176,0.10);
  --sidebar-bg: #212F4A;
  --sidebar-ink: #EAF3F5;
  --sidebar-ink-soft: #8FB6C2;
  --amber: #b06a1f;
  --amber-bg: #fbeee0;
  --brick: #a13c2e;
  --brick-bg: #f8e6e2;
  --leaf: #4f7a56;
  --leaf-bg: #e7f0e6;
  --control-h: 40px;
}
*{box-sizing:border-box;}
body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:'Urbanist', sans-serif;
  font-size:15px;
  line-height:1.5;
}
h1,h2,h3{
  font-family:'Urbanist', sans-serif;
  font-weight:800;
  margin:0 0 4px 0;
  letter-spacing:0.1px;
  overflow-wrap:break-word;
}
h3{font-weight:700;}
code, .mono{
  font-family:'Urbanist', sans-serif;
  font-weight:600;
  letter-spacing:0.2px;
}
#boot-loading{
  display:flex;
  align-items:center;
  justify-content:center;
  min-height:100vh;
  color:var(--ink-soft);
  font-size:14px;
  font-family:'Urbanist', sans-serif;
}
body.auth-ready #boot-loading{display:none;}
body:not(.auth-ready) .app{display:none;}

/* Shown instead of the app shell once a trial/subscription has lapsed --
   see auth-gate.js. Reuses .panel for the card so it stays visually part
   of the same design system rather than a bolted-on screen. */
#paywall{
  display:none;
  min-height:100vh;
  align-items:center;
  justify-content:center;
  padding:24px;
  background:var(--bg);
}
body.paywall-active #paywall{display:flex;}
body.paywall-active .app, body.paywall-active #boot-loading{display:none;}
.paywall-card{
  max-width:440px;
  width:100%;
  text-align:center;
  padding:40px 36px;
}
/* A text wordmark here rather than logo-full.png -- that asset is
   white-on-transparent (built for the navy sidebar/auth panels), so it's
   invisible on this card's white background. */
.paywall-wordmark{
  font-family:'Urbanist', sans-serif;
  font-weight:800;
  font-size:20px;
  color:var(--ink);
  margin-bottom:20px;
}
.paywall-wordmark span{font-weight:500; color:var(--ink-soft); font-size:15px;}
.paywall-card h1{font-size:21px; margin-bottom:10px;}
.paywall-card .hint{font-size:13.5px; margin-bottom:20px;}

.app{
  display:grid;
  grid-template-columns:216px 1fr;
  min-height:100vh;
}
.sidebar{
  background:var(--sidebar-bg);
  color:var(--sidebar-ink);
  padding:24px 18px;
  display:flex;
  flex-direction:column;
  gap:28px;
  position:sticky;
  top:0;
  height:100vh;
  overflow-y:auto;
}
.brand{
  padding:4px;
}
.brand-logo-full{
  display:block;
  height:52px;
  width:auto;
  max-width:100%;
}
nav{display:flex; flex-direction:column; gap:2px;}
.nav-btn{
  all:unset;
  cursor:pointer;
  padding:10px 12px;
  border-radius:6px;
  color:#AEB8C9;
  font-size:14px;
  font-weight:500;
  display:flex;
  align-items:center;
  gap:10px;
}
/* .nav-btn sets display:flex at the same specificity as the browser's own
   [hidden]{display:none} rule, and author styles win that tie -- so the
   Team button's `hidden` attribute (set in app.js for non-admins) was
   being silently overridden and the button stayed visible. This rule has
   higher specificity than plain .nav-btn, so [hidden] wins again. */
.nav-btn[hidden]{display:none;}
.nav-btn:hover{background:rgba(255,255,255,0.07); color:#fff;}
.nav-btn.active{background:var(--brand); color:#fff; font-weight:700;}
.nav-icon{width:16px; text-align:center; font-size:14px; opacity:0.9;}
main{
  padding:32px 40px 60px;
  max-width:1320px;
  margin:0 auto;
  width:100%;
  min-width:0;
}
.page-head{
  display:flex;
  justify-content:space-between;
  align-items:flex-end;
  margin-bottom:24px;
  gap:20px;
  flex-wrap:wrap;
}
.page-head > *{min-width:0;}
.page-head p{margin:4px 0 0; color:var(--ink-soft); font-size:13.5px;}

.btn{
  all:unset;
  box-sizing:border-box;
  cursor:pointer;
  background:var(--brand);
  color:#fff;
  height:var(--control-h);
  padding:0 16px;
  border-radius:6px;
  font-size:13.5px;
  font-weight:600;
  white-space:nowrap;
  display:inline-flex;
  align-items:center;
  justify-content:center;
}
.btn:hover{background:var(--brand-dark);}
.btn.ghost{
  background:transparent;
  color:var(--ink-soft);
  border:1px solid var(--line);
  font-weight:500;
}
.btn.ghost:hover{background:var(--ground); color:var(--ink);}
.btn.small{padding:0 10px; font-size:12.5px;}
.btn:disabled{opacity:0.6; cursor:default;}

.grid-cards{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap:14px;
  margin-bottom:28px;
}
.stat-card{
  background:var(--surface);
  border-radius:8px;
  padding:16px 18px;
  box-shadow:0 1px 3px rgba(32,30,29,0.06);
}
.stat-card .num{
  font-family:'Urbanist', sans-serif;
  font-size:28px;
  font-weight:800;
  line-height:1;
  color:var(--ink);
}
.stat-card .label{
  font-size:12px;
  color:var(--ink-soft);
  margin-top:6px;
}
.stat-card.warn .num{color:var(--amber);}
.stat-card.danger .num{color:var(--brick);}

.panel{
  background:var(--surface);
  border-radius:10px;
  padding:20px 22px;
  margin-bottom:22px;
  box-shadow:0 1px 3px rgba(32,30,29,0.06);
}
.panel-title{
  display:flex;
  justify-content:space-between;
  align-items:center;
  margin-bottom:14px;
  flex-wrap:wrap;
  row-gap:10px;
}
.panel-title h3{font-size:16px;}
.table-tools{
  display:flex;
  gap:8px;
  align-items:center;
  margin-left:auto;
  flex-wrap:wrap;
  max-width:100%;
}
.table-search{
  width:190px;
  max-width:100%;
  height:var(--control-h);
  box-sizing:border-box;
  padding:0 10px;
  border:1px solid var(--line);
  border-radius:6px;
  font-size:13px;
  font-family:inherit;
  background:#fff;
}
.table-search:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-tint);}
.row-count{
  font-size:12px;
  color:var(--ink-soft);
  margin-bottom:10px;
  margin-top:-6px;
}

.table-scroll{overflow-x:auto;}
table{width:100%; border-collapse:collapse; font-size:13.5px;}
.table-scroll table{min-width:640px;}
th{
  text-align:left;
  font-size:11px;
  letter-spacing:0.3px;
  color:var(--ink-soft);
  font-weight:700;
  padding:6px 10px;
  border-bottom:1px solid var(--ground);
}
td{
  padding:10px 10px;
  vertical-align:middle;
}
tbody tr:nth-child(even) td{background:var(--ground);}
/* Brief flash on a row jumped to via a "Use existing" link, so it's
   obvious which one matched -- fades back to the normal row color. */
tr.row-highlight td{background:var(--brand-tint) !important; transition:background 1.2s ease;}
/* A voided batch/shipment stays visible (for traceability) but reads as
   inactive history, not something currently in effect. */
tr.voided-row td{color:var(--ink-faint);}
tr.voided-row .tag, tr.voided-row .pill:not(.danger){opacity:0.6;}

.tag{
  display:inline-block;
  font-family:'Urbanist', sans-serif;
  font-weight:600;
  font-size:12px;
  letter-spacing:0.2px;
  padding:3px 8px;
  border-radius:4px;
  background:var(--ground);
  color:var(--brand-dark);
}
tbody tr:nth-child(even) .tag{background:var(--surface);}
.pill{
  display:inline-block;
  font-size:11.5px;
  padding:3px 9px;
  border-radius:20px;
  font-weight:600;
}
.pill.ok{background:var(--leaf-bg); color:var(--leaf);}
.pill.warn{background:var(--amber-bg); color:var(--amber);}
.pill.danger{background:var(--brick-bg); color:var(--brick);}

.alert-row{
  display:flex;
  align-items:center;
  gap:12px;
  padding:11px 14px;
  border-radius:7px;
  margin-bottom:8px;
  font-size:13.5px;
  flex-wrap:wrap;
}
.alert-row > span:not(.dot):not(.go){
  flex:1 1 auto;
  min-width:0;
}
.alert-row.warn{background:var(--amber-bg); color:#7a4a13;}
.alert-row.danger{background:var(--brick-bg); color:#7a291c;}
.alert-row .dot{width:7px; height:7px; border-radius:50%; flex-shrink:0;}
.alert-row.warn .dot{background:var(--amber);}
.alert-row.danger .dot{background:var(--brick);}
.alert-row .go{margin-left:auto;}
.alert-row .go a{color:inherit; font-weight:700; text-decoration:underline; cursor:pointer;}

form.inline-form{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(130px, 100%),1fr));
  gap:12px;
  align-items:end;
  margin-top:4px;
}
form.inline-form label{
  display:block;
  font-size:11.5px;
  color:var(--ink-soft);
  margin-bottom:5px;
}
form.inline-form > div{min-width:0;}
form.inline-form input, form.inline-form select{
  width:100%;
  min-width:0;
  height:var(--control-h);
  box-sizing:border-box;
  padding:0 10px;
  border:1px solid var(--line);
  border-radius:6px;
  font-size:13.5px;
  font-family:inherit;
  background:#fff;
}
form.inline-form input:focus, form.inline-form select:focus{
  outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-tint);
}
/* Generic small quantity input, reused wherever a single number needs the
   same sizing as the rest of the app's controls but isn't inside a
   form.inline-form (e.g. the "record actual yield" inline editor). */
.qty-input{
  width:96px;
  height:var(--control-h);
  box-sizing:border-box;
  padding:0 8px;
  border:1px solid var(--line);
  border-radius:5px;
  font-size:13px;
  font-family:inherit;
}
.qty-input:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-tint);}

/* ---------- production: FEFO ingredient-row picker ---------- */
#ingredient-rows{display:flex; flex-direction:column; gap:10px;}
.ingredient-row{
  background:var(--ground);
  border-radius:8px;
  padding:12px 14px;
}
.ingredient-row-main{
  display:flex;
  gap:12px;
  align-items:flex-end;
  flex-wrap:wrap;
}
.ingredient-row-main > div{min-width:0;}
.ing-search-field{flex:2 1 220px;}
.ing-qty-field{flex:1 1 140px;}
.ingredient-row label{display:block; font-size:11.5px; color:var(--ink-soft); margin-bottom:5px;}
.ing-search, .ing-qty{
  width:100%;
  height:var(--control-h);
  box-sizing:border-box;
  padding:0 10px;
  border:1px solid var(--line);
  border-radius:6px;
  font-size:13.5px;
  font-family:inherit;
  background:#fff;
}
.ing-search:focus, .ing-qty:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-tint);}
.row-assignment{margin-top:10px; font-size:12.5px;}
.row-assignment:empty{margin-top:0;}
.row-assignment .assign-line{padding:3px 0;}
.row-assignment .assign-error{color:var(--brick); font-weight:600;}
.row-assignment .assign-hint{color:var(--ink-soft);}
.manual-override-box{
  margin-top:10px;
  padding-top:10px;
  border-top:1px dashed var(--line);
  max-width:420px;
}
.manual-override-box select{
  width:100%;
  height:var(--control-h);
  box-sizing:border-box;
  padding:0 10px;
  border:1px solid var(--line);
  border-radius:6px;
  font-size:13px;
  font-family:inherit;
  background:#fff;
  margin-top:2px;
}
.search-box{
  display:flex;
  gap:10px;
  margin-bottom:18px;
}
.search-box input{
  flex:1;
  min-width:0;
  height:var(--control-h);
  box-sizing:border-box;
  padding:0 14px;
  border:1px solid var(--line);
  border-radius:7px;
  font-size:14px;
  font-family:'Urbanist', sans-serif;
  font-weight:600;
  letter-spacing:0.2px;
}
.search-box input:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-tint);}
.trace-result{
  margin-top:18px;
}
.trace-col{
  display:grid;
  grid-template-columns:1fr auto 1fr;
  gap:18px;
  align-items:start;
}
.trace-block{
  background:var(--ground);
  border-radius:8px;
  padding:14px 16px;
  min-width:0;
}
.trace-block h4{
  font-size:12px;
  text-transform:uppercase;
  letter-spacing:0.4px;
  color:var(--ink-soft);
  margin:0 0 10px;
  font-weight:700;
}
.trace-item{
  background:var(--surface);
  border-radius:6px;
  padding:9px 11px;
  margin-bottom:8px;
  font-size:13px;
  box-shadow:0 1px 2px rgba(32,30,29,0.05);
}
.trace-item .l1{font-weight:700;}
.trace-item .l2{color:var(--ink-soft); font-size:12px; margin-top:2px;}
.trace-arrow{
  align-self:center;
  font-size:20px;
  color:var(--ink-faint);
  padding-top:40px;
}
.empty-note{
  color:var(--ink-soft);
  font-size:13px;
  padding:30px 10px;
  text-align:center;
}
.center-batch{
  background:var(--sidebar-bg);
  color:#fff;
}
.center-batch h4{color:var(--sidebar-ink-soft);}
.center-batch .trace-item{
  background:rgba(255,255,255,0.08);
  box-shadow:none;
  color:#fff;
}
.center-batch .trace-item .l2{color:var(--sidebar-ink-soft);}
.hint{
  font-size:12.5px;
  color:var(--ink-soft);
  margin-top:10px;
}
.page{display:none;}
.page.active{display:block;}
::placeholder{color:var(--ink-faint); font-size:12.5px;}

/* ---------- mobile nav: hamburger + slide-out drawer ---------- */
/* Hidden on desktop; everything below only takes effect at/under 900px. */
.mobile-topbar{display:none;}
.sidebar-overlay{display:none;}

@media (max-width:900px){
  .app{
    display:block;
  }

  /* Input/select height is unified globally (see --control-h above). This
     block only normalizes native select/date chrome, which otherwise renders
     inconsistently on mobile browsers even at a matching height.
     Deliberately NOT applying -webkit-appearance:none to date inputs: on
     iOS Safari that can suppress the native calendar icon/placeholder
     entirely, leaving a blank box. Selects need it for the custom arrow. */
  form.inline-form select, .manual-override-box select{
    -webkit-appearance:none;
    appearance:none;
    padding-right:30px;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236B6864'%3E%3Cpath fill-rule='evenodd' d='M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z' clip-rule='evenodd'/%3E%3C/svg%3E");
    background-repeat:no-repeat;
    background-position:right 8px center;
    background-size:16px;
  }
  form.inline-form input[type="date"]{
    line-height:normal;
  }

  .mobile-topbar{
    display:flex;
    align-items:center;
    gap:14px;
    padding:12px 16px;
    background:var(--sidebar-bg);
    position:sticky;
    top:0;
    z-index:500;
  }
  .hamburger-btn{
    all:unset;
    cursor:pointer;
    color:#fff;
    font-size:22px;
    line-height:1;
    padding:4px 8px;
    border-radius:6px;
  }
  .hamburger-btn:hover, .hamburger-btn:focus-visible{background:rgba(255,255,255,0.12);}
  .mobile-topbar-logo{height:28px; width:auto; display:block;}

  .sidebar-overlay{
    display:block;
    position:fixed;
    inset:0;
    background:rgba(20,20,20,0.45);
    z-index:900;
    opacity:0;
    pointer-events:none;
    transition:opacity 0.2s ease;
  }
  .sidebar-overlay.open{
    opacity:1;
    pointer-events:auto;
  }

  .sidebar{
    position:fixed;
    top:0;
    left:0;
    bottom:0;
    width:260px;
    max-width:82vw;
    z-index:950;
    transform:translateX(-100%);
    transition:transform 0.22s ease;
    overflow-y:auto;
    box-shadow:2px 0 20px rgba(0,0,0,0.25);
  }
  .sidebar.open{
    transform:translateX(0);
  }

  main{padding:24px 18px 48px;}

  .table-scroll{-webkit-overflow-scrolling:touch;}
  .table-scroll.scrollable{
    box-shadow:inset -14px 0 10px -10px rgba(32,30,29,0.22);
  }
}

body.drawer-open{overflow:hidden;}
