/* =============================================================================
 * NeuraCoreWebHandler — the console's own layer.
 * -----------------------------------------------------------------------------
 * Loaded AFTER the shared theme (`neuracore.css`), which it refines and never
 * replaces. Nothing here defines a colour: every value is a token from the
 * theme, so the console and the landing site cannot drift apart.
 *
 * The shape — a fixed vertical tab strip on the left, one panel on the right —
 * is deliberately the shape of NeuraCoreDeploy and of the desktop client. An
 * operator moving between the three should not have to learn a third
 * navigation.
 * ========================================================================== */

/* --- The frame ----------------------------------------------------------- */
.console {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    min-height: 100vh;
}

/* `minmax(0, 1fr)` above and this below are what keep a wide table from
   widening the whole grid: without them a table's intrinsic width becomes the
   column's minimum and the page grows sideways every reflow. */
.console__main {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.console__side {
    background: var(--nc-panel);
    border-right: 1px solid var(--nc-line);
    padding: var(--nc-space-6) var(--nc-space-4);
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.console__brand { margin-bottom: var(--nc-space-1); }
.console__side-note {
    font-size: var(--nc-size-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin: 0 0 var(--nc-space-6);
}

/* The release tag. This console has a tab strip where the other surfaces have a
   footer, so it goes at the foot of the strip: `margin-top: auto` puts it there
   on a tall viewport and immediately after the tabs on a short one, which is
   what the flex column below makes possible. */
.console__side { display: flex; flex-direction: column; }
.console__side-version { margin: var(--nc-space-6) 0 0; }

@media (min-height: 40rem) {
    .console__side-version { margin-top: auto; }
}

.vtab__glyph {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
}

/* How many support tickets are open, at the far end of the Support tab. The
   tab is already a flex row, so `margin-left: auto` is what puts the disc
   against the edge of the strip rather than against the label, and keeps it
   there whatever the label's length.

   A disc rather than a rectangle, and never narrower than it is tall: a count
   is one or two digits and a pill that resized with them would jitter down the
   strip as tickets arrive. */
.vtab__count {
    margin-left: auto;
    flex: 0 0 auto;
    min-width: 1.4rem;
    height: 1.4rem;
    padding: 0 0.35rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    font-size: var(--nc-size-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/* Nothing waiting. It carries its own dark ground rather than sitting
   transparent, because the Support tab can be the active one and the active tab
   is a cyan fill: a disc with no ground would put dim text straight onto the
   cyan, which is the one thing AGENTS.md does not allow. Dark on the panel and
   dark on the cyan both read, so one rule covers the tab in either state. */
.vtab__count--none {
    background: var(--nc-bg);
    border: 1px solid var(--nc-line);
    color: var(--nc-text-dim);
}

/* One or more, which is the whole reason the badge is there. */
.vtab__count--waiting {
    background: var(--nc-red);
    border: 1px solid var(--nc-red);
    color: #ffffff;
}

/* --- The bar above the panel --------------------------------------------- */
.console__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--nc-space-4);
    padding: var(--nc-space-4) var(--nc-space-8);
    border-bottom: 1px solid var(--nc-line);
    background: rgba(18, 18, 20, 0.9);
    backdrop-filter: blur(8px);
    position: sticky;
    top: 0;
    z-index: 10;
}

.console__title { margin: 0; font-size: var(--nc-size-xl); }

.console__identity {
    display: flex;
    align-items: center;
    gap: var(--nc-space-3);
}

.console__who {
    display: inline-flex;
    align-items: center;
    gap: var(--nc-space-2);
    font-size: var(--nc-size-sm);
    font-weight: 600;
    color: var(--nc-text-dim);
}
.console__who:hover { color: var(--nc-cyan); text-decoration: none; }

.console__content {
    padding: var(--nc-space-6) var(--nc-space-8) var(--nc-space-16);
    display: flex;
    flex-direction: column;
    gap: var(--nc-space-6);
    min-width: 0;
}

/* --- The sign-in wall ---------------------------------------------------- */
.gate {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: var(--nc-space-6);
}

.gate__card {
    width: 100%;
    max-width: 420px;
    background: var(--nc-panel);
    border: 1px solid var(--nc-line);
    border-radius: var(--nc-radius-lg);
    padding: var(--nc-space-8);
    box-shadow: var(--nc-shadow);
}

.gate__brand {
    display: flex;
    align-items: center;
    gap: var(--nc-space-3);
    font-weight: 700;
    font-size: var(--nc-size-lg);
    color: #fff;
}
.gate__subtitle {
    font-size: var(--nc-size-xs);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin: var(--nc-space-1) 0 var(--nc-space-6);
}
.gate__headline { font-size: var(--nc-size-lg); margin-bottom: var(--nc-space-4); }
.gate__form { margin-top: var(--nc-space-4); }
.gate__form .nc-btn { margin-top: var(--nc-space-2); }

/* --- Second-factor enrolment --------------------------------------------- */
.enrol__secret { margin-bottom: var(--nc-space-4); }
.enrol__code {
    display: block;
    margin-top: var(--nc-space-2);
    padding: var(--nc-space-3);
    /* The secret is read off the screen and typed into a phone, so it is set
       large, spaced and selectable rather than squeezed into a line. */
    font-size: var(--nc-size-base);
    letter-spacing: 0.12em;
    line-height: 1.6;
    word-break: break-all;
    user-select: all;
}
.enrol__code--uri {
    font-size: var(--nc-size-xs);
    letter-spacing: 0;
}
.enrol__qr { margin-bottom: var(--nc-space-4); }

/* The frame is what the camera sees, so its job is contrast and nothing else.
   The cyan ground is the SVG's own, painted by the encoder; this only sets the
   code on the page and gives it the same padding the quiet zone assumes. */
.enrol__qr-frame {
    display: inline-block;
    margin-top: var(--nc-space-2);
    padding: var(--nc-space-2);
    background: var(--nc-cyan);
    border-radius: var(--nc-radius-sm);
    line-height: 0;
}
.enrol__qr-frame svg {
    display: block;
    /* Bounded, so a long URI's larger symbol cannot push the gate card wide,
       and never scaled up past its natural size where it would go soft. */
    width: 100%;
    max-width: 260px;
    height: auto;
    /* A QR code is a grid of hard squares. Smooth interpolation on a scaled
       symbol blurs the module edges, which is exactly what a decoder is
       measuring. */
    image-rendering: pixelated;
}

/* --- Listings ------------------------------------------------------------ */
.listing {
    display: flex;
    flex-direction: column;
    gap: var(--nc-space-3);
    min-width: 0;
}

.listing__search {
    display: flex;
    gap: var(--nc-space-2);
    align-items: center;
    flex-wrap: wrap;
}
/* A finite width, never a stretchy one: a search box that asks for all the room
   there is pushes the buttons beside it off the row. */
.listing__search .nc-input { width: min(340px, 100%); }

.listing__summary { margin: 0; font-size: var(--nc-size-sm); }

/* An avatar cell is a name with its key underneath. Both are needed: the name
   is what a person recognises, the key is what every record is made against. */
.avatar-cell { display: flex; flex-direction: column; gap: 1px; }
.avatar-cell__name { font-weight: 600; }
.avatar-cell__key { font-size: var(--nc-size-xs); }

/* Three hardware banners in one cell rather than three columns, which would
   push everything else off a laptop screen.

   Deliberately not a flex column, however tempting it is: `display: flex` on a
   `<td>` stops it being a table cell, the browser wraps it in an anonymous one,
   and the theme's `vertical-align: middle` stops reaching it. The folded cell
   then sits a line higher than every other cell in its row. The disclosure
   below stacks its own lines, so the cell has no reason to. */
.machine {
    font-size: var(--nc-size-xs);
    max-width: 26ch;
}

/* Folded, the cell is the name of the operating system alone; the kernel
   version, the processor and the adapter arrive on a click. A `<details>`
   because the console has no JavaScript.

   The two labels both sit in the summary and swap, because the summary is the
   only thing a second click can land on to fold the cell back. Neither is
   restyled: this is a fold, not a link, so it keeps the colours and the weight
   of the text it replaces and says it is clickable with the cursor alone. */
.machine__more summary {
    display: block;      /* Not `list-item`, which is where the triangle comes from. */
    cursor: pointer;
    list-style: none;    /* And where Firefox's comes from. */
}
.machine__more summary::-webkit-details-marker { display: none; }
.machine__more > .nc-faint { display: block; }
.machine__long { display: none; }
.machine__more[open] .machine__short { display: none; }
.machine__more[open] .machine__long { display: block; }

/* Centred rather than ranged right, for the three narrow figures at the far end
   of the heartbeat's row: against the table's edge each one sat a long way from
   its own heading. `nc-num` still supplies the mono digits, which is what keeps
   the figures in a column comparable; this only moves them. The heading takes
   the class with the cells, through `Components::table`, so a column and its
   heading cannot come apart. */
.nc-table th.col-mid,
.nc-table td.col-mid { text-align: center; }

.journal__detail { max-width: 46ch; }

/* --- Row actions --------------------------------------------------------- */
.row-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--nc-space-2);
}
.row-actions form { display: inline-flex; gap: var(--nc-space-2); align-items: center; }
.row-actions .nc-input { width: 11rem; }

/* `<details>` rather than a modal: the console has no JavaScript, and a
   disclosure is the one native control that hides a destructive form until
   somebody asks for it. */
.row-actions__more summary {
    cursor: pointer;
    font-size: var(--nc-size-xs);
    font-weight: 600;
    color: var(--nc-text-dim);
    padding: 0.3rem 0.6rem;
    border: 1px solid var(--nc-line);
    border-radius: var(--nc-radius-pill);
    list-style: none;
}
.row-actions__more summary::-webkit-details-marker { display: none; }
.row-actions__more summary:hover { color: var(--nc-cyan); border-color: var(--nc-cyan); }
.row-actions__more[open] summary { color: var(--nc-cyan); border-color: var(--nc-cyan); }
.row-actions__more > *:not(summary) { margin-top: var(--nc-space-2); }
.row-actions__more .nc-hint { max-width: 26ch; }

/* --- Maintenance tab ----------------------------------------------------- */
/* The four counts, above everything else on the console's first page. Auto-fit
   rather than a fixed four columns: at 700px four tiles of numbers become four
   columns of one digit each. */
.overview {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: var(--nc-space-3);
}
.overview__tile {
    background: var(--nc-panel);
    border: 1px solid var(--nc-line);
    border-radius: var(--nc-radius);
    padding: var(--nc-space-4) var(--nc-space-5, var(--nc-space-4));
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.overview__value {
    font-size: var(--nc-size-xl);
    font-weight: 650;
    line-height: 1.1;
    /* Tabular figures, so four tiles side by side line their digits up and a
       number that changes does not shuffle the ones beside it. */
    font-variant-numeric: tabular-nums;
    color: var(--nc-cyan);
}
.overview__label {
    font-size: var(--nc-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--nc-text-dim);
}

.status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--nc-space-4);
}
.status__state { display: flex; align-items: center; gap: var(--nc-space-3); flex-wrap: wrap; }
.status__line { margin: 0; font-size: var(--nc-size-sm); }
.status__action { flex: 0 0 auto; }

.address__title,
.settings__title { font-size: var(--nc-size-lg); margin-bottom: var(--nc-space-2); }
.address__value { font-size: var(--nc-size-lg); margin-bottom: var(--nc-space-2); }

.setting {
    display: grid;
    grid-template-columns: minmax(240px, 1fr) minmax(260px, 1fr);
    gap: var(--nc-space-4);
    align-items: start;
    padding-block: var(--nc-space-4);
    border-top: 1px solid var(--nc-line-soft);
}
.setting:first-of-type { border-top: 0; }
.setting__label { font-weight: 600; display: block; }
.setting__code { font-size: var(--nc-size-xs); }
.setting__description { margin: var(--nc-space-1) 0 0; }
.setting__updated { font-size: var(--nc-size-xs); margin: var(--nc-space-1) 0 0; }
.setting__control form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--nc-space-2);
}
.setting__control .setting__input { width: min(280px, 100%); }
.setting__control textarea { width: 100%; }

/* --- Definition lists ---------------------------------------------------- */
.facts {
    display: grid;
    grid-template-columns: minmax(140px, auto) 1fr;
    gap: var(--nc-space-2) var(--nc-space-4);
    margin: 0 0 var(--nc-space-4);
    font-size: var(--nc-size-sm);
}
.facts dt { color: var(--nc-text-dim); font-weight: 600; }
.facts dd { margin: 0; }

/* --- Narrow viewports ---------------------------------------------------- */
@media (max-width: 1000px) {
    .setting { grid-template-columns: 1fr; }
}

@media (max-width: 820px) {
    /* The tab strip becomes a horizontal row above the panel. A 232px column on
       a phone leaves nothing for the table it is meant to be navigating. */
    .console { grid-template-columns: 1fr; }
    .console__side {
        position: static;
        height: auto;
        border-right: 0;
        border-bottom: 1px solid var(--nc-line);
    }
    .nc-vtabs { flex-direction: row; flex-wrap: wrap; }
    .nc-vtab { border-left: 0; border-bottom: 3px solid transparent; }
    .nc-vtab--active { border-bottom-color: var(--nc-cyan); }
    .console__top,
    .console__content { padding-inline: var(--nc-space-4); }
}

/* --- The giveaway control ------------------------------------------------ */
/* One row: the object, how many, and the button. It wraps rather than
   compressing, because "How many" reading as a two-character box next to a
   truncated object name is how somebody gives away the wrong thing. */
.giveaway__form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--nc-space-2);
}
.giveaway__pick { flex: 1 1 260px; min-width: 0; }
.giveaway__qty  { flex: 0 0 5.5rem; }

/* The button is inert while the selection is "None".

   This console ships no client-side script and its Content-Security-Policy
   forbids it, so the usual `onchange` handler is not available; `:has()` with
   `option[value=""]:checked` asks the same question in the stylesheet.

   It is PRESENTATION and not the rule. SupportTicketPage::giveaway() refuses a
   submission that names no object however it arrives, so a browser without
   `:has()` gets a button that looks live and is told to choose an object, which
   is a worse experience and not a worse outcome. */
.giveaway__form:has(.giveaway__pick option[value=""]:checked) .giveaway__go {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}
