/*
   The customer portal's stylesheet. Plain CSS, hand-written, and deliberately NOT part of the SCSS
   pipeline: that pipeline scopes every area sheet under .area-x.page-y classes the shared layout puts on
   <body>, and the portal has its own layout with no such classes. It also shares no tokens with the
   internal application on purpose - this is a customer-facing shop front, not an admin screen
   (FDS 11 section 4.1).
*/

:root {
    --brand: #6E2329;
    --brand-dark: #531A1F;
    --page: #F4EDE0;
    --card: #FFFDF8;
    --border: #E4DBCA;
    --text: #23201A;
    --muted: #8C8270;
    --faint: #9A8F79;

    --pending-bg: #F5E7CC;
    --pending-text: #8A5A12;
    --pending-border: #D9B469;
    --good-bg: #E7EFD9;
    --good-text: #3B6B2C;
    --good-border: #A7C07E;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--page);
    color: var(--text);
    font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
    font-size: 16px;
    line-height: 1.5;
    /* Room for the fixed action bar so the last row is never trapped behind it. */
    padding-bottom: 96px;
}

h1, .portal-h1, .portal-card-title, .portal-row-name, .portal-account-name, .portal-brand-name {
    font-family: 'Libre Baskerville', Georgia, serif;
}

/* 720px content column, centred, mobile-first. The page scrolls as one: locking the shell to the
   viewport put a scrollbar in the middle of the page, cut the product list to about three rows once the
   cards above it had their say, and left the fixed bar covering whatever ran underneath. Collapsing the
   lists and the summary is what buys the height back - it does not need the viewport held down too. */
.portal-shell { max-width: 720px; margin: 0 auto; }

.portal-masthead {
    background: var(--brand);
    color: #fff;
    padding: 16px 20px;
    display: flex;
    align-items: center;
    gap: 14px;
}

/* The mark is 430x325. object-fit keeps it a logo rather than letting the masthead stretch it. */
.portal-mark {
    width: 100%;
    max-width: 96px;
    max-height: 64px;
    object-fit: contain;
    flex-shrink: 0;
}

/* text-align centres the name and strapline between the mark and the Profile button - flex:1 already
   gave this block the slack, it was just left-aligned inside it. */
.portal-brand { flex: 1; min-width: 0; text-align: center; }
.portal-brand-name { font-size: 1.15rem; font-weight: 700; }

/* Rule-flanked strapline, as the mockup has it. */
.portal-strapline {
    display: flex; align-items: center; gap: 10px;
    font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
    opacity: .9; margin-top: 2px;
}
.portal-strapline::before, .portal-strapline::after {
    content: ''; flex: 1; height: 1px; background: rgba(255, 255, 255, .4);
}

.portal-account-chip {
    background: rgba(255, 255, 255, .16);
    border: 1px solid rgba(255, 255, 255, .3);
    border-radius: 999px;
    padding: 4px 12px;
    font-size: .8rem;
    max-width: 40%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.portal-body { padding: 20px; display: flex; flex-direction: column; gap: 16px; }

/* The heading and the account on one row, the account against the right edge. baseline rather than
   centre so "Your account" lines up with the heading's own baseline instead of floating against it. */
.portal-topline {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
}

/* The account keeps whatever width its name needs and the heading block gives up the difference. A long
   name - "Martin's Sausage Factory" - was dropping to a line of its own, because wrapping the row is
   what a flex container does before it will shrink an item below its content. So: no wrapping, the
   account refuses to shrink, and min-width:0 is what actually lets the heading block yield (a flex item
   will not go under its content width without it). The strapline beneath the heading takes the extra
   line instead, which is prose and reads fine over two. */
.portal-intro { min-width: 0; }

.portal-account {
    text-align: right;
    flex: 0 0 auto;
}

/* The label and the name on one line. align-items:baseline on the row above matches an item's FIRST
   baseline, so with these two side by side that baseline is the name's - and the name sits level with
   "Trade Ordering" instead of a line under it. The label's own bottom margin has to go, or it would push
   the two apart inside the row. */
.portal-account-head {
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: 10px;
}

.portal-account-head .portal-card-title { margin-bottom: 0; }

.portal-account .portal-account-name { white-space: nowrap; }

/* Stacked on a narrow phone, where side by side would leave nothing for the heading. Left-aligned once
   stacked - a right-aligned block with nothing beside it reads as a mistake rather than as alignment.
   The name may wrap here, which is the right trade at this width: full-width prose, not a squeezed
   column. */
@media (max-width: 520px) {
    .portal-topline { flex-direction: column; }
    .portal-account { text-align: left; }
    .portal-account-head { justify-content: flex-start; }
    .portal-account .portal-account-name { white-space: normal; }
}

.portal-intro .portal-h1 { margin: 0 0 4px; font-size: 1.5rem; }
.portal-muted { color: var(--muted); margin: 0; }
.portal-h1 { margin: 0 0 8px; }

.portal-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
}
.portal-card-centred { text-align: center; padding: 32px 20px; }
.portal-card-suspended { border-color: var(--pending-border); background: var(--pending-bg); }

.portal-card-title {
    font-size: .78rem; letter-spacing: .1em; text-transform: uppercase;
    color: var(--faint); margin-bottom: 8px;
}
/* Smaller than the 1.15rem it carried as a card heading: sitting beside "Trade Ordering" it is a fact
   about the page rather than a title of its own, and at the old size it competed with the heading. */
.portal-account-name { font-size: 1rem; }

.portal-banner { border-radius: 10px; padding: 14px 16px; border: 1px solid; }
.portal-banner-good { background: var(--good-bg); color: var(--good-text); border-color: var(--good-border); }
.portal-banner-warn { background: var(--pending-bg); color: var(--pending-text); border-color: var(--pending-border); }
.portal-banner-title { font-weight: 700; margin-bottom: 4px; }

.portal-form { display: flex; flex-direction: column; gap: 18px; }
.portal-form-head { display: flex; align-items: baseline; justify-content: space-between; }

/* Sits under the form head, above the first range. Small, because it is a boundary condition rather
   than something most customers will ever come near. */
.portal-order-limits { font-size: .84rem; margin-top: -6px; }

.portal-range-band {
    font-size: .74rem; letter-spacing: .12em; text-transform: uppercase;
    color: var(--faint); padding: 0 0 6px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 4px;
}

.portal-row {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--border);
}
.portal-row-main { flex: 1; min-width: 0; }
.portal-row-name { font-size: 1rem; }
.portal-row-desc { color: var(--muted); font-size: .86rem; }
.portal-row-meta { color: var(--faint); font-size: .84rem; margin-top: 2px; }

.portal-row-error { color: #96201F; font-size: .82rem; margin-top: 4px; }
.portal-row-invalid .portal-qty { border-color: #96201F; background: #FDF1F1; }

.portal-row-input { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

/* 70px and right-aligned, as specified: wide enough for a three-digit quantity on a phone. */
.portal-qty {
    width: 70px;
    padding: 8px;
    text-align: right;
    font-size: 1rem;
    font-family: inherit;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: #fff;
    color: var(--text);
}
.portal-row-unit { color: var(--muted); font-size: .86rem; min-width: 34px; }

/* The customer's own note for a product, saved as their note for it on submit. Sits under the product
   detail in the left column, so it does not crowd the quantity input. */
.portal-row-note {
    width: 100%;
    margin-top: 6px;
    padding: 5px 8px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--page);
    color: var(--text);
    font-family: inherit;
    font-size: .82rem;
}
.portal-row-note::placeholder { color: var(--faint); }
.portal-row-note:focus { outline: none; border-color: var(--brand); background: var(--card); }

/* Saved-on-blur feedback: a brief green confirm, a persistent red edge if the save was refused. */
.portal-row-note.is-note-saved { border-color: #2e7d32; background: rgba(46, 125, 50, .06); }
.portal-row-note.is-note-error { border-color: #c62828; background: rgba(198, 40, 40, .06); }

.portal-summary-line {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 0;
    border-bottom: 1px dashed var(--border);
}
.portal-summary-name { flex: 1; min-width: 0; }
.portal-summary-qty { color: var(--muted); font-size: .86rem; white-space: nowrap; }
.portal-summary-total { font-weight: 500; white-space: nowrap; min-width: 68px; text-align: right; }

.portal-remove {
    border: none; background: none; cursor: pointer;
    color: var(--muted); font-size: 1.1rem; line-height: 1;
    padding: 2px 4px;
}
.portal-remove:hover { color: #96201F; }

.portal-date-block { margin-top: 14px; }
.portal-date-block label {
    display: block;
    font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--faint); margin-bottom: 4px;
}
.portal-date-row { display: flex; align-items: center; gap: 10px; }
.portal-date-row input {
    padding: 8px; font-family: inherit; font-size: .95rem;
    border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--text);
}

/* The order summary as an accordion. The head carries the card's padding and bleeds back out to the
   card's edges, so it reads as a full-width band the way the order lists' heads do, while the lines and
   the date block keep the card's inner margin. */
.portal-summary { padding: 0 16px 16px; }

.portal-summary-head {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    margin: 0 -16px;
    padding: 16px;
    cursor: pointer;
    list-style: none;
}
.portal-summary-head::-webkit-details-marker { display: none; }
.portal-summary-head .portal-card-title { margin: 0; }

/* Count and total, inside the open panel. */
.portal-summary-foot {
    display: flex; align-items: baseline; justify-content: space-between;
    margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
}

/* No bottom padding when there is nothing below the head to separate from. */
.portal-summary:not([open]) { padding-bottom: 0; }

/* A caret of its own, matching the order lists, since the native marker is hidden. */
.portal-summary-head::after {
    content: '▾';
    color: var(--faint);
    transition: transform .15s;
}
.portal-summary[open] .portal-summary-head::after { transform: rotate(180deg); }

.portal-total { font-size: 1.35rem; font-weight: 700; }

.portal-errors {
    margin-top: 12px; padding: 10px 12px;
    background: #FDF1F1; border: 1px solid #E6C3C3; border-radius: 8px;
    color: #96201F; font-size: .9rem;
}

.portal-confirm-lines { margin: 10px 0; }
.portal-confirm-foot { font-weight: 500; }

/* The floating dock: the action bar, plus the expandable order panel above it. Pinned to the foot of
   the viewport so Place order and the summary are reachable however far down the list the customer has
   read. Held to the same 720px column as the masthead - on a FIXED element, left/right pinned to 0 with
   auto side margins centres the box. (The same declaration on a flex item cancels the cross-axis stretch
   instead, which once shrank the bar to a floating tab - so the positioning lives on the dock, and the
   bar inside it is a plain row.) */
.portal-dock {
    position: fixed; bottom: 0; left: 0; right: 0;
    max-width: 720px;
    margin: 0 auto;
    z-index: 40;
    display: flex; flex-direction: column;
}
.portal-dock[hidden] { display: none; }

/* The panel that expands above the bar, carrying the lines and the delivery date. Capped so it never
   swallows the whole page, and it scrolls its own overflow - a long order lengthens the scroll here, not
   the page behind it. Rounded top and a lifted shadow so it reads as floating above the goods. */
.portal-dock-panel {
    max-height: 45vh;
    overflow-y: auto;
    background: var(--card);
    border: 1px solid var(--border);
    border-bottom: none;
    border-radius: 12px 12px 0 0;
    box-shadow: 0 -6px 18px rgba(0, 0, 0, .14);
    padding: 16px;
}
.portal-dock-panel[hidden] { display: none; }
.portal-dock-panel-title { margin: 0 0 10px; }

/* Burgundy action bar, always visible at the foot of the dock - the collapsed summary. */
.portal-sticky {
    background: var(--brand);
    color: #fff;
    border-top: 1px solid var(--brand-dark);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, .12);
    padding: 12px 20px;
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
}

/* A rounded top when the bar is the topmost thing showing (panel collapsed); when the panel is open it
   owns the rounding and the bar sits flush beneath it. */
.portal-dock-panel[hidden] + .portal-sticky { border-radius: 12px 12px 0 0; }

/* The whole dock is hidden until a quantity is keyed; this stays as a belt-and-braces guard in case the
   bar alone is ever toggled. The script also blanks the figures, so nothing stale is left behind. */
.portal-sticky[hidden] { display: none; }

/* The bar's figures double as the toggle for the panel, so this is a <button>. Stripped back to look
   like the plain stacked count/total it replaced - the button chrome, and its centred text, would read
   as a second action competing with Place order. */
.portal-sticky-left {
    display: flex; flex-direction: row; align-items: center; gap: 10px;
    background: none; border: 0; padding: 0; margin: 0;
    color: inherit; font: inherit; text-align: left; cursor: pointer;
}

/* The count over the total, beside the caret. */
.portal-sticky-figures { display: flex; flex-direction: column; line-height: 1.2; }

/* The disclosure caret. Points up while collapsed (the panel opens upward); flips to down when the bar
   is expanded, driven off aria-expanded so it stays in step with the panel without extra script. */
.portal-sticky-caret { font-size: .9rem; opacity: .85; transition: transform .15s; }
#PortalSummaryToggle[aria-expanded="true"] .portal-sticky-caret { transform: rotate(180deg); }

/* A tint of the white the bar carries, not var(--muted) - that is a brown mixed for the page background
   and on burgundy it reads as dirt rather than as a quieter label. */
#PortalStickyCount { color: rgba(255, 255, 255, .78); font-size: .8rem; }

/* Reversed out of the bar: white with burgundy text, so the action is the lightest thing on the darkest
   band and cannot be mistaken for part of the background. */
.portal-sticky .portal-btn {
    background: #fff;
    color: var(--brand);
}

.portal-sticky .portal-btn:hover:not(:disabled) { background: #F2E9E4; }

.portal-btn {
    background: var(--brand); color: #fff;
    border: none; border-radius: 8px;
    padding: 12px 22px;
    font-family: inherit; font-size: 1rem; font-weight: 700;
    cursor: pointer;
}
.portal-btn:hover:not(:disabled) { background: var(--brand-dark); }
.portal-btn:disabled { opacity: .6; cursor: default; }

.portal-link-btn {
    background: none; border: none; cursor: pointer;
    color: var(--brand); font-family: inherit; font-size: .88rem;
    text-decoration: underline; padding: 0;
}
.portal-link-btn:disabled { opacity: .6; cursor: default; text-decoration: none; }

/* Cancelling is irreversible, so it reads as the graver of the two actions - but still a link rather
   than a button, because it is not the thing the card is for. */
.portal-link-danger { color: #96201F; }

/* Two actions in the form head now: leaving amend mode, and clearing the draft. */
.portal-form-head-actions { display: flex; align-items: baseline; gap: 14px; }

/* Change / Cancel, on each order that is still the customer's to alter. On the order itself rather than a
   single promoted card, so somebody with two orders awaiting confirmation can act on either. */
.portal-order-actions {
    display: flex; align-items: center; gap: 16px;
    margin-top: 10px; padding-top: 10px;
    border-top: 1px dashed var(--border);
}

/* Secondary next to the sticky bar's primary: the same shape, outlined, so "Change this order" does not
   compete with "Place order" for the eye. */
.portal-btn-quiet {
    background: none;
    color: var(--brand);
    border: 1px solid var(--brand);
    padding: 10px 18px;
    font-size: .95rem;
}
.portal-btn-quiet:hover:not(:disabled) { background: var(--pending-bg); }

/* The desktop rule that used to live here - max-width 720px, auto margins and a rounded lip - is gone
   with the overlay it was written for. On a flex item "margin: 0 auto" does not merely centre: setting a
   side margin to auto cancels the cross-axis stretch, so the bar shrank to fit its button and sat in the
   middle of the screen as a rounded tab. The shell already holds the column to 720px, and a square band
   matches the masthead. */

/* Your orders / Past orders. Native <details> rather than scripted panels: it collapses without JS, keeps
   keyboard and screen-reader behaviour for free, and the portal has no widget library to reach for. */
.portal-orders { padding: 0; }

.portal-orders-head {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 16px;
    cursor: pointer;
    list-style: none;
}
.portal-orders-head::-webkit-details-marker { display: none; }
.portal-orders-head .portal-card-title { margin: 0; }

/* A caret of its own, since the native marker is hidden. */
.portal-orders-head::after {
    content: '▾';
    color: var(--faint);
    transition: transform .15s;
}
.portal-orders[open] .portal-orders-head::after { transform: rotate(180deg); }

.portal-chip {
    background: var(--brand);
    color: #fff;
    border-radius: 999px;
    padding: 2px 10px;
    font-size: .74rem;
    font-weight: 700;
    margin-left: auto;
    margin-right: 8px;
}
/* History is a count, not news. */
.portal-chip-quiet {
    background: transparent;
    color: var(--muted);
    border: 1px solid var(--border);
    font-weight: 500;
}

.portal-order {
    padding: 14px 16px;
    border-top: 1px solid var(--border);
}

.portal-order-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
}
.portal-order-ref { font-weight: 700; }

.portal-order-lines { margin-top: 8px; }
.portal-order-line {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    padding: 3px 0;
    font-size: .92rem;
}

.portal-order-foot {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--border);
    font-size: .86rem;
}
.portal-order-requested { color: var(--pending-text); font-weight: 500; }

/* One palette across the page, per the spec's status table. */
.portal-status {
    border-radius: 999px;
    padding: 3px 10px;
    font-size: .74rem;
    font-weight: 700;
    white-space: nowrap;
    border: 1px solid;
}
.portal-status-pending    { background: var(--pending-bg); color: var(--pending-text); border-color: var(--pending-border); }
.portal-status-confirmed  { background: var(--good-bg);    color: var(--good-text);    border-color: var(--good-border); }
.portal-status-production { background: #E2ECF3;           color: #2C5578;             border-color: #9DBBD2; }
/* Done with: quiet, so it does not compete with what is still coming. */
.portal-status-invoiced   { background: transparent;       color: var(--muted);        border-color: var(--border); }

/* ---------------------------------------------------------------- profile */

.portal-account-button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: none;
    /* font-family, not the font shorthand: the shorthand also resets font-size, which threw away the
       .8rem the chip sets above and rendered the label at masthead size.
       And colour is stated because a button takes its own rather than the masthead's, which is what
       left the label browser-dark on the burgundy band. */
    font-family: inherit;
    font-weight: 500;
    color: inherit;
    cursor: pointer;
}

.portal-dialog {
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--card);
    color: var(--text);
    padding: 0;
    max-width: 460px;
    width: calc(100% - 32px);
}

.portal-dialog::backdrop { background: rgba(0, 0, 0, .45); }

.portal-dialog-form { padding: 20px; }

.portal-dialog-title {
    margin: 0 0 14px;
    font-size: 1.1rem;
    color: var(--brand);
}

.portal-field { display: block; margin-bottom: 14px; border: 0; padding: 0; }

.portal-field-label {
    display: block;
    font-size: .82rem;
    font-weight: 600;
    margin-bottom: 4px;
}

.portal-field input {
    width: 100%;
    padding: 8px 10px;
    margin-bottom: 6px;
    border: 1px solid var(--border);
    border-radius: 6px;
    font: inherit;
    background: #fff;
}

.portal-field input[readonly] { background: var(--page); color: var(--muted); }

.portal-day-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }

.portal-day-chip {
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: #fff;
    font: inherit;
    cursor: pointer;
}

.portal-day-chip.is-on {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
}

/* Read-only: the office sets a customer's delivery days, so the portal shows them as static chips. */
.portal-day-chip.is-readonly {
    cursor: default;
}

.portal-dialog-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 12px;
    margin-top: 18px;
}

/* Cancelled reads as neutral-with-a-line-through-it rather than as an error: it is a fact about the
   order, not something wrong the customer must act on. */
.portal-status-cancelled { background: transparent; color: var(--muted); border-color: var(--border); }

.portal-order-cancelled-note { color: var(--muted); font-style: italic; }

.portal-order-actions-past {
    display: flex;
    justify-content: flex-end;
    margin-top: 8px;
}

/* ---------------------------------------------------------------- confirm popup */

/* Confirm-before-submit popup. "Place order" opens this to review the order; it is sent only on confirm. */
.portal-modal-overlay {
    position: fixed; inset: 0;
    background: rgba(35, 32, 26, .55);
    display: flex; align-items: center; justify-content: center;
    padding: 16px; z-index: 1000;
}
.portal-modal-overlay[hidden] { display: none; }

.portal-modal {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 12px;
    width: 100%; max-width: 460px;
    max-height: 90vh; overflow-y: auto;
    box-shadow: 0 10px 40px rgba(0, 0, 0, .25);
    padding: 20px;
}
.portal-modal-head .portal-card-title { margin-bottom: 0; }
.portal-modal-body { margin-top: 14px; }

.portal-confirm-line {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 0; border-bottom: 1px dashed var(--border);
}
.portal-confirm-line-name { flex: 1; min-width: 0; }
.portal-confirm-line-qty { color: var(--muted); font-size: .86rem; white-space: nowrap; }
.portal-confirm-line-total { white-space: nowrap; font-weight: 600; }

.portal-confirm-meta {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 8px; margin-top: 12px;
}

.portal-modal-foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-top: 18px;
}
