/*
    Application layout only. Every colour, space, radius and shadow comes from nocturne.css.

    Written against the EXISTING class names rather than renaming markup to Pillarbox's vocabulary.
    That is a deliberate trade: the whole console restyles without touching a single .razor file or
    a single test selector, so the change is a stylesheet swap that can be reviewed and reverted on
    its own. Porting the markup to .card / .banner-* can follow later if the two consoles ever need
    to share components rather than just a look.
*/

/* ─────────────────────────── app shell ─────────────────────────── */
/*
    v3: A LEFT RAIL, matching Pillarbox. See the note in MainLayout.razor for why this replaced the
    top bar — briefly, the nav outgrew a horizontal tab set and the tables wanted one left edge to
    start from on every screen.

    Grid rather than a fixed-position rail: the rail is a real column, so `main` cannot slide under
    it and no page needs a left margin that has to be kept in step with --nav-width.
*/

.app-shell {
    display: grid;
    grid-template-columns: var(--nav-width) minmax(0, 1fr);
    min-height: 100vh;
}

/*
    minmax(0, 1fr) above, NOT 1fr.

    A grid track sized 1fr floors at min-content, and a wide table's min-content is the sum of its
    unbreakable columns — so the orders table pushed the whole shell wider than the viewport and put
    a horizontal scrollbar on the document, dragging the rail off screen with it. minmax(0, 1fr)
    lets the column be narrower than its content, which is what makes the table scroll inside itself.
*/

/*
    FLEX, NOT GRID, and the reason is worth recording.

    This was grid-template-rows: auto auto 1fr — brand, nav, foot. But NavMenu renders TWO siblings,
    the item list and the role-gated "New account" button, so the rail had four children and the
    button landed on the 1fr row: it stretched into a full-height block down the middle of the rail.

    A grid with named rows has to know how many children it will get, and this one cannot — the
    button and two of the nav items appear only for certain roles. Flex with margin-top: auto on the
    foot is indifferent to the count.
*/
.rail {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    padding: var(--space-6) var(--space-4);
    background: var(--color-surface);
    border-right: 1px solid var(--color-divider);

    /* Sticky, not fixed: it stays put while a long order list scrolls, without leaving the grid. */
    position: sticky;
    top: 0;
    align-self: start;
    height: 100vh;
}

.brand { display: flex; align-items: center; gap: var(--space-3); flex: none; text-decoration: none; }
.brand:hover { text-decoration: none; }

/* The mark is a thin outlined glyph carrying no weight of its own — Nocturne keeps brands quiet. */
.brand-mark { display: block; flex: none; }

.brand-name {
    display: block;
    font-family: var(--font-heading);
    font-weight: 500;
    font-size: 15px;
    letter-spacing: 0.04em;
    color: var(--color-text);
}

.brand-sub { display: block; font-size: 10.5px; color: var(--color-neutral-500); }

.tabs { display: flex; flex-direction: column; gap: 1px; }

.tab {
    font-size: 14px;
    text-decoration: none;
    color: var(--color-neutral-300);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);

    /* The active edge is drawn on every item, transparent until it is active. Adding the border
       only when active shifts the label 2px sideways as you navigate. */
    border-left: 2px solid transparent;
}

.tab:hover { color: var(--color-text); background: color-mix(in srgb, var(--color-text) 6%, transparent); text-decoration: none; }

/*
    v3: active is an accent LEFT EDGE over a lifted surface — not the outlined pill the top bar
    used. In a vertical stack an outline on one item reads as a button among links; an edge reads
    as "you are here", which is the only thing it has to say.
*/
.tab.active {
    color: var(--color-accent-300);
    border-left-color: var(--color-accent);
    background: var(--color-raised);
}

/* ── the rail foot ── */

/* margin-top: auto pins this to the bottom whatever else the rail holds. */
.rail-foot { margin-top: auto; font-size: 12px; }
.rail-foot p { font-size: 11.5px; line-height: 1.45; margin: var(--space-2) 0 var(--space-4); }

.env {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: 10.5px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-neutral-400);
}

/* Accent, not alarm. Being in production is the normal state of this console, not a warning —
   an alarm dot burning permanently in the corner is one people stop seeing within a week. */
.env-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-accent); flex: none; }

.who { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); font-size: 12px; }
.who .btn-ghost { padding-inline: 0; }

main { display: block; min-width: 0; }
.page { padding: var(--space-6) var(--space-6) 56px; max-width: 1400px; }

/*
    A page title with its primary action beside it.

    align-items: start, so a long intro paragraph does not drag the button down the page with it —
    the button belongs level with the heading, which is where the eye arrives.
*/
.page-head {
    display: flex;
    align-items: start;
    justify-content: space-between;
    gap: var(--space-6);
}

/* The intro already carries the bottom margin; inside a page-head it must not add a second one. */
.page-head .page-intro { margin-bottom: 0; }
.page-head + * { margin-top: var(--space-6); }
.page h1 { font-size: 24px; margin: 0 0 var(--space-2); }
.page-intro { margin: 0 0 var(--space-6); font-size: 13px; max-width: 70em; color: var(--color-neutral-400); }

/* ───────────────────────── statistics ───────────────────────── */
/*
    Surface cards with a hairline edge, which is how Nocturne carries elevation on a dark ground.
*/

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: var(--space-3);
    margin-bottom: var(--space-6);
}

.stat {
    padding: var(--space-4);
    background: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}

.stat-value {
    font-family: var(--font-heading);
    font-weight: 500;
    font-size: 26px;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.stat-label {
    font-size: 10.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-top: var(--space-1);
    color: var(--color-neutral-500);
}

/* A statistic that represents a problem takes the alarm hue; the rest stay ink. */
.stat-alert .stat-value { color: var(--color-alarm); }

/* ─────────────────────────── sections ─────────────────────────── */

/*
    v3: A SECTION IS A CARD.

    Before this, sections were separated by nothing but vertical space and the rules inside their
    own tables — the "ruled grid". On a screen like the account detail, which stacks six of them,
    that left no answer to "where does Health end and Customer details begin" except reading the
    headings. A card draws the boundary once, at 8px, and the rules inside it become unnecessary.
*/
.section {
    margin-top: var(--space-6);
    padding: var(--space-6);
    background: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}

/*
    A CARD INSIDE A CARD IS TWO BORDERS SAYING ONE THING.

    Tables, timelines and fact lists each paint their own surface so they work standing alone — on
    the orders list the table IS the page. Inside a section they are already on a surface, so they
    drop it. Without this the nested element is the same colour as its parent with a second hairline
    around it, which reads as a rendering fault rather than as structure.
*/
.section > .table,
.section > .timeline,
.section > .facts {
    background: transparent;
    box-shadow: none;
    border-radius: 0;
}

/* Their outer margins go too: the card's padding is the spacing now. */
.section > .facts { margin-top: 0; margin-bottom: 0; }
.section > .table:last-child tbody tr:last-child td { border-bottom: 0; }

/*
    A notice inside a section cannot use the section's own surface colour or it disappears. One
    step up, matching the dropdown fill — the left rule still carries the meaning.
*/
.section > .notice { background: var(--color-raised); }
.section > .notice-alert { background: linear-gradient(90deg, color-mix(in srgb, var(--color-alarm) 14%, var(--color-raised)), var(--color-raised) 60%); }
.section > .notice-ok { background: linear-gradient(90deg, color-mix(in srgb, var(--color-accent) 14%, var(--color-raised)), var(--color-raised) 60%); }

.section-head { display: flex; align-items: center; gap: var(--space-3); }
.section-head h3 { margin: 0; }
.section-intro { font-size: 12.5px; margin: var(--space-2) 0 var(--space-4); max-width: 60em; color: var(--color-neutral-400); }

/* ── the attention list ── */
.attention-row {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    /* The same fade-to-nothing as .notice-alert — this IS the dashboard's incident band. */
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--color-alarm) 16%, var(--color-surface)),
        var(--color-surface) 60%);
    border-radius: var(--radius-md);
    border-left: 2px solid var(--color-alarm);
    margin-bottom: var(--space-2);
    text-decoration: none;
    color: inherit;
}

.attention-row:hover {
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--color-alarm) 24%, var(--color-raised)),
        var(--color-raised) 60%);
    text-decoration: none;
}
.attention-account { font-family: var(--font-heading); font-weight: 500; font-size: 14px; margin-right: var(--space-2); }
.attention-detail { font-size: 12.5px; }
.attention-count { font-variant-numeric: tabular-nums; font-family: var(--font-heading); font-weight: 500; font-size: 15px; }

/* ── status bars ── */
.bar-row {
    display: grid;
    grid-template-columns: 190px 1fr 80px;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-2) 0;
}

.bar-track { height: 8px; background: var(--color-neutral-900); border-radius: var(--radius-sm); overflow: hidden; }
.bar-fill { display: block; height: 100%; background: var(--color-accent); min-width: 2px; border-radius: var(--radius-sm); }

/* The one status that means "stuck" takes the alarm hue. */
.bar-fill.is-alert { background: var(--color-alarm); }

.bar-count { text-align: right; font-variant-numeric: tabular-nums; font-size: 13px; }
.bar-label { font-size: 13px; }

/* ─────────────────────────── tables ─────────────────────────── */

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
    background: var(--color-surface);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.table th {
    text-align: left;
    font-size: 10.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-neutral-500);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-divider);
    font-weight: 500;
}

.table td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid color-mix(in srgb, var(--color-text) 7%, transparent); }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.table td.num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.table tr.clickable { cursor: pointer; }

.table-foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    padding-top: var(--space-3);
    font-size: 11.5px;
    color: var(--color-neutral-500);
}

/* ─────────────────────────── filters ─────────────────────────── */

.filters {
    display: flex;
    gap: var(--space-3);
    align-items: center;
    flex-wrap: wrap;
    padding: var(--space-3) var(--space-4);
    background: var(--color-surface);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-4);
}

.filters .input { width: 240px; }
.filters .input-narrow { width: 110px; }
.check { display: inline-flex; align-items: center; gap: var(--space-2); font-size: 12.5px; cursor: pointer; }
.check input { accent-color: var(--color-accent); width: 15px; height: 15px; }

/* ───────────────────── detail: facts list ───────────────────── */

.facts {
    display: grid;
    grid-template-columns: 170px 1fr;
    gap: 0;
    margin: var(--space-4) 0 var(--space-8);
    background: var(--color-surface);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.facts dt {
    padding: var(--space-3) var(--space-4);
    font-size: 10.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-neutral-500);
    border-bottom: 1px solid color-mix(in srgb, var(--color-text) 7%, transparent);
}

.facts dd {
    margin: 0;
    padding: var(--space-3) var(--space-4);
    font-size: 13px;
    border-bottom: 1px solid color-mix(in srgb, var(--color-text) 7%, transparent);
}

/* ─────────────────────────── forms ─────────────────────────── */

.field { margin-bottom: var(--space-6); max-width: 520px; }
.field label { display: block; font-size: 12px; margin-bottom: var(--space-1); color: var(--color-neutral-400); }
.row { display: flex; gap: var(--space-2); align-items: flex-start; }
.hint { font-size: 12px; margin: var(--space-2) 0 0; max-width: 60em; color: var(--color-neutral-500); }

/* ─────────────────────── notices (banners) ─────────────────────── */
/*
    A tinted surface with a left rule in the relevant hue. Nocturne's banner shape — the tint is
    faint and the rule carries the meaning, so a page of notices does not turn into a wall of
    colour.
*/

.notice {
    padding: var(--space-4);
    border-radius: var(--radius-md);
    border-left: 2px solid var(--color-neutral-700);
    background: var(--color-surface);
    margin: var(--space-4) 0;
}

.notice h2 { font-size: 15px; margin: 0 0 var(--space-1); }
.notice p { font-size: 12.5px; margin: 0 0 var(--space-2); }
.notice p:last-child { margin-bottom: 0; }

/*
    v3: A GRADIENT THAT FADES OUT, NOT A FLAT TINT.

    The tint used to be even across the whole band, which made a wide notice on a wide screen a
    large field of colour — the exact flood the system forbids everywhere else. The gradient puts
    the weight against the left rule, where the meaning already is, and is gone by 60%. The wider
    the screen, the less colour, which is the right way round.
*/
.notice-alert {
    border-left-color: var(--color-alarm);
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--color-alarm) 16%, var(--color-surface)),
        var(--color-surface) 60%);
}

.notice-ok {
    border-left-color: var(--color-accent);
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--color-accent) 16%, var(--color-surface)),
        var(--color-surface) 60%);
}

.findings { margin: var(--space-2) 0 0; padding-left: 18px; font-size: 12.5px; }
.findings li { margin-bottom: var(--space-1); }

/* ───────────────────── account detail extras ───────────────────── */

.detail-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-6); margin-bottom: var(--space-6); }
.kicker { font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent); }
.detail-head h1 { margin: var(--space-1) 0 var(--space-2); }
.tag-row { display: flex; gap: var(--space-1); }

/* The one-sentence conclusion, at heading weight because it is the answer. */
.verdict { font-family: var(--font-heading); font-weight: 500; font-size: 17px; line-height: 1.3; margin: 0 0 var(--space-2); }

.timeline { list-style: none; margin: 0; padding: 0; background: var(--color-surface); border-radius: var(--radius-md); overflow: hidden; }

.timeline li {
    display: grid;
    grid-template-columns: 130px 1fr;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid color-mix(in srgb, var(--color-text) 7%, transparent);
}

.timeline li:last-child { border-bottom: 0; }
.timeline-when { font-size: 12.5px; font-variant-numeric: tabular-nums; }
.timeline-title { display: block; font-family: var(--font-heading); font-weight: 500; font-size: 13px; }
.timeline-note { display: block; font-size: 12px; }

/* Marked by an alarm rule rather than a red panel — the accent is never a flood. */
/*
    v3: the danger zone is a card with an alarm EDGE, not a rule above un-carded content.

    It used to be a top border separating it from the section above. Now that sections are cards
    that border sat inside one, reading as a stray line rather than a boundary. The edge runs down
    the left like every other alarm in the system, so "this is the destructive part of the page" is
    said the same way "this account is not reaching its scale" is said.
*/
.danger {
    margin-top: var(--space-8);
    border-left: 2px solid var(--color-alarm-700);
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--color-alarm) 10%, var(--color-surface)),
        var(--color-surface) 55%);
}

.danger h3 { color: var(--color-alarm-300); }

/* ─────────────────────── update banner ─────────────────────── */
/*
    NOT a filled accent bar. The Modernist build ran the accent full-width here; Nocturne does not
    flood, so this is a tinted surface with an accent rule and the button carries the emphasis.
*/

.update-banner {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-6);
    background: color-mix(in srgb, var(--color-accent) 10%, var(--color-surface));
    border-bottom: 1px solid color-mix(in srgb, var(--color-accent) 40%, transparent);
}

.update-text { flex: 1; font-size: 12.5px; }

/* ─────────────────────────── sign in ─────────────────────────── */
/*
    A centred card on the ground, not a split poster. The poster was a full accent field, which is
    the exact thing this system does not do.
*/

.login { display: grid; place-items: center; min-height: 100vh; padding: var(--space-6); }

.login-poster {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-6);
    flex-direction: column;
    text-align: center;
}

.login-eyebrow { display: flex; align-items: center; gap: var(--space-2); }
.login-eyebrow span { font-size: 10.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-neutral-500); }

.login-wordmark {
    font-family: var(--font-heading);
    font-weight: 500;
    font-size: 30px;
    letter-spacing: 0.08em;
    color: var(--color-text);
}

.login-rule { display: none; }
.login-statement { font-size: 13px; color: var(--color-neutral-400); max-width: 26em; }
.login-note { display: none; }

.login-form {
    width: min(360px, 100%);
    padding: var(--space-8);
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
}

.login-form h2 { font-size: 17px; margin: 0 0 var(--space-1); }
.login-form form { width: 100%; }

.login-error {
    font-size: 12.5px;
    color: var(--color-alarm-300);
    border-left: 2px solid var(--color-alarm);
    background: color-mix(in srgb, var(--color-alarm) 10%, transparent);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-4);
}

/* ─────────────── forms: the customer-details editor ─────────────── */
/*
    .input-narrow existed only inside .filters. The account screen needs it too — a postcode field
    the width of an address field invites somebody to keep typing.
*/
.field .input-narrow { width: 220px; }

/*
    An address is typed with line breaks in it and is meaningless without them. Everything else on
    these screens is single-line, so this is opt-in rather than a global white-space change.
*/
.preserve-lines { white-space: pre-line; }

/* ─────────────────────── the order journey drawer ─────────────────────── */
/*
    Slides in over the order list rather than replacing it. The question it answers is nearly always
    asked while looking at a filtered list with a butcher on the phone, and navigating away costs
    the list, the filter and the operator's place in it.
*/

.drawer-scrim {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: color-mix(in srgb, var(--color-bg) 72%, transparent);

    /* The page behind stays legible on purpose — the drawer explains a row that is still on screen,
       so blacking it out would break the connection between the two. */
    backdrop-filter: blur(1px);
}

.drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 41;
    width: min(560px, 100vw);
    display: flex;
    flex-direction: column;
    background: var(--color-surface);
    border-left: 1px solid var(--color-neutral-800);

    /* The only shadow in the application. It is what says "on top of", which a border alone does
       not, and it is the one place in this design where that needs saying. */
    box-shadow: -24px 0 48px -24px rgb(0 0 0 / 55%);
    animation: drawer-in 140ms ease-out;
}

/* Respected rather than assumed: a panel flying in from the edge is exactly the motion that causes
   trouble for people who have asked the system to stop doing it. */
@media (prefers-reduced-motion: reduce) {
    .drawer { animation: none; }
}

@keyframes drawer-in {
    from { transform: translateX(16px); opacity: 0; }
    to   { transform: translateX(0);    opacity: 1; }
}

.drawer:focus-visible { outline: none; }

.drawer-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-6);
    border-bottom: 1px solid var(--color-neutral-800);
}

.drawer-head h2 { margin: var(--space-1) 0 0; font-size: 17px; }

.drawer-body {
    padding: var(--space-4) var(--space-6) var(--space-8);
    overflow-y: auto;
}

/* ── the stage list ── */

.journey {
    list-style: none;
    margin: var(--space-6) 0;
    padding: 0;
}

.journey-stage {
    position: relative;
    display: grid;
    grid-template-columns: 14px 1fr;
    gap: var(--space-4);
    padding-bottom: var(--space-6);
}

/* The spine. Drawn on every stage but the last, so the run of dots reads as one sequence. */
.journey-stage:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 6px;
    top: 14px;
    bottom: 0;
    width: 1px;
    background: var(--color-neutral-800);
}

.journey-marker {
    width: 13px;
    height: 13px;
    margin-top: 3px;
    border-radius: 50%;
    border: 1px solid var(--color-neutral-700);
    background: var(--color-surface);
}

/*
    THE MARKER CARRIES THE EVIDENCE, AND THE FILL IS THE MESSAGE.

    Solid = we have a timestamp. Hollow = it happened, or happens, and nothing wrote down when.
    Nothing here uses the alarm colour: a gap in the RECORD is not a fault in the ORDER, and
    colouring it like one would put an alarm on every order in the system.
*/
.journey-stage.is-recorded  .journey-marker { background: var(--color-neutral-300); border-color: var(--color-neutral-300); }
.journey-stage.is-inferred  .journey-marker { border-color: var(--color-neutral-500); }
.journey-stage.is-unrecorded .journey-marker { border-style: dashed; }
.journey-stage.is-unclear   .journey-marker { border-color: var(--color-alarm-700); }
.journey-stage.is-future    .journey-marker { opacity: 0.45; }

/* Not yet happened, so it recedes — but stays readable, because "where it will go next" is half
   the answer when an order is stuck. */
.journey-stage.is-future .journey-content { opacity: 0.6; }

.journey-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.journey-title { font-size: 13.5px; font-weight: 500; }
.journey-when { font-size: 12.5px; margin-top: 2px; color: var(--color-neutral-300); }
.journey-detail { font-size: 12.5px; margin: var(--space-2) 0 0; }

.journey-caveat {
    font-size: 12px;
    margin: var(--space-2) 0 0;
    padding-left: var(--space-3);
    border-left: 2px solid var(--color-alarm-700);
    color: var(--color-neutral-400);
}

.journey-source {
    display: inline-block;
    margin-top: var(--space-2);
    font-size: 11px;
    color: var(--color-neutral-500);
}

/* A trailing cell of actions inside a click-to-open row. Right-aligned and quiet, so it does not
   compete with the row itself. */
.row-action { text-align: right; white-space: nowrap; }
.btn-small { font-size: 11.5px; min-height: 24px; padding: 0 var(--space-2); }
