/* ===========================================================================
   Customer portal

   Separate from app.css on purpose. The hub is a dense, data-led tool used all
   day by people who know it; this is used occasionally, by someone who does not
   work here, often when something is already going wrong. It gets bigger type,
   more room, fewer things on screen, and one obvious action per thing they came
   to do.

   The token NAMES match the ones the portal already used (--ink, --card,
   --accent) so the twenty-odd pages that reference them keep working, and the
   VALUES line up with app.css so the two do not drift into different blues.

   Light by default. The old stylesheet followed the device, which meant a
   customer on a dark-mode laptop got a near-black support portal — fine for
   staff software, not the first impression a customer-facing product wants.
   Dark is still one click away and still remembered.
   =========================================================================== */

:root {
    /* Native widgets follow the theme: select menus, date pickers and their
       scrollbars. Without it a dark page opens a white date picker. */
    color-scheme: light;

    --bg:        #f4f6fa;
    --card:      #ffffff;
    --card-2:    #f8fafc;
    --ink:       #0f172a;
    --ink-2:     #475569;
    --ink-3:     #7c8ba1;
    --border:    #e4e9f0;
    --border-2:  #cfd8e3;

    --accent:        #1d4ed8;
    --accent-hover:  #1e40af;
    --accent-soft:   #eaf0ff;
    --link:          #1d4ed8;

    --error:   #b91c1c;  --error-bg:   #fee2e2;
    --success: #15803d;  --success-bg: #dcfce7;
    --warn:    #b45309;  --warn-bg:    #fef3c7;
    --info-fg: #1d4ed8;  --info-bg:    #e6efff;

    --hover-bg:  #f5f7fb;
    --field-bg:  #ffffff;
    --result-bg: #ffffff;

    --radius:    10px;
    --radius-lg: 16px;
    --shadow:    0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.06);
    --shadow-lg: 0 4px 6px -1px rgba(15, 23, 42, 0.07), 0 2px 4px -2px rgba(15, 23, 42, 0.05);
}
/* Dark: neutral surfaces, not navy.

   These were a blue ramp (#0b1220 upward), which at this luminance reads as
   purple rather than as grey. Same neutral ramp app.css now uses, and the same
   steps between the surfaces as before, so only the hue has moved. The blues
   that remain are the ones meant to be blue: the accent and the links. */
html[data-theme="dark"] {
    color-scheme: dark;

    --bg:        #111114;
    --card:      #1c1c20;
    --card-2:    #17171a;
    --ink:       #dcdce1;
    --ink-2:     #a3a3ac;
    --ink-3:     #8a8a94;
    --border:    #2c2c33;
    --border-2:  #42424b;

    --accent:        #2f6fed;
    --accent-hover:  #5a94f7;
    --accent-soft:   #1b2231;
    --link:          #7ab3ff;

    /* Left alone. Red, green and amber are supposed to carry colour, and
       these have no blue in them to take out. */
    --error:   #fca5a5;  --error-bg:   #341717;
    --success: #86efac;  --success-bg: #14301c;
    --warn:    #fcd34d;  --warn-bg:    #362003;
    --info-fg: #7ab3ff;  --info-bg:    #1b2231;

    --hover-bg:  #26262b;
    --field-bg:  #17171a;
    --result-bg: #1c1c20;

    --shadow:    0 1px 2px rgba(0,0,0,0.5);
    --shadow-lg: 0 6px 16px rgba(0,0,0,0.55);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font: 16px/1.6 "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------- shell */

/* Wider than it was. 880px was holding a request list, a four-tile grid and a
   long form to less than half of most screens, which is what made it feel
   squashed. */
.portal-shell { max-width: 1240px; margin: 0 auto; padding: 0 28px 64px; }

/* FULL BLEED. The bar spans the window; only .portal-header-inner is held to
   the shell width. It used to live inside .portal-shell, so the bar itself
   stopped at the content width and floated in the middle of the page with
   background showing either side. */
.portal-header {
    position: sticky; top: 0; z-index: 20;
    background: var(--card);
    border-bottom: 1px solid var(--border);
    margin-bottom: 34px;
}
.portal-header-inner {
    max-width: 1240px; margin: 0 auto; padding: 12px 28px;
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.portal-brand {
    display: flex; align-items: center; gap: 13px;
    font-size: 18px; font-weight: 700; letter-spacing: -0.015em;
    color: var(--ink); text-decoration: none;
}
/* No plate, and sized by HEIGHT not a square.
   
   I put a white background behind this on the assumption that a dark mark
   needs something to sit on in dark mode. The artwork is nothing of the sort:
   it is white lettering with a heavy black outline on transparency, drawn to
   read on either background — the outline carries it on light, the white fill
   carries it on dark. The plate was solving a problem that did not exist and
   produced a white box in dark mode.
   
   And it is 301x220, so forcing it into a 42px SQUARE letterboxed it to 42x30
   and threw away a third of the width it was drawn at. Fixing the height and
   letting the width follow gives it its real proportions. */
.portal-brand img.logo { height: 38px; width: auto; display: block; }
.portal-brand-sub {
    font-weight: 500; font-size: 14px; color: var(--ink-3);
    padding-left: 11px; margin-left: 2px; border-left: 1px solid var(--border);
}

.portal-user { display: flex; align-items: center; gap: 12px; font-size: 13px; }
.pu-info { text-align: right; line-height: 1.35; }
.pu-name { font-weight: 600; color: var(--ink); }
.pu-company { color: var(--ink-3); font-size: 12px; }
.pu-logout { color: var(--ink-2); text-decoration: none; font-size: 12.5px; }
.pu-logout:hover { color: var(--ink); text-decoration: underline; }
.pu-theme {
    width: 34px; height: 34px; padding: 0; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: 50%;
    background: transparent; color: var(--ink-2); cursor: pointer; font-size: 14px;
}
.pu-theme:hover { background: var(--hover-bg); color: var(--ink); }

.portal-back {
    display: inline-block; margin-bottom: 16px;
    font-size: 14px; color: var(--ink-2); text-decoration: none;
}
.portal-back:hover { color: var(--ink); text-decoration: underline; }
.portal-link { color: var(--link); text-decoration: none; }
.portal-link:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- type */

h1 { font-size: 27px; line-height: 1.25; letter-spacing: -0.02em; margin: 0 0 8px; font-weight: 700; }
h2 { font-size: 18px; line-height: 1.35; margin: 0 0 14px; font-weight: 650; }
h3 {
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--ink-3); margin: 26px 0 12px;
}
p { margin: 0 0 14px; }
p:last-child { margin-bottom: 0; }
.eyebrow {
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--ink-3); margin-bottom: 6px;
}
.meta, .help { font-size: 13px; color: var(--ink-3); }
.help { margin-top: 5px; }
.lede { font-size: 17px; color: var(--ink-2); margin-bottom: 30px; max-width: 60ch; }

/* The greeting block needs air above it now the header is flush to the page. */
.portal-shell > h1:first-of-type { margin-top: 4px; }

/* ---------------------------------------------------------------- cards */

.card {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow);
    padding: 24px 26px; margin-bottom: 18px;
}
.card > h1:first-child, .card > h2:first-child, .card > h3:first-child { margin-top: 0; }
@media (max-width: 560px) { .card { padding: 18px 16px; border-radius: var(--radius); } }

/* The big "what did you come here to do" tiles on the portal home. */
.action-grid {
    display: grid; gap: 18px; margin-bottom: 40px;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.action-card {
    position: relative; overflow: hidden;
    display: flex; flex-direction: column;
    padding: 26px 24px 22px; min-height: 178px;
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow);
    color: var(--ink); text-decoration: none;
    transition: border-color .14s ease, box-shadow .14s ease, transform .14s ease;
}
/* A line of brand colour along the top, revealed on hover. Gives the tile
   somewhere to go without moving anything the eye is reading. */
.action-card::before {
    content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
    background: var(--accent); transform: scaleX(0); transform-origin: left;
    transition: transform .18s ease;
}
.action-card:hover {
    border-color: var(--border-2); box-shadow: var(--shadow-lg);
    transform: translateY(-2px); text-decoration: none;
}
.action-card:hover::before { transform: scaleX(1); }
.action-card:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft), var(--shadow-lg); }

.action-card .ac-icon {
    width: 46px; height: 46px; margin-bottom: 16px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 13px; background: var(--accent-soft); color: var(--accent);
}
.action-card .ac-icon svg { width: 23px; height: 23px; }
/* Emoji need a line-height of their own or they sit low in the box, and a font
   stack that does not fall back to a monochrome glyph on Windows. */
.action-card .ac-glyph {
    font-size: 25px; line-height: 1;
    font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.action-card .ac-title { font-weight: 650; font-size: 17px; margin-bottom: 5px; letter-spacing: -0.01em; }
/* How many are waiting (Approvals): a count the eye finds first. */
.ac-count { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; padding: 0 7px; margin-left: 6px;
            border-radius: 999px; background: #dc2626; color: #fff; font-size: 12.5px; font-weight: 700; letter-spacing: 0; vertical-align: 2px; }
.action-card .ac-sub { font-size: 13.5px; color: var(--ink-3); line-height: 1.5; }
/* Pushed to the bottom so every tile's call to action lines up across the row,
   whatever length the description ran to. */
.action-card .ac-go {
    margin-top: auto; padding-top: 16px;
    font-size: 13px; font-weight: 600; color: var(--accent);
}

/* The one most people came for. Given weight so it is not one of four equals. */
.action-card-primary {
    background: linear-gradient(180deg, var(--accent-soft) 0%, var(--card) 62%);
    border-color: var(--accent);
}
.action-card-primary::before { transform: scaleX(1); }

/* "Show N older requests". */
.req-more { margin-top: 16px; }

/* ---------------------------------------------------------------- forms */

label { display: block; font-size: 13.5px; font-weight: 550; color: var(--ink-2); margin-bottom: 5px; }
.form-label { display: block; font-size: 13.5px; font-weight: 550; color: var(--ink-2); margin-bottom: 5px; }
.req { color: var(--error); font-weight: 700; }

input[type=text], input[type=email], input[type=password], input[type=date],
input[type=search], input[type=tel], input[type=number], input[type=url],
select, textarea, .input, .select, .textarea {
    width: 100%; padding: 11px 13px;
    border: 1px solid var(--border-2); border-radius: var(--radius);
    font: inherit; font-size: 15px; color: var(--ink); background: var(--field-bg);
    transition: border-color .12s ease, box-shadow .12s ease;
}
input:focus, select:focus, textarea:focus,
.input:focus, .select:focus, .textarea:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
input::placeholder, textarea::placeholder { color: var(--ink-3); }
textarea, .textarea { min-height: 110px; resize: vertical; line-height: 1.55; }
select, .select { appearance: none; background-image: none; }

.form-row, .form-group { margin-bottom: 18px; }
.form-grid, .form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 580px) { .form-grid, .form-grid-2 { grid-template-columns: 1fr; } }
.field-error { color: var(--error); font-size: 13px; margin-top: 5px; }

.radio-group label, .checkbox-group label {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 12px 14px; margin-bottom: 8px;
    border: 1px solid var(--border-2); border-radius: var(--radius);
    font-weight: 400; color: var(--ink); cursor: pointer;
    transition: border-color .12s ease, background .12s ease;
}
.radio-group label:hover, .checkbox-group label:hover {
    background: var(--hover-bg); border-color: var(--accent);
}
.radio-group input, .checkbox-group input { margin-top: 3px; accent-color: var(--accent); }

/* Read-only "here is what we hold" rows. */
.field-block { padding: 13px 0; border-bottom: 1px solid var(--border); }
.field-block:last-child { border-bottom: none; }
.field-block-label { font-size: 12.5px; color: var(--ink-3); margin-bottom: 2px; }
.field-block-value { font-size: 15px; color: var(--ink); }

/* The starter and leaver forms. Long, and filled in by someone who does it
   rarely, so the sections get real separation rather than running together as
   one wall of fields. */
/* Forms stay at a readable measure even though the shell is wider now. A
   single column of fields stretched across 1040px is a worse form, not a
   roomier one — the eye has to travel from a label on the left to a field
   ending on the far right. */
.portal-request-form,
.card > form:not(.portal-request-form):not([class*="grid"]) { max-width: 720px; }
.portal-request-form { display: block; }
.portal-request-form h3 {
    margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--border);
}
.portal-request-form h3:first-of-type { margin-top: 0; padding-top: 0; border-top: none; }
.portal-request-form > .btn,
.portal-request-form > button[type=submit] { margin-top: 24px; }

/* ---------------------------------------------------------------- buttons */

.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 11px 20px; border-radius: var(--radius);
    border: 1px solid var(--border-2); background: var(--card); color: var(--ink);
    font: inherit; font-size: 14.5px; font-weight: 550; cursor: pointer;
    text-decoration: none; transition: background .12s ease, border-color .12s ease;
}
.btn:hover { background: var(--hover-bg); border-color: var(--ink-3); text-decoration: none; }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.btn-primary {
    background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn[disabled], .btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-lg { padding: 14px 26px; font-size: 15.5px; }
.btn-block { width: 100%; }

/* ---------------------------------------------------------------- alerts */

.alert, .flash {
    padding: 14px 16px; border-radius: var(--radius); margin-bottom: 18px;
    font-size: 14.5px; border: 1px solid transparent; line-height: 1.55;
}
.alert-error,   .flash-error   { background: var(--error-bg);   color: var(--error);   border-color: var(--error); }
.alert-success, .flash-success { background: var(--success-bg); color: var(--success); border-color: var(--success); }
.alert-info,    .flash-info    { background: var(--info-bg);    color: var(--info-fg); border-color: var(--info-fg); }
.alert-warn,    .flash-warn    { background: var(--warn-bg);    color: var(--warn);    border-color: var(--warn); }

/* ---------------------------------------------------------------- requests */

.request-list { display: flex; flex-direction: column; }
.request-list > a, .request-list > li, .request-list > div {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    padding: 16px 2px; border-bottom: 1px solid var(--border);
    color: inherit; text-decoration: none;
}
.request-list > li > div:first-child { min-width: 0; }
.request-list > li[hidden] { display: none; }
.request-list > *:last-child { border-bottom: none; }
.request-list > a:hover { background: var(--hover-bg); }
.request-subject { font-weight: 600; font-size: 15.5px; color: var(--ink); margin-bottom: 4px; }
.request-subject a { color: var(--ink); text-decoration: none; }
.request-subject a:hover { color: var(--link); text-decoration: underline; }
.request-meta { font-size: 13px; color: var(--ink-3); }

.status-pill {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px; border-radius: 999px;
    font-size: 12px; font-weight: 600; white-space: nowrap;
    background: var(--hover-bg); color: var(--ink-2);
}
.status-pill::before { content: "●"; font-size: 9px; }
.status-pill.is-open   { background: var(--info-bg);    color: var(--info-fg); }
.status-pill.is-you    { background: var(--warn-bg);    color: var(--warn); }
.status-pill.is-closed { background: var(--success-bg); color: var(--success); }

/* ---------------------------------------------------------------- articles */

.article-list { display: flex; flex-direction: column; gap: 12px; }
.article-card {
    display: block; padding: 18px 20px;
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); color: inherit; text-decoration: none;
    transition: border-color .12s ease, box-shadow .12s ease;
}
.article-card:hover { border-color: var(--accent); box-shadow: var(--shadow); text-decoration: none; }
.article-title { font-weight: 650; font-size: 16px; margin-bottom: 4px; }
.article-meta  { font-size: 13px; color: var(--ink-3); }
.article-body  { font-size: 16px; line-height: 1.7; }
.article-body h2 { margin-top: 30px; }
.article-body img { max-width: 100%; height: auto; border-radius: var(--radius); }
.article-body pre {
    background: var(--card-2); border: 1px solid var(--border);
    padding: 14px; border-radius: var(--radius); overflow-x: auto; font-size: 14px;
}
.article-body code { background: var(--card-2); padding: 2px 6px; border-radius: 5px; font-size: 14px; }
.article-body blockquote {
    margin: 16px 0; padding-left: 16px;
    border-left: 3px solid var(--border-2); color: var(--ink-2);
}
.article-body table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.article-body th, .article-body td { padding: 9px 12px; border: 1px solid var(--border); text-align: left; }

.tags { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.tag-pill {
    padding: 4px 11px; border-radius: 999px; font-size: 12px;
    background: var(--card-2); border: 1px solid var(--border); color: var(--ink-2);
}
.pin-icon { color: var(--warn); }

/* ---------------------------------------------------------------- attachments */

.attachment-list { display: flex; flex-direction: column; gap: 8px; }
.attachment-list a {
    display: flex; align-items: center; gap: 10px;
    padding: 11px 14px; border: 1px solid var(--border); border-radius: var(--radius);
    color: var(--ink); text-decoration: none; font-size: 14.5px;
}
.attachment-list a:hover { border-color: var(--accent); background: var(--hover-bg); }
.att-meta { font-size: 12.5px; color: var(--ink-3); margin-left: auto; white-space: nowrap; }

.inline-pdf-block { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; margin: 16px 0; }
.inline-pdf-head {
    display: flex; align-items: center; gap: 10px;
    padding: 11px 14px; background: var(--card-2);
    border-bottom: 1px solid var(--border); font-size: 14px; font-weight: 550;
}
.inline-pdf-download { margin-left: auto; font-size: 13px; color: var(--link); text-decoration: none; }
.inline-pdf-download:hover { text-decoration: underline; }
.inline-pdf-block iframe, .inline-pdf-block embed { display: block; width: 100%; min-height: 620px; border: 0; }

/* ---------------------------------------------------------------- timeline */

.timeline { position: relative; padding-left: 22px; }
.timeline::before {
    content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px;
    width: 2px; background: var(--border);
}
.timeline > * { position: relative; padding-bottom: 20px; }
.timeline > *::before {
    content: ""; position: absolute; left: -21px; top: 7px;
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--card); border: 2px solid var(--accent);
}
.timeline-time { font-size: 12.5px; color: var(--ink-3); margin-bottom: 3px; }

/* ---------------------------------------------------------------- asset picker */

.asset-picker { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.apicker-controls { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; padding: 12px 14px; background: var(--card-2); border-bottom: 1px solid var(--border); }
.apicker-search { flex: 1 1 200px; min-width: 0; }
.apicker-spares-only { display: flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 400; margin: 0; white-space: nowrap; }
.apicker-list { max-height: 340px; overflow-y: auto; }
.apicker-row {
    display: flex; align-items: center; gap: 10px;
    padding: 11px 14px; border-bottom: 1px solid var(--border);
    font-weight: 400; margin: 0; cursor: pointer;
}
.apicker-row:last-child { border-bottom: none; }
.apicker-row:hover { background: var(--hover-bg); }
.apicker-empty { padding: 22px 14px; text-align: center; color: var(--ink-3); font-size: 14px; }
.apicker-warn { padding: 11px 14px; background: var(--warn-bg); color: var(--warn); font-size: 13.5px; }
.apicker-warn-name { font-weight: 650; }

/* ---------------------------------------------------------------- impersonation */

.portal-impersonation-banner {
    position: sticky; top: 0; z-index: 40;
    background: var(--warn-bg); color: var(--warn);
    border-bottom: 1px solid var(--warn);
}
.pib-inner {
    max-width: 880px; margin: 0 auto;
    display: flex; align-items: center; gap: 10px;
    padding: 10px 20px; font-size: 13.5px;
}
.pib-icon { flex-shrink: 0; }
.pib-text { flex: 1; min-width: 0; }
.pib-end { color: inherit; font-weight: 650; text-decoration: underline; white-space: nowrap; }

/* ---------------------------------------------------------------- misc */

.empty {
    padding: 34px 20px; text-align: center;
    color: var(--ink-3); font-size: 14.5px;
}
hr { border: 0; border-top: 1px solid var(--border); margin: 26px 0; }
a { color: var(--link); }

/* Nothing on this page should ever make the body scroll sideways on a phone. */
@media (max-width: 560px) {
    body { font-size: 15.5px; }
    h1 { font-size: 23px; }
    .portal-shell { padding: 0 14px 44px; }
    .portal-header { margin-bottom: 22px; }
    .portal-header-inner { padding: 10px 14px; }
    .portal-brand { font-size: 16px; }
    .portal-brand img.logo { height: 30px; }
    .portal-brand-sub { display: none; }
    .action-card { min-height: 0; padding: 20px 18px 18px; }
    .pu-info { display: none; }          /* name and company are on every page; the logout is what is needed */
    .action-grid { grid-template-columns: 1fr; }
}
