body { font-family: Arial, Helvetica, sans-serif; margin: 0; background: #f5f6f7; color: #1a1a1a; }
header { background: #1a2f4b; color: #fff; padding: 14px 24px; display: flex; justify-content: space-between; align-items: center; }
header h1 { font-size: 32px; margin: 0; }
/* header h1 font-size history: 16px -> 40px (increased by 150%) -> 32px
   (shrunk to 80% of 40px). */

/* Company logo in the header's upper-left corner. The logo art itself is
   dark navy/red on a transparent background, so it needs a light card
   behind it to stay legible against the dark header — otherwise it nearly
   disappears into header's navy background. */
.brand { display: flex; align-items: center; gap: 16px; }
.brand-logo-wrap { background: #fff; padding: 6px 10px; border-radius: 6px; line-height: 0; }
.brand-logo { height: 56px; width: auto; display: block; }
main { max-width: 960px; margin: 24px auto; padding: 0 16px; }
.card { background: #fff; border: 1px solid #ddd; border-radius: 6px; padding: 20px; margin-bottom: 16px; }
label { display: block; margin-bottom: 6px; font-weight: bold; font-size: 13px; }
input[type=text] { padding: 8px; font-size: 14px; width: 240px; border: 1px solid #bbb; border-radius: 4px; }

/* Order Number + Line Item Filter side by side, with the Search button
   dropping to its own row underneath (see public/search.html). */
.field-row { display: flex; gap: 24px; margin-bottom: 12px; flex-wrap: wrap; }
.field-group { display: flex; flex-direction: column; }
.field-group label { margin-bottom: 6px; }
#orderSearch button { margin-top: 4px; }
button { padding: 8px 16px; font-size: 14px; background: #1a2f4b; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
button:hover { background: #223d63; }
button.secondary { background: #888; }
.error { color: #b00020; margin-top: 8px; font-size: 13px; }
.success { color: #1a7a3c; margin-top: 8px; font-size: 13px; }
.tabs { display: flex; gap: 8px; margin-bottom: 16px; }
.tabs button { background: #eee; color: #333; }
.tabs button.active { background: #1a2f4b; color: #fff; }
table { width: 100%; border-collapse: collapse; margin-top: 12px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; font-size: 13px; }
th { background: #f0f2f5; }

/* search.html's Results table only — table-layout:fixed (see the <colgroup>
   in search.html) means every cell wraps its content to its column's
   declared width instead of the column growing to fit; word-break here is
   the extra push needed for the Line Items cell specifically (9/2026,
   Dan) — a great many short line-number links/icons in a row, packed with
   no natural word-break spaces between them, could otherwise still resist
   wrapping even inside a fixed-width column. */
table.results-table { table-layout: fixed; }
td.lines-cell { white-space: normal; word-break: break-word; overflow-wrap: break-word; }

a.line-link { margin-right: 6px; }
/* Line items with no heat code / MTR available yet render as plain,
   non-clickable text instead of a link (see public/search.js). */
span.line-nolink { margin-right: 6px; color: #888; cursor: default; }

/* "Generate all MTRs" button next to a row's line-item list — combines
   every MTR-available line currently shown for that order into one
   PDF/HTML document (see public/search.js). */
a.generate-all-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  margin-left: 4px;
  border: 1px solid #bbb;
  border-radius: 4px;
  background: #f0f2f5;
  vertical-align: middle;
}
a.generate-all-btn:hover { background: #e2e6eb; }
a.generate-all-btn img { width: 15px; height: 15px; }
.hidden { display: none; }

/* Sold to / Ship to address blocks on order.html. Once the address field
   comes back as multiple lines (real CR/LF characters, e.g. Address1 /
   Address2 / Address3 / "City State Zip" each on their own line — see the
   BAQ calculated-field guidance for Calc_ShipToAddress), plain HTML would
   otherwise collapse those line breaks like any other whitespace. pre-wrap
   (rather than pre-line) also preserves runs of multiple spaces, in case
   the BAQ field uses extra spacing to line up City/State/Zip. */
.address-block { white-space: pre-wrap; }

/* "MTR Display Format" radio group above the search-results table — the
   default `label` rule above (display:block, bold) is meant for form field
   labels, not inline radio options, so it's overridden here. */
fieldset.format-toggle {
  display: flex;
  align-items: center;
  gap: 16px;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 6px 14px;
  margin-bottom: 4px;
}
fieldset.format-toggle legend {
  font-weight: bold;
  font-size: 13px;
  padding: 0 6px;
}
label.format-option {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: normal;
  font-size: 13px;
  margin-bottom: 0;
  cursor: pointer;
}

/* order.html only — wider than the default `main` (960px) so there's room
   for a left sidebar next to the line-items grid without cramping either.
   Scoped to this one page via the extra class rather than changing `main`
   itself, so search.html/index.html keep their original, narrower width. */
main.wide { max-width: 1300px; }

/* Order # / Order Date / PO# / Ordered By / Salesperson / Sold To / Ship To
   as a stacked left column instead of the old top banner — see order.html.
   Sidebar first (left) and narrower; the line-items grid + MTR panel take
   the wider remaining column and lead with the grid at the very top, per
   Dan's layout request (9/2026). Stacks to a single column below 900px so
   this doesn't get cramped on a narrower window. */
.order-layout {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 16px;
  align-items: start;
}
@media (max-width: 900px) {
  .order-layout { grid-template-columns: 1fr; }
}
.order-sidebar > div { margin-bottom: 14px; }
.order-sidebar > div:last-child { margin-bottom: 0; }
.order-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

/* Collapsible <details>/<summary> sections — order.html's line-items grid,
   and (9/2026) search.html's Search and Results cards too, once an order is
   opened inline below them. Shared as a class rather than per-ID rules
   (originally just #linesDetails) since the same look is now used in
   several places across two pages — the JS on each page only ever toggles
   .open on the <details> element itself; this is purely the look of the
   clickable summary bar, not the expand/collapse behavior. */
details.collapsible > summary {
  cursor: pointer;
  font-weight: bold;
  font-size: 15px;
  list-style: none;
}

/* Search/MTR Lookup's own top-level summary (9/2026, Dan — "make the font
   for the Search/MTR Lookup the same as the Recent Order box") — this is
   the OUTER #searchSection summary specifically, not every collapsible
   summary on the page (the nested "Search"/"Results" ones inside it, and
   order.html's "Line Items", stay at the smaller 15px size above; they're
   sub-sections, not a page-level heading). "Recent Orders" right below it
   is a plain <h2>, which this app never overrides with its own font-size —
   so it renders at the browser's default h2 size (1.5em, ~24px at this
   app's 16px body font). Matched here by number rather than switched to an
   actual <h2> inside the <summary>, since nesting a block-level heading
   element inside <summary> is valid HTML but not worth the risk of
   surprising layout/accessibility quirks for what's really just a font-size
   match. */
#searchSection > summary { font-size: 24px; }
details.collapsible > summary::-webkit-details-marker { display: none; }
details.collapsible > summary::before {
  content: '▾ ';
  display: inline-block;
}
details.collapsible:not([open]) > summary::before {
  content: '▸ ';
}
details.collapsible table { margin-top: 12px; }

/* MTR panel (order.html) — appears below the line-items card once a user
   opens an MTR from the grid; see openMtr() in order.js. */
.mtr-panel-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* flex-wrap (9/2026, Dan) — a "generate all" MTR with a lot of lines
     (test case: 72) makes #mtrPanelTitle's "MTR — Lines 1,2,3,...,72" text
     very long. Flex items default to min-width:auto, meaning a flex item
     won't shrink below its own content's natural width even when the
     container is too narrow for it — without flex-wrap, that long title
     was refusing to give up space, squeezing the Email/Close button group
     off to the side and out of view instead of wrapping. With wrap
     enabled, the button group (flex-shrink:0 below, so it's never the one
     that gets squeezed) simply drops to its own line whenever the title
     doesn't fit beside it, keeping both buttons visible no matter how long
     the line list gets. */
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 12px;
}
.mtr-panel-toolbar a { color: #06c; text-decoration: none; margin-right: 12px; }
.mtr-panel-toolbar a:hover { text-decoration: underline; }
/* Lets the long line-number list wrap onto multiple lines within the title
   itself too, rather than relying purely on the toolbar-level wrap above —
   min-width:0 overrides the flex item's default min-width:auto, which is
   what actually allows it to shrink/wrap in the first place. */
#mtrPanelTitle { min-width: 0; word-break: break-word; }
/* The Email/Close button group never shrinks or wraps internally — see the
   flex-wrap comment above; this is the flex item that's meant to just drop
   to its own row intact when the title needs the space. */
.mtr-panel-toolbar > div { flex-shrink: 0; }

/* Inline "Email" form (9/2026) — appears under the toolbar above when
   #mtrPanelEmailBtn is clicked; see order.js. Its own small bottom margin
   (rather than .card's default) keeps it snug against #mtrPanelErr right
   below it. */
.mtr-email-form { margin-bottom: 12px; }
.mtr-email-form input[type=text] { width: 280px; }
/* Fixed height with its own internal scrollbar, rather than auto-sized to
   content — the panel already collapses the line-items grid to make room
   (see linesDetails.open in order.js), so this just needs to be tall
   enough to be useful without pushing the rest of the page around every
   time a different MTR (single page vs. multi-line) is opened. Works the
   same way for both the format=html (srcdoc) and format=pdf (src, browser's
   native PDF viewer) cases. */
.mtr-frame {
  display: block;
  width: 100%;
  height: 78vh;
  /* min-height floor (9/2026) — this iframe sits nested two levels deep
     (search.html > .order-detail-frame > order.html > this), and `vh` is
     always relative to whichever browsing context's OWN viewport the
     element belongs to — here, order.html's, which is really just however
     tall the OUTER .order-detail-frame iframe happens to be rendered at.
     That's normally plenty (.order-detail-frame is 82vh relative to the
     real top-level window), but chasing down a report of this panel
     rendering with a title/toolbar and NO visible content for some
     sessions — no console/network errors, correct src/srcdoc confirmed via
     DevTools, so not a data or request problem — a collapsed/near-zero
     result somewhere in that vh chain is the most consistent explanation
     even though no staff-vs-customer branch exists anywhere in this file
     or order.js/search.js to point at a specific cause. This floor can't
     hurt the working case (78vh already exceeds it on any normal window)
     and guarantees a real, visible box on any window/nesting combination
     where the vh chain comes out smaller than expected. See also
     sizeMtrFrame() in order.js, which sets an explicit pixel height (read
     live from this frame's own window.innerHeight, sidestepping the vh
     cascade entirely) every time the panel opens or the window resizes —
     belt and suspenders. */
  min-height: 480px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: #fff;
}

/* Order-detail panel embedded on search.html (9/2026) — order.html loaded
   into an iframe below the search/results cards, so opening an order never
   navigates away from the search page. Taller than .mtr-frame since it
   holds order.html's own sidebar + line-items grid, and potentially ITS
   OWN MTR panel further down once a line is opened inside it — order.html
   is completely unchanged for this, it just collapses its own line-items
   grid the exact same way whether it's a full page or sitting in this
   iframe. See order.html/order.js's "embedded" handling for why THIS
   iframe hides order.html's own header/back-link when nested this way. */
.order-detail-frame {
  display: block;
  width: 100%;
  height: 82vh;
  /* Same min-height safety net as .mtr-frame above, and for the same
     reason — this one's relative to the real top-level window (search.html
     is never itself embedded), so it's far less likely to be the one that
     collapses, but it costs nothing to guard it too. */
  min-height: 520px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: #fff;
}

/* order.html rendered inside the iframe above (?embedded=1) — search.html
   already has its own header/ribbon and back-navigation doesn't apply when
   this is just a panel on another page, so order.html's own header is
   suppressed rather than showing a redundant, confusing second one. */
/* Matches BOTH html.embedded (set synchronously in order.html's <head>,
   before first paint — see the inline script there) and body.embedded (set
   later by order.js, kept for back-compat) so this hides the header either
   way it got set. */
html.embedded header, body.embedded header { display: none; }
html.embedded main.wide, body.embedded main.wide { margin-top: 12px; }

/* Top-level "Search / MTR Lookup" vs. "Preview Customer Portal" tab bar
   (9/2026) — same .tabs look the Search card's own sub-tabs already use,
   just given a little breathing room since this one sits directly under
   the header instead of inside a card. */
.main-tabs { margin-top: 4px; margin-bottom: 16px; }

/* Preview Customer Portal order list (9/2026) — see #portalTabView in
   search.html / renderPortalOrders() in search.js. */
table.portal-orders-table { table-layout: fixed; }
td.portal-invoice-cell {
  white-space: normal;
  word-break: break-word;
  overflow-wrap: break-word;
}
/* Each invoice link rendered on its own line within the cell — matches the
   CRLF-separated "one per line" convention used everywhere else in this app
   (see nl2br() in public/order.js) rather than running them together.
   (There used to be a matching .portal-shipments-cell rule here too, for an
   order-level Shipments column — dropped 9/2026, Dan: the header-level
   shipment rollup this needed (Calculated_OrderShipmentList) is no longer
   built; shipment info is shown per line in the expand-row detail grid
   instead, via ORDER_DETAIL_BAQ_ID's existing per-line field. See
   CUSTOMER_PORTAL_ORDERS_BAQ_ID's comment in .env.example.) */
.portal-invoice-cell a { display: block; }
.portal-invoice-cell a { color: #06c; text-decoration: none; }
.portal-invoice-cell a:hover { text-decoration: underline; }

/* Expand/collapse toggle — first column of each order row. Plain button
   styled to look like the ▸/▾ used elsewhere (details.collapsible), rather
   than a real <details> element, since a portal order row's "detail" is a
   whole extra <tr> (holding the line-items iframe) that has to line up
   with the table's own columns — a <details>/<summary> pair can't wrap
   just part of a table row the way it wraps the collapsible cards
   elsewhere in this app. */
.portal-expand-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  padding: 0;
  color: #1a2f4b;
}
tr.portal-order-row { cursor: pointer; }
tr.portal-order-row:hover { background: #f7f8fa; }
tr.portal-detail-row td { padding: 10px; background: #fafbfc; }

/* Order Status badges (9/2026) — see orderStatus() in
   src/routes/portal.js; "On Hold" can't actually be detected yet pending a
   confirmed field from Dan (see CUSTOMER_PORTAL_ORDERS_BAQ_ID's comment in
   .env.example), but the style is ready for whenever it is. */
.status-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 12px;
  font-weight: bold;
}
.status-open { background: #e4f5ea; color: #1a7a3c; }
.status-closed { background: #eceff1; color: #555; }
.status-hold { background: #fdecea; color: #b00020; }

/* Order-list grouping (9/2026, Dan) — a customer session with more than 20
   orders in its window groups them by month; a staff session (always many
   customers at once) always groups by customer instead. See
   renderGroupedPortalOrders()/groupOrdersByMonth()/groupOrdersByCustomer()
   in search.js. A deliberately separate class from the app's generic
   .hidden utility (rather than reusing it) — an order row can be hidden for
   TWO independent reasons now (its own detail row not expanded, AND/OR its
   group being collapsed), and reusing .hidden for both would make toggling
   one accidentally clobber the other. */
/* Filter box above the Recent Orders grid (9/2026, Dan — "a filter box at
   the top ... to filter by company name (for staff), order number, PO
   number, status, and invoice"). Reuses the same .field-group/label look
   the Search card's own fields already use, just wrapped to a new row
   instead of stacking, and includes a plain <select> alongside the text
   inputs — this app's existing input[type=text] rule doesn't cover
   <select>, hence the dedicated rule below. */
.portal-filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
  margin-bottom: 12px;
}
.portal-filter-row select {
  padding: 8px;
  font-size: 14px;
  width: 160px;
  border: 1px solid #bbb;
  border-radius: 4px;
  background: #fff;
}
.portal-filter-row input[type=text] {
  width: 160px;
}

tr.portal-group-collapsed { display: none; }
/* Filter box (9/2026) — toggled by applyPortalFilterVisibility() in
   search.js on every filter-box keystroke, purely via classList.toggle()
   with no DOM rebuild. Kept as its own class, independent from
   .hidden (a row's own expand/collapse) and .portal-group-collapsed
   (its group's open/closed state) above, so none of the three ever
   clobber each other — same reasoning as .portal-group-collapsed. */
tr.portal-filtered-out { display: none; }
tr.portal-group-header td { background: #eef1f5; padding: 0; }
.portal-group-toggle {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  font-weight: bold;
  color: #1a2f4b;
  padding: 8px 10px;
}
.portal-group-toggle:hover { background: #e2e6eb; }
