/* ===========================================================================
   OIStudio Ops — app-specific styling on top of OpenImpact.Horizon.
   tokens.css/base.css (loaded in App.razor) provide the design tokens, layout
   engine, Onest font and canonical .btn/.status-pill/.table styling; this
   file holds only Ops's own identity (enquiry-status colours, the Pacific
   Horizon coral/amber/ocean/deep accents, --seal/--link/--glass-bg) and the
   admin topbar/table/form layout specific to this app.
   =========================================================================== */

:root {
    /* Pacific Horizon accents — used sparingly, no package equivalent */
    --coral: #FF7A59;
    --amber: #FFB347;
    --ocean: #0E5C7A;
    --deep: #052131;
    --accent-glow: rgba(0, 212, 170, 0.28);

    /* Glass + depth — no package equivalent, kept local per Selo's precedent */
    --glass-bg: rgba(255, 255, 255, 0.82);

    /* Fixed identity tokens — never white-labelled, per Selo's precedent */
    --seal: var(--deep);
    --link: var(--accent-strong);

    /* Status identity — enquiry-state colours, no package equivalent */
    --status-new-bg: var(--accent-soft);
    --status-new-fg: #0A7C64;
    --status-inprogress-bg: rgba(255, 179, 71, 0.18);
    --status-inprogress-fg: #8A5A12;
    --status-responded-bg: rgba(14, 92, 122, 0.14);
    --status-responded-fg: var(--deep);
    --status-closed-bg: rgba(100, 116, 139, 0.16);
    --status-closed-fg: #475569;

    /* Task status identity: four new states beside the enquiry ones.
       status-inprogress is shared: it means the same thing in both. */
    --status-todo-bg: rgba(100, 116, 139, 0.12);
    --status-todo-fg: #475569;
    --status-blocked-bg: rgba(255, 122, 89, 0.20);
    --status-blocked-fg: #B23A1C;
    --status-done-bg: var(--accent-soft);
    --status-done-fg: #0A7C64;
    --status-cancelled-bg: rgba(100, 116, 139, 0.16);
    --status-cancelled-fg: #64748B;
}

/* ---- Blazor framework boilerplate ---- */
h1:focus { outline: none; }
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--accent-strong); }
.invalid { outline: 1px solid var(--coral); }
.validation-message { color: #B23A1C; }

.blazor-error-boundary {
    background: #B23A1C;
    padding: 1rem 1.5rem;
    color: #fff;
}
.blazor-error-boundary::after { content: "An error has occurred."; }

/* ---- Base + typography ---- */
body {
    background-image:
        radial-gradient(60rem 40rem at 88% -10%, rgba(0, 212, 170, 0.06), transparent 60%),
        radial-gradient(50rem 36rem at -10% 8%, rgba(14, 92, 122, 0.05), transparent 55%);
    background-attachment: fixed;
}

a { color: var(--link); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--accent-strong); }

.error { color: #B23A1C; font-weight: 600; }
.success { color: #0A7C64; font-weight: 600; }
.field-hint { font-size: 0.8rem; color: var(--muted); margin: 0; }

/* Horizon's canonical .btn-primary sets white text on --accent; this app's
   teal (#00D4AA) is too light for white text to meet contrast — kept as
   Ops's original dark-ink text, worth fixing upstream in Horizon someday
   since Selo/Suara share the same teal accent and don't override this. */
.btn-primary { color: var(--ink); }

/* ---- Admin topbar and content ---- */
.admin-topbar {
    display: flex; align-items: center; justify-content: flex-end; gap: 1rem;
    padding: 0.85rem 2rem; border-bottom: 1px solid var(--line-subtle);
    background: var(--glass-bg); backdrop-filter: saturate(160%) blur(16px);
    -webkit-backdrop-filter: saturate(160%) blur(16px); min-height: 1.5rem; position: sticky; top: 0; z-index: 5;
}
.admin-who { font-weight: 600; font-size: 0.9rem; }
.admin-logout { margin: 0; }

/* The hamburger that opens the mobile drawer. Local rather than Horizon's
   .top-nav-menu, because this topbar is not a TopNav and borrowing another
   component's internal class is how a consumer gets broken by somebody else's
   refactor. Shown only below 768px, which is exactly where Horizon hides the rail. */
.admin-drawer-toggle { display: none; }

.admin-main { padding: 2rem 2.25rem; max-width: 66rem; }
.admin-main h1 { margin-top: 0; font-size: 1.7rem; }

/* ---- Admin login ---- */
.admin-login { max-width: 23rem; margin: 14vh auto 0; text-align: center; }
.admin-login h1 { margin: 1.1rem 0 1.75rem; font-size: 1.6rem; }
.admin-login form { display: flex; flex-direction: column; gap: 0.9rem; text-align: left; }
.admin-login label { display: flex; flex-direction: column; gap: 0.35rem; font-weight: 600; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.admin-login button { margin-top: 0.4rem; }
.admin-login .error { margin-top: 0; }

/* ---- Filter control ---- */
.filter {
    padding: 0.55rem 0.8rem; border: 1px solid var(--line); border-radius: var(--radius-pill);
    min-width: 14rem; background: #fff; font: inherit;
}
.filter:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ---- Admin forms ---- */
.admin-form {
    display: flex; flex-wrap: wrap; gap: 0.7rem; align-items: flex-end; margin: 1rem 0;
    padding: 1.25rem; border: 1px solid var(--line-subtle); border-radius: var(--radius-md); background: #fff; box-shadow: var(--shadow-lift);
}
.admin-form textarea { flex-basis: 100%; resize: vertical; }
.admin-form > button[type="button"]:disabled { cursor: default; opacity: 0.45; }

.admin-form--stacked { flex-direction: column; align-items: stretch; max-width: 36rem; }
.admin-form--stacked label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }

/* A checkbox inside a non-stacked .admin-form: its siblings stack a label above a
   block control, but a checkbox is inline, so this lays the label out as a row beside it. */
.admin-form > label.check { display: flex; flex-direction: row; align-items: center; gap: 0.4rem; }

/* This has the same specificity as the rule above, so it must stay declared
   after it: the checkbox on the New task modal matches both selectors (it is
   a direct child of an .admin-form that is also .admin-form--stacked), and
   source order is what lets this one keep its own gap and text styling there. */
.admin-form--stacked label.check { flex-direction: row; align-items: center; gap: 0.5rem; text-transform: none; letter-spacing: 0; color: var(--ink); font-size: 0.9rem; }
.admin-form--stacked label.check input { width: auto; }
.admin-form--stacked button { align-self: flex-start; }

/* ---- Enquiry detail ---- */
.detail-meta { color: var(--muted); margin: 0 0 1.25rem; }
.detail-block { margin: 1.25rem 0; }
.detail-block > .label {
    display: block; font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.07em;
    color: var(--muted); font-weight: 600; margin-bottom: 0.35rem;
}
.detail-message { white-space: pre-wrap; background: #fff; border: 1px solid var(--line-subtle); border-radius: var(--radius-md); padding: 1rem 1.15rem; box-shadow: var(--shadow-ring); }
.notes { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.notes li, .notifications li { background: #fff; border: 1px solid var(--line-subtle); border-radius: var(--radius-md); padding: 0.75rem 0.95rem; box-shadow: var(--shadow-ring); }
.notes li small, .notifications li small { color: var(--muted); }
/* Note bodies are typed into a textarea and can be multi-paragraph, so their
   newlines are content. On the span rather than the li, or the Razor source
   indentation surrounding the markup renders too. */
.note-body { white-space: pre-wrap; }

/* Puts the Pin control on the same line as the note's timestamp. The button is
   rendered for admins only, so on most operators' screens this row holds the
   timestamp alone and looks exactly as it did before. */
.note-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; }

/* Horizon's .btn has no size modifier, and a full-size ghost button beside a
   timestamp overwhelms the note it belongs to. */
.note-pin, .notification-mark { padding: 0.1rem 0.5rem; font-size: 0.7rem; }

/* ---- Pinned note ----
   Lifted out of the thread and rendered above the details form, because a pin
   that only floats to the top of a thread sitting below the checklist is still
   below the fold. Borrows .admin-task-banner's accent bar so the two page-level
   callouts read as a set; the pill borrows .admin-pill further down. */
.pinned-note {
    margin: 0 0 1rem;
    padding: 0.75rem 0.95rem;
    border-left: 3px solid var(--accent-strong);
    background: var(--accent-soft);
    border-radius: var(--radius-md);
}
.pinned-note p { margin: 0; }

/* Clamped rather than line-clamped: -webkit-box would fight the pre-wrap that
   keeps a multi-paragraph note's blank lines, and a max-height in em is stable
   whatever the note contains. The fade has to end in the callout's own
   background, not white, or it reads as a printing fault. */
.pinned-body-clamped { max-height: 9em; overflow: hidden; position: relative; }
.pinned-body-clamped::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3.25em;
    background: linear-gradient(to bottom, transparent, var(--accent-soft));
}
/* The clamp cuts mid-line, so the toggle needs real space under it or it reads
   as sitting on top of the text the fade is still dissolving. */
.pinned-toggle { margin-top: 0.7rem; padding: 0.1rem 0.5rem; font-size: 0.75rem; }
.pinned-note-head { margin-bottom: 0.4rem; }
.pinned-note-head small, .pinned-note-foot small { color: var(--muted); }
.pinned-note-foot {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 0.75rem; margin-top: 0.6rem;
}

/* ---- Status badges — kept local: StatusPill (the package's component) is
   single-tone by design, but operators rely on four distinct colours here
   to scan the enquiries list at a glance. ---- */
.status-badge {
    display: inline-flex; align-items: center; padding: 0.22rem 0.65rem;
    border-radius: var(--radius-pill); font-size: 0.7rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.06em;
}
.status-badge.status-new { background: var(--status-new-bg); color: var(--status-new-fg); }
.status-badge.status-inprogress { background: var(--status-inprogress-bg); color: var(--status-inprogress-fg); }
.status-badge.status-responded { background: var(--status-responded-bg); color: var(--status-responded-fg); }
.status-badge.status-closed { background: var(--status-closed-bg); color: var(--status-closed-fg); }
.status-badge.status-todo { background: var(--status-todo-bg); color: var(--status-todo-fg); }
.status-badge.status-blocked { background: var(--status-blocked-bg); color: var(--status-blocked-fg); }
.status-badge.status-done { background: var(--status-done-bg); color: var(--status-done-fg); }
.status-badge.status-cancelled { background: var(--status-cancelled-bg); color: var(--status-cancelled-fg); text-decoration: line-through; }

/* Three more states on the existing four-colour .status-badge. Local for the
   same reason the others are: Horizon's StatusPill is single-tone, and an
   editor scanning 180 rows for what still needs approval reads colour first.
   Reuses the task-status tokens above rather than defining new ones: Draft
   reads as "not started yet" the same way Todo does, In review as "being
   worked" the same way In progress does, and Approved as "done" the same way
   Done does. */
.status-badge.status-draft { background: var(--status-todo-bg); color: var(--status-todo-fg); }
.status-badge.status-inreview { background: var(--status-inprogress-bg); color: var(--status-inprogress-fg); }
.status-badge.status-approved { background: var(--status-done-bg); color: var(--status-done-fg); }

/* ---- Task board ---- */
.priority-high { font-weight: 700; color: #B23A1C; }
.priority-low { color: var(--muted); }

/* The whole overdue treatment: the date goes red. No extra badge, no
   separate view. Applied only while the task is neither Done nor Cancelled. */
.overdue { color: #B23A1C; font-weight: 700; }

.board-tabs { margin-bottom: 0.5rem; }

/* ---- Checklist (task detail) ---- */
.checklist { list-style: none; margin: 0.75rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.checklist li {
    display: flex; align-items: center; gap: 0.6rem;
    background: #fff; border: 1px solid var(--line-subtle); border-radius: var(--radius-md);
    padding: 0.5rem 0.75rem; box-shadow: var(--shadow-ring);
}
.checklist li > span { flex: 1 1 auto; }
.checklist li.is-done > span { text-decoration: line-through; color: var(--muted); }
.checklist input[type="checkbox"] { width: auto; margin: 0; }

/* A sibling of .checklist above, and local for the same reason: Horizon has no
   list primitive that renders an anchor, a destination and a removal control on
   one row. The host is muted and deliberately not part of the anchor, so a
   free-text label cannot disguise where the link goes. */
.task-links { list-style: none; margin: 0.75rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.task-links li {
    background: #fff; border: 1px solid var(--line-subtle); border-radius: var(--radius-md);
    padding: 0.5rem 0.75rem; box-shadow: var(--shadow-ring);
}
.task-link-head { display: flex; align-items: baseline; gap: 0.6rem; }
.task-link-head > a { flex: 0 1 auto; overflow-wrap: anywhere; }
.task-link-host { flex: 1 1 auto; color: var(--muted); font-size: 0.85rem; }
.task-link-note { display: block; margin-top: 0.2rem; color: var(--muted); font-size: 0.85rem; }

/* A sibling of .checklist and .task-links above, local for the same reason: Horizon
   0.5.1 has no list primitive that renders an anchor with trailing metadata on one
   row. Shaped to match them because a project's subtasks sit exactly where its
   checklist used to, and the two must not step out of line with each other. */
.subtasks { list-style: none; margin: 0.75rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.subtasks li {
    display: flex; align-items: center; gap: 0.6rem;
    background: #fff; border: 1px solid var(--line-subtle); border-radius: var(--radius-md);
    padding: 0.5rem 0.75rem; box-shadow: var(--shadow-ring);
}
.subtasks li > a { flex: 1 1 auto; overflow-wrap: anywhere; }
.subtasks li small { color: var(--muted); font-size: 0.85rem; }

/* The line under the header on a subtask, pointing back at its project. Pulled up
   against the header, because it belongs to the title rather than to the meta block
   that follows it. */
.subtask-parent { margin: -0.5rem 0 0.75rem; }

/* A muted inline hint, used for the links cap message. Horizon 0.5.0 defines no
   .hint, so this does not collide with anything shared; it is local because
   nothing else needed a generic hint style until this one did. */
.hint { color: var(--muted); font-size: 0.85rem; margin: 0.2rem 0 0; }

/* The one place a non-admin is told why the controls are inert. Written when
   Horizon had no inline notice component; 0.5.0 has since added Alert, with
   tones, which probably covers this. Nobody has compared the two, so this stays
   local until somebody does. Do not treat its localness as a standing decision. */
.admin-task-banner {
    padding: 0.6rem 0.8rem;
    border-left: 3px solid var(--accent-strong);
    background: var(--accent-soft);
    border-radius: var(--radius-md);
    font-size: 0.9rem;
    color: var(--ink);
}

/* ---- Knowledge detail ---- */
/* The details form beside a status/jurisdictions/danger rail, which nothing
   else in Ops needed: every other detail page (task, enquiry) is one column.
   No Horizon equivalent, so this is local. Collapses to one column on the
   same breakpoint the admin shell already uses for tablet width. */
.detail-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(16rem, 1fr); gap: 1.5rem; align-items: start; }
.detail-side h2 { margin-top: 0; }

/* A row of status-move buttons. Horizon's .btn has no wrapping layout of its
   own to borrow, and there can be as many as two here (Draft has both In
   review and Approved to move to). */
.status-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.5rem 0 1.5rem; }

/* ---- Data table — restores the boxed look Ops had before (base.css's
   .table-container only sets overflow-x; background/radius/shadow added
   here, not conflicting with the package's own rule). ---- */
.table-container {
    background: #fff;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lift);
}
.table tbody tr.clickable:hover { background: var(--accent-soft); }

.hidden-hp { position: absolute; left: -9999px; }

/* ===========================================================================
   Responsive — desktop / tablet / mobile
   =========================================================================== */
@media (max-width: 992px) {
    .admin-topbar { padding: 0.75rem 1.25rem; }
    .admin-main { padding: 1.5rem 1.25rem; }
    .detail-grid { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
    .admin-drawer-toggle {
        display: inline-flex; align-items: center; justify-content: center;
        width: 2.5rem; height: 2.5rem; margin-right: auto;
        border: none; background: none; color: var(--ink);
        border-radius: var(--radius-sm); cursor: pointer;
    }
    .admin-drawer-toggle:hover { background: var(--surface-sunk); }
}

@media (max-width: 576px) {
    .admin-main { padding: 1rem; }
    .filter { min-width: 0; width: 100%; }
    .admin-form { padding: 1rem; }
}

/* Local, not Horizon's StatusPill: this is a single-tone marker sitting inline
   inside a table cell, and StatusPill is sized for standalone use. Borrows the
   radius and type scale of the local .status-badge so the two read as a set. */
.admin-pill, .pinned-pill, .project-pill {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.05rem 0.45rem;
    border: 1px solid var(--line-subtle);
    border-radius: var(--radius-pill);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    vertical-align: middle;
    color: var(--muted);
}

/* Shares .admin-pill's declaration above rather than restating it, so the two
   markers cannot drift apart. Only the margin differs: this one starts a line
   instead of trailing a title. */
.pinned-pill { margin-left: 0; }

/* Shares the declaration above rather than restating it, for the reason
   .pinned-pill does. Only the colour differs, because a project marker and an
   admin marker can appear on the same row and have to be told apart at a glance. */
.project-pill { color: var(--accent-strong); border-color: var(--accent-strong); }

/* The project name on a subtask row, and the progress count on a project row.
   One class, because both are the same thing: quiet context trailing a title. */
.subtask-meta { margin-left: 0.5rem; color: var(--muted); font-size: 0.85rem; }

/* The bar itself is Horizon's own .progress, not a local one. An earlier version of
   this block defined .progress locally on the belief that Horizon shipped no progress
   primitive; it does, at base.css, and the two rules collided. The local rule set
   display and gap but not height or overflow, so Horizon's height of --space-2 and its
   overflow: hidden came through and clipped the count text sitting inside the flex row.
   Hence the wrapper has a name of its own: what is genuinely missing upstream is a row
   pairing a bar with its count, not the bar. */
.progress-cell { display: flex; align-items: center; gap: 0.5rem; min-width: 8rem; }
.progress-cell .progress { flex: 1 1 auto; }
.progress-count { color: var(--muted); font-size: 0.85rem; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* The attention column. Colour reinforces the words rather than carrying the meaning
   alone, because a count that only reads as urgent when you can distinguish the hue is
   not readable by everyone. .overdue above is reused so late work looks the same here
   as it does on the board. */
.attention { display: flex; flex-wrap: wrap; gap: 0.1rem 0.6rem; }
.attention-blocked { color: #B45309; font-weight: 700; }
.attention-clear { color: var(--muted); }

/* The next-due cell: a date somebody scans, with the subtask it belongs to underneath,
   because a bare date leaves you opening the project to find out what it refers to. */
.next-due { display: flex; flex-direction: column; line-height: 1.3; }
.next-due-title { color: var(--muted); font-size: 0.85rem; }

/* ---- Notifications ---- */
/* The same card shape as the task note thread, because a notification is a note:
   folded into the .notes li and .notes li small rules above rather than restated,
   so the two provably stay in step instead of by convention. Local because Horizon
   has no list component for this at 0.5.0. Read rows recede but stay: the task's
   own thread is the permanent record, so removing them preserves nothing, and an
   inbox you can empty is an inbox you can empty by accident. */
.notifications { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.notifications li.is-read { opacity: 0.55; box-shadow: none; }

/* ---- Mentions ---- */
/* Anchored below the field rather than at the caret: caret-pixel anchoring needs
   a mirror-div measuring hack in JavaScript, and a full-width list under the box
   reads as a combobox rather than as a near miss at being one. Local because
   Horizon has no combobox at 0.5.0. Borrows the card shape of .notes li above,
   so the menu reads as part of this app rather than as a browser default. */
.mention-field { position: relative; }
.mention-field textarea { width: 100%; }
/* The last four undo .admin-form--stacked label, which the two description fields
   sit inside and which uppercases, tracks out, mutes and shrinks everything in it.
   Handles are lowercase, so an inherited uppercase menu offers a handle in a form
   that is not the one it inserts; the muted colour flattens the handle into the
   name beside it; and the smaller size puts the handle under the 0.85rem name
   below, inverting the hierarchy those two rules are built around. All four,
   the way label.check above undoes all four. */
.mention-menu {
    position: absolute; left: 0; right: 0; top: 100%; z-index: 20;
    margin: 0.15rem 0 0; padding: 0.25rem; list-style: none;
    max-height: 12rem; overflow-y: auto;
    background: #fff; border: 1px solid var(--line-subtle);
    border-radius: var(--radius-md); box-shadow: var(--shadow-lift);
    text-transform: none; letter-spacing: normal; color: var(--ink); font-size: 0.9rem;
}
.mention-menu li {
    padding: 0.3rem 0.5rem; border-radius: var(--radius-md); cursor: pointer;
}
.mention-menu li.is-highlighted { background: var(--accent-soft); }
.mention-menu span { color: var(--muted); margin-left: 0.5rem; font-size: 0.85rem; }
