/*!
 * inventory-shell.css: the staff application frame (P0-15, ADR 0012; redesigned in P1-20, ADR 0028) — sidebar,
 * top bar, #main, page header, toast region, conflict modal, loading states of spec O3 #8 and the Form-pattern
 * save bar.
 *
 * Loaded after inventory.css (Views/layouts/_head.php). Values come from var(--token) only (no hex/rgb, checked by
 * scripts/qa-token-scan.php + DesignTokensTest); the only literal lengths are 1px/2px/3px strokes, rem widths of
 * the frame and unitless factors. Motion never exceeds --dur. The component kit (DataTable, StatCard, EmptyState,
 * …) is inventory-components.css (P0-16), loaded after this file.
 *
 * Sidebar states: full (default) · icons-only on desktop (`.app.is-nav-mini`, remembered per device by
 * inventory-app.js) · drawer on a phone (`.app.is-nav-open`, Alpine). The active item is marked by a left accent
 * bar AND a soft background AND aria-current — never by colour alone.
 */

/* ============================================================ 1. frame (.app / .side / .main) */
[x-cloak]{display:none!important}

.inv-shell{min-height:100vh;background:var(--bg)}
.app{display:grid;grid-template-columns:var(--side-w) minmax(0,1fr);min-height:100vh;
  transition:grid-template-columns var(--dur) ease-out}
.app.is-nav-mini{grid-template-columns:var(--side-w-mini) minmax(0,1fr)}

.side{position:sticky;top:0;display:flex;flex-direction:column;height:100vh;overflow:hidden;
  padding:var(--s3) var(--s2) var(--s2);background:var(--surface);border-right:1px solid var(--line)}

.brandrow{display:flex;align-items:center;gap:var(--s2);min-height:var(--hdr-h);padding:0 var(--s2) var(--s3);
  font-weight:700;font-size:var(--t-sm);line-height:var(--lh-head);color:var(--ink);text-decoration:none;
  white-space:nowrap;overflow:hidden}
.brandrow>span:not(.brand-mark){min-width:0;overflow:hidden;text-overflow:ellipsis}
a.brandrow:hover{color:var(--primary)}
a.brandrow:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-sm)}
.brand-mark{display:inline-grid;place-items:center;flex:none;width:var(--s6);height:var(--s6);
  border-radius:var(--r-sm);background:var(--primary);color:var(--primary-ink);box-shadow:var(--sh-1)}
.brand-mark .inv-icon{width:1.25rem;height:1.25rem}
/* P8-05: the company whose data this is, under the product name (one address for every tenant, DECISIONS #30) */
.brand-text{display:grid;min-width:0}
.brand-text>span{min-width:0;overflow:hidden;text-overflow:ellipsis}
.brand-tenant{font-size:var(--t-xs);font-weight:500;color:var(--ink-3)}

.side .nav-list{margin:0;padding:0;list-style:none}
.side .nav-list a{position:relative;display:flex;align-items:center;gap:var(--s3);min-height:var(--control-h);
  margin:1px 0;padding:var(--s2) var(--s3);border-radius:var(--r-sm);color:var(--ink-2);font-size:var(--t-sm);
  font-weight:500;text-decoration:none;white-space:nowrap;overflow:hidden;
  transition:background-color var(--dur),color var(--dur)}
.side .nav-list a .inv-icon{color:var(--ink-3);transition:color var(--dur)}
.side .nav-list a:hover{background:var(--surface-2);color:var(--ink)}
.side .nav-list a:hover .inv-icon{color:var(--ink-2)}
.side .nav-list a.on{background:var(--primary-soft);color:var(--primary-soft-ink);font-weight:600}
.side .nav-list a.on .inv-icon{color:var(--primary)}
/* the active marker: a left accent bar, so it still reads in high-contrast and greyscale */
.side .nav-list a.on::before{content:"";position:absolute;left:0;top:var(--s1);bottom:var(--s1);width:3px;
  border-radius:0 var(--r-pill) var(--r-pill) 0;background:var(--primary)}
.side .nav-list a:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
.side .nav-label{overflow:hidden;text-overflow:ellipsis}
.side .grp{padding:var(--s4) var(--s3) var(--s1);color:var(--ink-3);font-size:var(--t-xs);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden}
.nav-section:first-child .grp{padding-top:var(--s1)}
.side-nav{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;
  scrollbar-color:var(--line-strong) transparent}
.side-nav::-webkit-scrollbar{width:var(--s2)}
.side-nav::-webkit-scrollbar-thumb{border-radius:var(--r-pill);background:var(--line-strong)}
.side-foot{flex:none;display:flex;flex-direction:column;gap:var(--s1);margin-top:var(--s2);padding-top:var(--s2);
  border-top:1px solid var(--line)}
.inv-side-toggle{justify-content:flex-start;gap:var(--s3);width:100%;padding-left:var(--s3);
  color:var(--ink-3);font-size:var(--t-xs)}
.inv-side-toggle .inv-icon{color:var(--ink-3)}
.inv-side-toggle-icon{display:inline-flex}

/* icons-only rail: labels and group headings collapse, icons centre, the accent bar stays */
.app.is-nav-mini .side{padding-left:var(--s1);padding-right:var(--s1);align-items:stretch}
.app.is-nav-mini .side .nav-label,
.app.is-nav-mini .side .grp,
.app.is-nav-mini .brandrow span:not(.brand-mark),
.app.is-nav-mini .inv-side-toggle span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.app.is-nav-mini .side .nav-list a,
.app.is-nav-mini .brandrow,
.app.is-nav-mini .inv-side-toggle{justify-content:center;gap:0;padding-left:0;padding-right:0}
.app.is-nav-mini .nav-section+.nav-section{margin-top:var(--s2);padding-top:var(--s2);border-top:1px solid var(--line)}

.main{display:flex;flex-direction:column;min-width:0}
.hdr{position:sticky;top:0;z-index:1020;display:flex;align-items:center;gap:var(--s2);min-height:var(--hdr-h);
  padding:var(--s2) var(--s4);background:var(--surface);border-bottom:1px solid var(--line)}
.hdr-brand{display:none;font-weight:700;font-size:var(--t-sm)}
/* location line: "section › page" — the page's own <h1> stays inside #main (PageHeader) */
/* P1-19: `nowrap` — around 1100px the section name ("ข้อมูลหลัก") used to break in the middle of the word and make
   the top bar two lines tall; the page title next to it already truncates with an ellipsis. */
.hdr-crumb{display:flex;align-items:center;gap:var(--s2);min-width:0;color:var(--ink-3);font-size:var(--t-sm);white-space:nowrap}
.hdr-crumb b{color:var(--ink);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hdr-crumb .inv-icon{color:var(--ink-3)}
.hdr-tools{display:flex;align-items:center;gap:var(--s2);margin-left:auto}
.hdr-user{margin-left:0}
.hdr .dropdown-header.who{max-width:18rem;white-space:normal;color:var(--ink-2);font-size:var(--t-sm);
  font-weight:600;letter-spacing:normal;text-transform:none}
.hdr .dropdown-header.who small{display:block;color:var(--ink-3);font-weight:400}
.inv-avatar-btn{padding:0 var(--s1) 0 0;min-height:var(--tap);border-radius:var(--r-pill)}
.inv-avatar{display:inline-grid;place-items:center;width:var(--s6);height:var(--s6);
  border-radius:50%;background:var(--primary-soft);color:var(--primary-soft-ink);font-size:var(--t-xs);font-weight:700}
.hdr .dropdown-item[aria-pressed="true"]{color:var(--primary);font-weight:600;background:var(--primary-soft)}

/* top-bar search: a real GET form, with the keyboard shortcut written on it */
.hdr-search{position:relative;flex:1 1 22rem;max-width:26rem;margin:0}
.hdr-search .inv-icon{position:absolute;left:var(--s3);top:50%;transform:translateY(-50%);color:var(--ink-3);
  pointer-events:none}
.hdr-search input{padding-left:calc(var(--s5) + var(--s2));padding-right:var(--s7);background:var(--surface-2);
  border-color:transparent}
.hdr-search input:focus{background:var(--surface)}
.hdr-kbd{position:absolute;right:var(--s2);top:50%;transform:translateY(-50%);padding:0 var(--s2);
  border:1px solid var(--line-strong);border-radius:var(--r-sm);background:var(--surface);color:var(--ink-3);
  font-family:var(--f-mono);font-size:var(--t-xs);line-height:var(--s5);pointer-events:none}

.content{flex:1;padding:var(--s5) var(--s5) var(--s8);outline:none}
.inv-backdrop{display:none}

/* mobile menu toggle: 48px target (O2 mobile-first), hidden on desktop */
.inv-nav-toggle{display:none;min-width:var(--tap);min-height:var(--tap);padding:0}
.inv-burger{position:relative;display:block;width:1.25rem;height:1.25rem}

@media (max-width:63.99rem){
  .hdr-search{flex-basis:12rem}
  .hdr-kbd{display:none}
}
@media (max-width:51.24rem){
  .app,
  .app.is-nav-mini{grid-template-columns:minmax(0,1fr)}
  .side{position:fixed;inset:0 auto 0 0;z-index:1045;width:min(18rem,85vw);box-shadow:var(--sh-3);
    transform:translateX(-100%);visibility:hidden;transition:transform var(--dur) ease-out,visibility 0s linear var(--dur)}
  .app.is-nav-open .side{transform:none;visibility:visible;transition-delay:0s}
  .app.is-nav-mini .side{padding-left:var(--s2);padding-right:var(--s2)}
  .app.is-nav-mini .side .nav-label,
  .app.is-nav-mini .side .grp{position:static;width:auto;height:auto;clip-path:none}
  .app.is-nav-mini .side .nav-list a,
  .app.is-nav-mini .brandrow{justify-content:flex-start;gap:var(--s3);padding-left:var(--s3);padding-right:var(--s3)}
  .inv-backdrop{display:block;position:fixed;inset:0;z-index:1040;background:color-mix(in srgb,var(--ink) 45%,transparent)}
  .side .nav-list a{min-height:var(--tap)}
  .side-foot .inv-side-toggle{display:none}
  .inv-nav-toggle{display:inline-flex}
  .hdr{gap:var(--s1);padding:var(--s1) var(--s2)}
  /* P8-23: the warehouse theme's 48px bell, language pills and avatar ran 1px past a 360px screen with an 8px gap
     between them (the whole page scrolled sideways); a 4px gap keeps every target 48px and the bar inside the screen. */
  .hdr-tools{gap:var(--s1)}
  .hdr-brand{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .hdr-crumb,
  .hdr-search{display:none}
  /* the theme switcher would push the top bar past a 360px screen; the same four choices are in the user
     menu below, so only the language pills stay out here (they have no second home). */
  .inv-theme-seg{display:none}
  .content{padding:var(--s4) var(--s3) var(--s8)}
}
/* P8-23: below ~480px the product name next to the menu button was squeezed to a 3px sliver of its first letter; it
   is the first line of the menu drawer the button opens, so on a phone the bar leaves it out. */
@media (max-width:30rem){
  .hdr-brand{display:none}
}

/* ============================================================ 2. page header (.ph) */
.ph{display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--s3);margin-bottom:var(--s5)}
.ph h1{font-size:var(--t-2xl)}
.ph .crumb{margin-bottom:var(--s1);color:var(--ink-3);font-size:var(--t-xs)}
.ph .crumb a{color:inherit;text-decoration:none}
.ph .crumb a:hover{color:var(--primary);text-decoration:underline}
.ph .acts{display:flex;flex-wrap:wrap;gap:var(--s2);margin-left:auto}
.inv-lead{max-width:48rem;margin:0 0 var(--s4);color:var(--ink-3);font-size:var(--t-sm)}
.content h2{font-size:var(--t-xl)}
.inv-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}

/* ============================================================ 3. loading (O3 #8): no work may look finished early */
.inv-progress{position:fixed;inset:0 0 auto;z-index:1100;height:3px;background:var(--primary);
  transform:scaleX(0);transform-origin:left;opacity:0;transition:transform var(--dur) ease-out,opacity var(--dur) ease-out;
  pointer-events:none}
.inv-navigating .inv-progress{transform:scaleX(.7);opacity:1}
.inv-navigating #main{opacity:.6;transition:opacity var(--dur) ease-out var(--dur)}

.htmx-indicator{display:none}
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator{display:inline-block}
.inv-spin{flex:none;width:.875rem;height:.875rem;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;
  animation:inv-spin .7s linear infinite}
@keyframes inv-spin{to{transform:rotate(360deg)}}
.inv-busy-label{display:none}
.htmx-request .inv-busy-label{display:inline}
.htmx-request .inv-idle-label{display:none}
.inv-busy{transition:opacity var(--dur) ease-out}
.inv-busy.htmx-request{opacity:.55;pointer-events:none}
[aria-busy="true"]{cursor:progress}

@media (prefers-reduced-motion:reduce){
  .inv-spin{animation-duration:1.4s}
  .inv-progress,.side,.app,.inv-busy{transition:none}
}

/* ============================================================ 4. toasts (styleguide .toast) */
.inv-toasts{position:fixed;right:var(--s4);bottom:var(--s4);z-index:1090;display:flex;flex-direction:column;gap:var(--s2);
  width:min(23.75rem,calc(100vw - var(--s4) * 2));pointer-events:none}
.inv-toast{display:flex;align-items:flex-start;gap:var(--s3);padding:var(--s3) var(--s4);background:var(--surface);
  color:var(--ink);border:1px solid var(--line);border-left:3px solid var(--c-ok);border-radius:var(--r);
  box-shadow:var(--sh-3);pointer-events:auto;animation:inv-toast-in var(--dur) ease-out}
.inv-toast.is-error{border-left-color:var(--c-err)}
.inv-toast.is-warning{border-left-color:var(--c-warn)}
.inv-toast.is-info{border-left-color:var(--c-info)}
.inv-toast-icon{flex:none;display:inline-flex;align-items:center;justify-content:center;width:var(--s5);height:var(--s5);
  margin-top:1px;color:var(--c-ok)}
.inv-toast.is-error .inv-toast-icon{color:var(--c-err)}
.inv-toast.is-warning .inv-toast-icon{color:var(--c-warn)}
.inv-toast.is-info .inv-toast-icon{color:var(--c-info)}
.inv-toast-icon .inv-icon{width:100%;height:100%}
.inv-toast-body{flex:1;min-width:0}
.inv-toast-body b{font-size:var(--t-sm);font-weight:700} /* inline <b>, as in the styleguide: the first line box is the body one */
.inv-toast-detail{color:var(--ink-3);font-size:var(--t-xs)}
.inv-toast-retry{margin-top:var(--s2)}
.inv-toast .btn-close{flex:none}
@keyframes inv-toast-in{from{opacity:0;transform:translateY(var(--s2))}to{opacity:1;transform:none}}
@media (max-width:51.24rem){
  /* store phones keep the primary action at the bottom (O2): toasts go to the top */
  .inv-toasts{top:var(--s3);right:var(--s3);bottom:auto;left:var(--s3);width:auto}
}

/* ============================================================ 5. 409 conflict modal (O3 #9) */
.inv-conflict-modal .modal-title{font-size:var(--t-lg)}
.inv-conflict-message{margin:0 0 var(--s2);font-weight:600}
.inv-conflict-panel.card{margin-bottom:var(--s4);padding:var(--s4);border-left:3px solid var(--c-warn)}
.inv-conflict-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--s2);margin-top:var(--s4)}
.inv-conflict-actions form{margin:0}
.inv-diff tbody th{font-weight:500}
.inv-diff tr.is-changed>*{background:var(--c-warn-bg);color:var(--c-warn-fg)}
.inv-diff-flag{display:inline-block;margin-left:var(--s1);padding:0 var(--s2);border-radius:var(--r-pill);
  background:var(--surface);color:var(--c-warn-fg);font-size:var(--t-xs);font-weight:600}

/* ============================================================ 6. Form pattern: one column, cards, sticky save bar */
.inv-form{max-width:45rem}
/* `minmax(0, …)`, not the implicit `auto`: a grid column is as wide as its widest item's MIN-CONTENT, so one wide
   child — a DataTable, whose own `min-width` is what makes it scroll inside its wrapper — pushed the whole detail
   column to 686px on a 360px phone and the page scrolled sideways (P1-19 visual QA). */
.inv-form-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s4)}
.inv-form .card+.card{margin-top:var(--s4)}
/* the fieldset that makes a whole form read-only (no edit permission, archived record) — no box of its own */
.inv-form-lock{min-width:0;margin:0;padding:0;border:0}
.inv-form .card-body>h2{margin-bottom:var(--s3);font-size:var(--t-lg)}
/* fields side by side from tablet width: .is-2 halves, .is-3 = one wide + two narrow (name · type · required) */
.inv-form-cols{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s4)}
.inv-form-cols>.is-wide{grid-column:1/-1}
@media (min-width:40rem){
  .inv-form-cols.is-2{grid-template-columns:repeat(2,minmax(0,1fr))}
  .inv-form-cols.is-3{grid-template-columns:minmax(0,2fr) repeat(2,minmax(0,1fr))}
}
.inv-meta-list{margin:0;padding:0;list-style:none;font-size:var(--t-sm)}
.inv-meta-list li{display:flex;flex-wrap:wrap;gap:var(--s2);justify-content:space-between;padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.inv-meta-list li:last-child{border-bottom:0}
.inv-field .form-control.num{text-align:right}
.inv-field .invalid-feedback{display:flex;gap:var(--s1);align-items:flex-start}
/* P1-19: a `btn-block` primary in the save bar took the whole row and squeezed the secondary next to it until its
   label broke over two lines ("Back to stock movements"). The bar is already full width on a phone through
   `.inv-savebar .btn{flex:1}` below, so block has nothing left to do here. */
.inv-savebar .btn-block{width:auto}
.inv-savebar{position:sticky;bottom:0;z-index:5;display:flex;justify-content:flex-end;gap:var(--s2);margin-top:var(--s5);
  padding:var(--s3) 0;background:var(--bg);border-top:1px solid var(--line)}
/* P4-17 keyboard-first (WCAG 2.4.11): a field reached with Tab never sits under the sticky top bar or the sticky save
   bar — the browser scrolls a focused element clear of the scroll padding. Before this the invited-vendor cards of
   the RFQ form took the focus hidden behind "เปิด RFQ" at 1440x900. The bar is one control row + its padding. */
html:has(.hdr){scroll-padding-top:calc(var(--hdr-h) + var(--s2))}
html:has(.inv-savebar){scroll-padding-bottom:calc(var(--control-h) + var(--s3) * 2 + var(--s4))}
/* P1-05 one screen: photos · fields · save bar evenly spaced, one column, nothing else competing for the thumb */
.inv-quick{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s4)}
.inv-quick .inv-savebar{margin-top:0}
/* P1-09 quick actions of a scanned label: full-width, thumb-high buttons stacked under the card on a phone */
.inv-quick-actions{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s4)}
.inv-quick-actions .btn{flex:1 1 9rem;min-height:var(--tap)}
/* a note beside the buttons ("เพิ่มรายการต่อไป" of the one-screen add form, P1-05) */
.inv-savebar-note{display:flex;align-items:center;gap:var(--s2);margin-right:auto;padding:0;font-size:var(--t-sm)}
.inv-savebar-note .form-check-input{float:none;margin:0}
.inv-savebar-note .form-check-label{margin:0}
/* P2-05 ยืนยันการจอง: one form in the save bar — the sentence that says what the press will do, then the button */
.inv-reserve{display:flex;align-items:center;gap:var(--s3);margin:0}
.inv-reserve .form-text{max-width:26rem;margin:0;text-align:end}
@media (max-width:51.24rem){
  html:has(.inv-savebar){scroll-padding-bottom:calc(var(--tap) + var(--s3) + var(--s4) * 2)}
  html:has(.inv-savebar-note){scroll-padding-bottom:calc(var(--tap) * 2 + var(--s2) + var(--s3) + var(--s4) * 2)}
  .inv-savebar{flex-wrap:wrap;padding-bottom:var(--s4)}
  .inv-savebar .btn{flex:1;min-height:var(--tap)}
  .inv-savebar-note{flex:1 0 100%;min-height:var(--tap);margin:0}
  /* on a phone the booking is the one thing on the bar: its sentence takes the row above, the button the whole width */
  .inv-reserve{flex:1 0 100%;flex-wrap:wrap;gap:var(--s2)}
  .inv-reserve .form-text{flex:1 0 100%;max-width:none;text-align:start}
  .inv-reserve .btn{flex:1;min-height:var(--tap)}
}

/* ============================================================ 6b. home (P0-10 landing, redesigned in P1-20) */
.inv-home-quick{margin-bottom:var(--s7)}
.inv-home-quick h2,
.inv-home-roles h2{margin-bottom:var(--s4);font-size:var(--t-lg)}
.inv-home-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,15rem),1fr));gap:var(--s3)}
.inv-home-card{display:flex;align-items:center;gap:var(--s3);min-height:calc(var(--s7) + var(--s5));
  padding:var(--s4);background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--sh-1);color:var(--ink);font-weight:600;text-decoration:none;
  transition:box-shadow var(--dur),border-color var(--dur),transform var(--dur)}
.inv-home-card:hover{color:var(--ink);border-color:var(--c-brand-200);box-shadow:var(--sh-2);transform:translateY(-1px)}
.inv-home-card:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.inv-home-card-icon{display:grid;place-items:center;flex:none;width:var(--s7);height:var(--s7);
  border-radius:var(--r-sm);background:var(--primary-soft);color:var(--primary)}
.inv-home-card-label{flex:1;min-width:0}
/* P2-14: the reports home puts one line of "what does this report answer" under the name of the report */
.inv-home-card-label small{display:block;font-weight:400;font-size:var(--t-sm);color:var(--ink-3)}
.inv-home-card-go{color:var(--ink-3)}
.inv-home-card:hover .inv-home-card-go{color:var(--primary)}
.inv-home-roles ul{display:flex;flex-wrap:wrap;gap:var(--s2);margin:0;padding:0;list-style:none}
.inv-home-roles li{display:inline-flex;align-items:center;gap:var(--s2);padding:var(--s1) var(--s3);
  border:1px solid var(--line);border-radius:var(--r-pill);background:var(--surface);color:var(--ink-2);
  font-size:var(--t-sm);font-weight:600}
.inv-home-roles li .inv-icon{color:var(--accent)}
@media (prefers-reduced-motion:reduce){ .inv-home-card:hover{transform:none} }

/* ============================================================ 7. layout bits of the /ui/shell demo (its list is kit components) */
.inv-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,11rem),1fr));gap:var(--s4);margin-bottom:var(--s5)}
.inv-stats-note{grid-column:1/-1;margin:0}
.inv-tablewrap{overflow-x:auto;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--sh-1)}
.inv-tablewrap .table{min-width:36rem}
.inv-tablewrap .table>tbody>tr:last-child>*{border-bottom-width:0}
.inv-checks{margin-top:var(--s5)}
.inv-checks .card-body h2{margin-bottom:var(--s3);font-size:var(--t-lg)}
.inv-detail{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(0,1fr);gap:var(--s5);align-items:start}
.inv-detail-side h2{margin-bottom:var(--s2);font-size:var(--t-lg)}
.inv-detail-side p{margin:0 0 var(--s2)}
.inv-detail-side form{margin:var(--s3) 0 var(--s2)}
@media (max-width:51.24rem){
  .inv-detail{grid-template-columns:minmax(0,1fr)}
  .inv-tablewrap .table{min-width:32rem}
}
/* a Detail tab with several blocks in its main column (P1-04 photos: lead · uploader · gallery) + a list of tips */
.inv-stack{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s4);align-content:start}
.inv-stack>.inv-lead{margin:0}
/* P8-23: a note under a list (the users screen's "no e-mail sender yet") sat flush against the table's edge */
.inv-dt+.inv-lead{margin-top:var(--s3)}
.inv-tips{margin:0 0 var(--s3);padding-left:var(--s5);font-size:var(--t-sm);color:var(--ink-2)}
.inv-tips li+li{margin-top:var(--s1)}
.inv-cover{display:block;margin:0 0 var(--s3);border:1px solid var(--line);border-radius:var(--r);overflow:hidden;background:var(--surface-2)}
.inv-cover img{display:block;width:100%;height:auto;aspect-ratio:1/1;object-fit:cover}
a.inv-cover:hover{border-color:var(--primary)}
a.inv-cover:focus-visible{outline:2px solid var(--focus);outline-offset:2px}

/* ============================================================ 8. P1-12 ตรวจนับ — the blind counting screen (spec P5
   "Count: รายการตามตำแหน่ง, ช่องตัวเลขใหญ่, ไม่แสดง expected") plus the small inline forms of the count sheet.
   One card per line so a thumb can only ever touch one row's number, and the row that has to be recounted by another
   person is marked with the warning colour instead of a second column of text. */
.inv-count-lines{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s3)}
.inv-count-line .card-body{display:grid;gap:var(--s2)}
.inv-count-line-title{margin:0;font-size:var(--t-md);line-height:var(--lh-body)}
.inv-count-line-meta{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);margin:0;font-size:var(--t-sm);color:var(--ink-2)}
.inv-count-line-meta .num{font-family:var(--f-mono);font-variant-numeric:tabular-nums}
.inv-count-line-form{display:grid;gap:var(--s2)}
.inv-count-line.is-recount{border-color:var(--c-warn)}
.inv-count-line.is-recount .inv-count-line-title::after{content:'';display:inline-block;width:var(--s2);height:var(--s2);
  margin-left:var(--s2);border-radius:var(--r-pill);background:var(--c-warn);vertical-align:middle}
@media (min-width:51.25rem){
  .inv-count-line-form{grid-template-columns:minmax(0,1fr) auto;align-items:end}
}

/* one field + one button on a line (the cause of a variance, "ตีกลับให้นับใหม่") */
.inv-inline-form{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s2);margin:var(--s3) 0}
.inv-inline-form .inv-field{flex:1 1 12rem;margin:0}
.inv-inline-form .form-select{min-height:var(--control-h)}

/* short list of recorded facts (SoD exceptions on a count sheet) */
.inv-notes{margin:0 0 var(--s4);padding-left:var(--s5);font-size:var(--t-sm);color:var(--ink-2)}
.inv-notes li+li{margin-top:var(--s1)}

/* ============================================================ 9. P2-03 สร้างออเดอร์เช่า — the 3-step wizard
   (spec O2 pattern 4, screens.html #3). The date bar sits above everything because the window decides every
   number under it; the cart is one card per line so a thumb only ever touches one line's quantity, and the
   summary carries the one primary action of the screen. */
.inv-availbar .card-body{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s2) var(--s3)}
.inv-availbar .inv-field{flex:1 1 9rem;margin:0}
.inv-availbar-note{flex:1 1 100%;margin:0;font-size:var(--t-sm);color:var(--ink-2)}
.inv-cart{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s3);margin:0 0 var(--s4);padding:0;list-style:none}
.inv-cart-line .card-body{display:grid;gap:var(--s2)}
.inv-cart-title{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--s2);margin:0;font-size:var(--t-md);
  line-height:var(--lh-body)}
.inv-cart-meta{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);margin:0;font-size:var(--t-sm);color:var(--ink-2)}
.inv-cart-form{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s2)}
.inv-cart-form .inv-field,
.inv-cart-form .inv-qty{flex:1 1 8rem;margin:0}
.inv-cart-line.is-short{border-color:var(--c-warn)}

/* ============================================================ notification bell (P2-13, spec F8)
   The bell of the top bar and its dropdown of the newest messages. The unread badge is a count, and the
   colour of a row is a 3px dot in the level's own token — never the whole row, so a long Thai title stays
   readable in all four themes. The panel is a plain Bootstrap dropdown: no JavaScript of its own, and every
   row is a link, so hx-boost carries it like any other navigation. */
.inv-bell{position:relative}
.inv-bell-btn{position:relative;min-width:var(--tap);min-height:var(--tap);border-radius:var(--r-pill)}
/* P2-15: the count is 12px on the loud rose fill — white reads on the light theme's `--c-err` (4.7:1) but only
   2.7:1 on the lighter rose the dark themes use, so the ink comes from the token that flips with the theme. */
.inv-bell-badge{position:absolute;top:var(--s1);right:var(--s1);min-width:var(--s4);padding:0 var(--s1);
  border-radius:var(--r-pill);background:var(--c-err);color:var(--c-err-ink);font-size:var(--t-xs);
  font-weight:700;line-height:var(--s4);text-align:center}
.inv-bell-menu{width:min(22rem,calc(100vw - var(--s5)));padding:0;overflow:hidden}
.inv-bell-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  padding:var(--s3) var(--s3) var(--s2);border-bottom:1px solid var(--line);font-weight:600;color:var(--ink)}
.inv-bell-head form{margin:0}
.inv-bell-list{max-height:22rem;margin:0;padding:0;overflow-y:auto;list-style:none}
.inv-bell-item{border-bottom:1px solid var(--line)}
.inv-bell-item:last-child{border-bottom:0}
.inv-bell-link{display:flex;gap:var(--s2);padding:var(--s2) var(--s3);color:var(--ink);text-decoration:none}
a.inv-bell-link:hover{background:var(--surface-2)}
a.inv-bell-link:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
.inv-bell-dot{flex:none;width:var(--s1);height:var(--s1);margin-top:var(--s2);border-radius:50%;
  background:var(--c-info)}
.inv-bell-item.is-success .inv-bell-dot{background:var(--c-ok)}
.inv-bell-item.is-warning .inv-bell-dot{background:var(--c-warn)}
.inv-bell-item.is-danger .inv-bell-dot{background:var(--c-err)}
.inv-bell-item:not(.is-unread) .inv-bell-dot{background:var(--line-strong)}
.inv-bell-text{display:grid;gap:var(--s1);min-width:0}
.inv-bell-text b{font-size:var(--t-sm);font-weight:600;line-height:var(--lh-head)}
.inv-bell-item:not(.is-unread) .inv-bell-text b{font-weight:400;color:var(--ink-2)}
.inv-bell-text small,
.inv-bell-text time{font-size:var(--t-xs);color:var(--ink-3)}
.inv-bell-empty,
.inv-bell-error{margin:0;padding:var(--s4) var(--s3);color:var(--ink-3);font-size:var(--t-sm);text-align:center}
.inv-bell-error{color:var(--c-err-fg)}
.inv-bell-skel{margin:var(--s3)}
.inv-bell-all{display:flex;align-items:center;justify-content:center;gap:var(--s1);
  padding:var(--s2) var(--s3);border-top:1px solid var(--line);background:var(--surface-2);
  color:var(--primary);font-size:var(--t-sm);text-decoration:none}
.inv-bell-all:hover{background:var(--primary-soft);color:var(--primary-soft-ink)}
.inv-bell-all:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}

/* the inbox screen: the same rows, full width, with what they are about */
.inv-inbox{display:grid;gap:0;margin:0;padding:0;list-style:none;border:1px solid var(--line);
  border-radius:var(--r);background:var(--surface);overflow:hidden}
.inv-inbox .inv-bell-item{border-bottom:1px solid var(--line)}
.inv-inbox .inv-bell-link{padding:var(--s3) var(--s4);gap:var(--s3)}
.inv-inbox .inv-bell-text b{font-size:var(--t-md)}
.inv-bell.is-disabled .inv-bell-btn{opacity:.55;cursor:not-allowed}
.inv-bell.is-loading .inv-bell-btn{opacity:.7}

/* ============================================================ P3-03 "คำขอจากลูกค้า" card of the order screen
   (ADR 0060 #5) — the postpone / cancel a customer sent from their own tracking page, loaded into the order
   detail by htmx and swapped back by every answer. */
.inv-reqs{display:grid;gap:var(--s3);padding:var(--s4)}
.inv-reqs h2{margin:0;font-size:var(--t-lg)}
.inv-reqs-none{margin:0;color:var(--ink-3);font-size:var(--t-sm)}
.inv-reqs-link{display:grid;gap:var(--s1);margin:0;font-size:var(--t-xs)}
.inv-reqs-link span{color:var(--ink-3)}
.inv-reqs-link a{overflow-wrap:anywhere}
/* P6-15: on a touch screen the customer's own link (a long address, two lines at 360px — 38px) is a --tap tall target */
@media (pointer:coarse){ .inv-reqs-link a{display:flex;align-items:center;min-height:var(--tap)} }
.inv-reqs-list{display:grid;gap:var(--s3);margin:0;padding:0;list-style:none}
.inv-reqs-item{display:grid;gap:var(--s2);padding-bottom:var(--s3);border-bottom:1px solid var(--line)}
.inv-reqs-item:last-child{border-bottom:0;padding-bottom:0}
.inv-reqs-item.is-pending{padding:var(--s3);border-bottom:0;border-radius:var(--r);
  background:var(--c-warn-bg);color:var(--c-warn-fg)}
.inv-reqs-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}
.inv-reqs-when{margin-inline-start:auto;color:var(--ink-3);font-size:var(--t-xs)}
.inv-reqs-item.is-pending .inv-reqs-when{color:inherit}
.inv-reqs-days,
.inv-reqs-reason,
.inv-reqs-note{margin:0;font-size:var(--t-sm)}
.inv-reqs-reason{color:var(--ink-2)}
.inv-reqs-note{color:var(--ink-3)}
.inv-reqs-item.is-pending .inv-reqs-reason,
.inv-reqs-item.is-pending .inv-reqs-note{color:inherit}
.inv-reqs-form{display:grid;gap:var(--s3);padding-top:var(--s3);border-top:1px solid var(--line)}
.inv-reqs-acts{display:flex;flex-wrap:wrap;gap:var(--s2)}

/* ---- P8-05: a new password link, shown once on the person's page (admin/users, ADR 0066) ---- */
.inv-account-link{margin-bottom:var(--s4);border-color:var(--primary)}
.inv-account-link h2{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s2);font-size:var(--t-lg)}
.inv-account-link p{margin:0 0 var(--s3);font-size:var(--t-sm)}
.inv-account-link-row{display:flex;flex-wrap:wrap;gap:var(--s2);margin-bottom:var(--s2)}
.inv-account-link-row .form-control{flex:1 1 20rem;min-width:0}
.inv-account-link .inv-account-link-note{margin:0 0 var(--s1);color:var(--ink-3);font-size:var(--t-xs)}

/* ---- P9-18: "การเรียกเก็บเงิน — จัดการที่ Single Point" (billing, ADR 0117) — read only: the plan card, one CapacityBar
   per cap (two across on a wide screen, one on a phone) and the modules the licence lists. Colours stay the kit's. ---- */
#billing-page>.inv-lead,
#billing-page>.inv-notice{margin:0}
.inv-billing-h{margin-bottom:var(--s3);font-size:var(--t-lg)}
.inv-billing-lead{margin:calc(var(--s2) * -1) 0 var(--s4);color:var(--ink-3);font-size:var(--t-sm)}
.inv-billing-caps{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,15rem),1fr));gap:var(--s4) var(--s5)}
.inv-billing-cap{display:grid;gap:var(--s1);min-width:0}
.inv-billing-cap-name{margin:0;font-size:var(--t-sm);font-weight:600;line-height:var(--lh-head)}
.inv-billing-caps+.form-text{margin:var(--s4) 0 0}
.inv-billing-module{display:inline-flex;align-items:center;gap:var(--s1);font-weight:600}
.inv-meta-list li.is-off .inv-billing-module{color:var(--ink-3);font-weight:400}
