/*
 * External portal (customer + assessor) styling. Reuses the workshop design tokens defined in
 * app.css (--bs-ink, --bs-hi-vis, fonts) but a distinct, calm, single-column layout — these pages
 * are seen by customers and insurers, not operators, so they carry no dense operational chrome.
 */

.pt {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bs-ink);
    color: #e9ecf1;
    font-family: var(--bs-font-ui);
}

.pt-wrap {
    width: 100%;
    max-width: 640px;
    margin-inline: auto;
    padding-inline: 1.25rem;
}

.pt-header {
    border-block-end: 3px solid var(--bs-hi-vis);
    padding-block: 1rem;
}

.pt-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.pt-brand {
    font-family: var(--bs-font-display);
    font-size: 1.6rem;
    letter-spacing: 0.04em;
    color: #fff;
}

.pt-main {
    flex: 1;
    padding-block: 2.5rem 3rem;
}

.pt-card {
    background: var(--bs-paper);
    color: var(--bs-ink);
    border-radius: 14px;
    padding: 2rem 1.75rem;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
}

.pt-eyebrow {
    font-family: var(--bs-font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #6b7280;
    margin: 0 0 0.5rem;
}

.pt-status__reg {
    font-family: var(--bs-font-display);
    font-size: 2.6rem;
    letter-spacing: 0.05em;
    margin: 0;
    line-height: 1;
}

.pt-status__vehicle {
    color: #4b5563;
    margin: 0.35rem 0 1.25rem;
}

.pt-status__headline {
    font-weight: 600;
    font-size: 1.05rem;
    margin: 0 0 1.5rem;
    padding: 0.85rem 1rem;
    border-radius: 10px;
    background: rgba(0, 222, 145, 0.10);
    border-inline-start: 4px solid var(--bs-hi-vis);
}

.pt-status__headline--ready {
    background: rgba(0, 222, 145, 0.18);
}

.pt-status__headline--muted {
    background: #f3f4f6;
    border-inline-start-color: #9ca3af;
}

/* Vertical progress tracker. */
.pt-track {
    list-style: none;
    margin: 0 0 1.5rem;
    padding: 0;
}

.pt-track__step {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding-block: 0.55rem;
    position: relative;
}

.pt-track__step:not(:last-child)::before {
    content: '';
    position: absolute;
    inset-inline-start: 8px;
    inset-block-start: 1.6rem;
    block-size: calc(100% - 0.5rem);
    inline-size: 2px;
    background: #d1d5db;
}

.pt-track__dot {
    inline-size: 18px;
    block-size: 18px;
    border-radius: 50%;
    background: #d1d5db;
    flex: 0 0 auto;
    z-index: 1;
}

.pt-track__label {
    font-weight: 500;
    color: #6b7280;
}

.pt-track__step--done .pt-track__dot { background: var(--bs-hi-vis); }
.pt-track__step--done .pt-track__label { color: var(--bs-ink); }

.pt-track__step--current .pt-track__dot {
    background: var(--bs-ink);
    box-shadow: 0 0 0 4px rgba(0, 222, 145, 0.30);
}
.pt-track__step--current .pt-track__label {
    color: var(--bs-ink);
    font-weight: 700;
}

.pt-status__note {
    color: #6b7280;
    font-size: 0.9rem;
    margin: 0;
}

/* "Before you collect" balance notice (RSPH-166, Completion add-on only). Amber, matching the
   workshop side's own due/outstanding colour (kpi-stat__n--amber, badge-flag--amber) — a heads-up to
   act on, not an error. */
.pt-collect {
    margin: 0 0 1.5rem;
    padding: 0.9rem 1rem;
    border-radius: 10px;
    background: #fff4e0;
    border-inline-start: 4px solid #e8a400;
}

.pt-collect__title {
    font-weight: 700;
    margin: 0 0 0.6rem;
    color: #6b4a00;
}

.pt-collect__list {
    list-style: none;
    margin: 0 0 0.6rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.pt-collect__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
}

.pt-collect__label {
    color: #6b4a00;
}

.pt-collect__amount {
    font-family: var(--bs-font-mono);
    font-weight: 700;
    color: #6b4a00;
}

.pt-collect__note {
    margin: 0;
    font-size: 0.85rem;
    color: #8a6a1f;
}

/* A credit row (an overpaid bill or excess) sits inside the same amber panel — something else on the
   other ledger is still genuinely outstanding, which is why the panel is showing at all — but reads
   as good news, not another demand: green, matching the workshop side's own kpi-stat__n--green /
   badge-flag--green "good" colour. Its own list + note (fix round 2) are deliberately separated from
   the demand rows above by a hairline, so the "please settle the amounts above" note can never be
   read as applying to a credit below it — the two ledgers don't net, and a customer who read them as
   one sum and under-paid the excess would leave that stage stuck Current, blocking release. */
.pt-collect__list--credit {
    margin-block-start: 0.6rem;
    padding-block-start: 0.6rem;
    border-block-start: 1px dashed rgba(0, 0, 0, 0.12);
}
.pt-collect__row--credit .pt-collect__label { color: #146c37; }
.pt-collect__amount--credit { color: #1a7f3c; }
/* The credit note takes the credit rows' green, not the panel's amber. Inheriting .pt-collect__note
   made "there's nothing you need to do now" visually identical to "Please settle the amounts above"
   two lines up — the exact opposite instruction in the exact same colour, on the one screen where a
   customer decides whether they owe money before collecting. */
.pt-collect__note--credit { margin-block-start: 0.4rem; color: #1a7f3c; }

.pt-footer {
    padding-block: 1.25rem;
    color: #7e879a;
    font-size: 0.8rem;
    font-family: var(--bs-font-mono);
}

/* Assessor login + forms */
.pt-link {
    color: var(--bs-hi-vis);
    text-decoration: none;
    font-family: var(--bs-font-mono);
    font-size: 0.8rem;
    letter-spacing: 0.06em;
}
.pt-link:hover { text-decoration: underline; }

.pt-auth__title {
    font-family: var(--bs-font-display);
    font-size: 2.2rem;
    letter-spacing: 0.04em;
    margin: 0 0 0.35rem;
}

.pt-auth__lead {
    color: #4b5563;
    margin: 0 0 1.5rem;
}

.pt-auth__error {
    background: #fdecec;
    border-inline-start: 4px solid #d64545;
    color: #8a1f1f;
    padding: 0.75rem 1rem;
    border-radius: 8px;
    margin-bottom: 1.25rem;
}

.pt-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-bottom: 1rem;
}

.pt-field label {
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--bs-ink);
}

.pt-field input,
.pt-field textarea {
    width: 100%;
    padding: 0.65rem 0.8rem;
    border: 1px solid #cbd2dc;
    border-radius: 8px;
    font: inherit;
}

.pt-field input:focus,
.pt-field textarea:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 3px rgba(0, 222, 145, 0.25);
}

.pt-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.7rem 1.4rem;
    border: none;
    border-radius: 8px;
    background: var(--bs-hi-vis);
    color: var(--bs-ink-2);
    font-family: var(--bs-font-ui);
    font-weight: 700;
    cursor: pointer;
}
.pt-btn:hover { background: var(--bs-hi-vis-press); }

.pt-btn--ghost {
    background: transparent;
    border: 1px solid #cbd2dc;
    color: var(--bs-ink);
}

/* Estimate list */
.pt-list { list-style: none; margin: 1rem 0 0; padding: 0; }
.pt-list__item { border-top: 1px solid #e5e7eb; }
.pt-list__link {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.85rem 0.25rem;
    text-decoration: none;
    color: var(--bs-ink);
}
.pt-list__link:hover { background: #f7faf9; }
.pt-list__reg { font-family: var(--bs-font-display); font-size: 1.4rem; letter-spacing: 0.04em; }
.pt-list__meta { color: #6b7280; font-size: 0.85rem; }

/* Estimate detail table */
.pt-table { width: 100%; border-collapse: collapse; margin: 1.25rem 0; font-size: 0.9rem; }
.pt-table th, .pt-table td { padding: 0.5rem 0.6rem; border-bottom: 1px solid #e5e7eb; text-align: start; }
.pt-table thead th { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: #6b7280; }
.pt-table tfoot th, .pt-table tfoot td { font-weight: 700; border-top: 2px solid #cbd2dc; }
.pt-num { text-align: end; font-family: var(--bs-font-mono); }

/* Decision form */
.pt-decision { margin-top: 1.5rem; border-top: 1px solid #e5e7eb; padding-top: 1.25rem; }
.pt-decision textarea {
    padding: 0.6rem 0.8rem;
    border: 1px solid #cbd2dc;
    border-radius: 8px;
    font: inherit;
    resize: vertical;
}
.pt-decision textarea:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 3px rgba(0, 222, 145, 0.25);
}
.pt-hint { color: #6b7280; font-size: 0.8rem; }
.pt-decision__actions { display: flex; gap: 0.75rem; margin-top: 1rem; }

/* Horizontal scroll guard for the table on narrow screens */
@media (max-width: 480px) {
    .pt-table { display: block; overflow-x: auto; white-space: nowrap; }
}

.pt-eyebrow--spaced { margin-top: 1.75rem; }
.pt-track--compact .pt-track__step { padding-block: 0.35rem; }
.pt-track--compact .pt-track__step:not(:last-child)::before { inset-block-start: 1.2rem; }

.pt-docs { list-style: none; margin: 0.75rem 0 0; padding: 0; }
.pt-docs__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.5rem 0.25rem;
    border-top: 1px solid #e5e7eb;
}
.pt-docs__cat {
    font-family: var(--bs-font-mono);
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #6b7280;
}

/* Message thread */
.pt-thread { list-style: none; margin: 0.75rem 0 1rem; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.pt-thread__msg { padding: 0.65rem 0.85rem; border-radius: 10px; background: #f3f4f6; max-width: 85%; }
.pt-thread__msg--assessor { align-self: flex-end; background: rgba(0, 222, 145, 0.12); }
.pt-thread__meta { margin: 0 0 0.25rem; font-size: 0.72rem; color: #6b7280; }
.pt-thread__body { margin: 0; }
.pt-msgform { margin-bottom: 1.5rem; }

/* Staff-side thread panel (rendered inside the app shell on the job screen) */
.portal-thread { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.portal-thread__msg { padding: 0.6rem 0.8rem; border-radius: 8px; background: rgba(0,0,0,0.03); }
.portal-thread__msg--assessor { border-inline-start: 3px solid var(--bs-hi-vis); }
.portal-thread__meta { margin: 0 0 0.25rem; font-size: 0.75rem; color: #6b7280; }
.portal-thread__body { margin: 0; white-space: pre-wrap; }
.portal-reply textarea { width: 100%; padding: 0.5rem 0.7rem; border: 1px solid #cbd2dc; border-radius: 6px; font: inherit; }

/* ---- Customer satisfaction survey (RSPH-148) ----
   The one screen on the portal that asks the customer for something rather than telling them
   something, so it stays in the tracking page's calm card and spends its only emphasis on the score
   control itself.

   The control is a native radio group. Not stars, not emoji, not a slider: a radio row is the only
   option that keyboards and screen readers already understand, needs no JavaScript in whatever
   client the email was opened in, and scales unchanged from the 1-5 satisfaction questions to the
   0-10 recommendation without becoming a second component. */

.pt-survey__lead {
    color: #4b5563;
    margin: 0 0 1.75rem;
}

.pt-survey__group {
    font-family: var(--bs-font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #6b7280;
    margin: 1.75rem 0 0.75rem;
    padding-block-end: 0.5rem;
    border-block-end: 1px solid #e5e7eb;
}

.pt-survey__group:first-of-type { margin-block-start: 0; }

/* Fieldsets carry a browser default border and padding that would box every question. */
.pt-survey__q {
    border: none;
    margin: 0 0 1.5rem;
    padding: 0;
    min-inline-size: 0;
}

.pt-survey__q-text {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--bs-ink);
    padding: 0;
    margin-block-end: 0.55rem;
}

.pt-scale__options {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 0.4rem;
}

/* The recommendation question is 0-10 — eleven options. They wrap to two rows on a phone rather
   than shrinking to unreadable, un-tappable slivers. */
.pt-scale--wide .pt-scale__options {
    grid-template-columns: repeat(11, 1fr);
    gap: 0.25rem;
}

.pt-scale__opt { display: block; cursor: pointer; }

/* The radio itself is hidden from sight but NOT from the accessibility tree or the keyboard:
   opacity + absolute keeps it focusable and announced, which display:none would not. */
.pt-scale__opt input {
    position: absolute;
    opacity: 0;
    inline-size: 1px;
    block-size: 1px;
}

.pt-scale__num {
    display: flex;
    align-items: center;
    justify-content: center;
    min-block-size: 2.75rem;
    border: 1px solid #cbd2dc;
    border-radius: 8px;
    font-family: var(--bs-font-mono);
    font-size: 0.95rem;
    color: #4b5563;
    background: #fff;
    transition: background-color 120ms ease, border-color 120ms ease;
}

.pt-scale--wide .pt-scale__num {
    min-block-size: 2.4rem;
    font-size: 0.8rem;
}

.pt-scale__opt:hover .pt-scale__num { border-color: var(--bs-hi-vis); }

.pt-scale__opt input:checked + .pt-scale__num {
    background: var(--bs-hi-vis);
    border-color: var(--bs-hi-vis);
    color: var(--bs-ink-2);
    font-weight: 700;
}

/* Focus lands on the visually hidden input, so the ring has to be drawn on its label sibling —
   without this the keyboard user has no idea where they are. */
.pt-scale__opt input:focus-visible + .pt-scale__num {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 3px rgba(0, 222, 145, 0.25);
}

.pt-scale__ends {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin: 0.35rem 0 0;
    font-size: 0.78rem;
    color: #6b7280;
}

.pt-survey__comment { margin-block-start: 1.75rem; }

@media (prefers-reduced-motion: reduce) {
    .pt-scale__num { transition: none; }
}

/* Below roughly a small phone, eleven columns stop being tappable at any font size. */
@media (max-width: 400px) {
    .pt-scale--wide .pt-scale__options { grid-template-columns: repeat(6, 1fr); }
}

/* ---- Dark mode (RSPH-28) ----
   The portal page background is already dark; the light "paper" card is what needs re-theming when a
   staff member who chose dark mode lands here. Flip the card surface and the text that used the dark
   ink token, and darken the light neutral fills/borders. Brand + status colours are left untouched. */
[data-bs-theme="dark"] .pt-card { background: #1c1f24; color: #e6e9ee; }
[data-bs-theme="dark"] .pt-track__step--done .pt-track__label,
[data-bs-theme="dark"] .pt-track__step--current .pt-track__label,
[data-bs-theme="dark"] .pt-list__link,
[data-bs-theme="dark"] .pt-field label { color: #e6e9ee; }
/* Muted greys hardcoded for the light card (eyebrow, upcoming timeline steps, the contact note)
   sit at ~3.4:1 on the dark card and the vehicle line at ~1.9:1 — below the AA floor. Lift them to a
   readable slate. The vehicle make/model is job identity, so it reads brighter than the quiet text. */
[data-bs-theme="dark"] .pt-eyebrow,
[data-bs-theme="dark"] .pt-track__step--upcoming .pt-track__label,
[data-bs-theme="dark"] .pt-status__note { color: #98a2b3; }
[data-bs-theme="dark"] .pt-status__vehicle { color: #c7cdd6; }
[data-bs-theme="dark"] .pt-btn--ghost { color: #e6e9ee; border-color: #333a43; }
[data-bs-theme="dark"] .pt-field input,
[data-bs-theme="dark"] .pt-field textarea,
[data-bs-theme="dark"] .pt-decision textarea,
[data-bs-theme="dark"] .portal-reply textarea { background: #23272e; color: #e6e9ee; border-color: #333a43; }
[data-bs-theme="dark"] .pt-status__headline--muted,
[data-bs-theme="dark"] .pt-thread__msg { background: #23272e; }
[data-bs-theme="dark"] .pt-collect {
    background: rgba(255, 184, 28, 0.14);
    border-inline-start-color: #ffcf4d;
}
[data-bs-theme="dark"] .pt-collect__title,
[data-bs-theme="dark"] .pt-collect__label,
[data-bs-theme="dark"] .pt-collect__amount { color: #ffcf4d; }
[data-bs-theme="dark"] .pt-collect__note { color: #d9b877; }
/* MUST stay declared after the generic amber ".pt-collect__amount" dark-mode rule above: the amount
   half of this selector (".pt-collect__amount--credit") ties it on specificity (0,2,0 vs 0,2,0), so
   it wins on source order, not specificity — reordering the two rules would silently turn the credit
   row amber. */
[data-bs-theme="dark"] .pt-collect__row--credit .pt-collect__label,
[data-bs-theme="dark"] .pt-collect__amount--credit { color: var(--bs-hi-vis); }
/* Same reason as the light-mode rule above, and it MUST also stay after the amber
   ".pt-collect__note" rule — it ties it on specificity (0,2,0) and wins on source order alone. */
[data-bs-theme="dark"] .pt-collect__note--credit { color: var(--bs-hi-vis); }
/* The hairline separating the credit rows from the demand rows above them is a black alpha, which is
   invisible against the dark panel — the one thing keeping "you owe this" and "we owe you" from
   reading as a single list of figures. */
[data-bs-theme="dark"] .pt-collect__list--credit { border-block-start-color: rgba(255, 255, 255, 0.22); }
[data-bs-theme="dark"] .pt-list__item,
[data-bs-theme="dark"] .pt-table th,
[data-bs-theme="dark"] .pt-table td,
[data-bs-theme="dark"] .pt-decision,
[data-bs-theme="dark"] .pt-docs__item { border-color: #333a43; }
[data-bs-theme="dark"] .pt-table tfoot th,
[data-bs-theme="dark"] .pt-table tfoot td { border-top-color: #333a43; }
[data-bs-theme="dark"] .pt-list__link:hover { background: #23272e; }
[data-bs-theme="dark"] .pt-track__dot,
[data-bs-theme="dark"] .pt-track__step:not(:last-child)::before { background: #333a43; }

/* Survey (RSPH-148): the score buttons are a white fill on a light card, which is the one part of
   this screen that would stay bright on the dark card. The checked state keeps the hi-vis fill and
   the dark ink numeral it already has — that pair reads at full contrast in both themes. */
[data-bs-theme="dark"] .pt-survey__lead { color: #c7cdd6; }
[data-bs-theme="dark"] .pt-survey__group,
[data-bs-theme="dark"] .pt-scale__ends { color: #98a2b3; }
[data-bs-theme="dark"] .pt-survey__group { border-block-end-color: #333a43; }
[data-bs-theme="dark"] .pt-survey__q-text { color: #e6e9ee; }
[data-bs-theme="dark"] .pt-scale__num {
    background: #23272e;
    border-color: #333a43;
    color: #c7cdd6;
}
