﻿/*
    Nixie's own chrome.

    Theming is driven by data-theme on <html>, set from the user's account rather than from the operating
    system, so the choice follows them between machines and matches what apps are told to render for. Every
    colour is a variable so the two themes differ in one place instead of being sprinkled through the rules.
*/

:root[data-theme="light"] {
    --nx-bg: #f4f5f7;
    --nx-surface: #ffffff;
    --nx-surface-2: #fafbfc;
    --nx-ink: #1f1f24;
    --nx-ink-soft: #5c6068;
    --nx-line: #e3e5e9;
    --nx-accent: #b6813c;
    --nx-accent-ink: #8a5f27;
    --nx-shadow: 0 1px 2px rgba(16, 18, 24, .06), 0 4px 12px rgba(16, 18, 24, .05);
}

:root[data-theme="dark"] {
    --nx-bg: #16171b;
    --nx-surface: #1f2027;
    --nx-surface-2: #24252d;
    --nx-ink: #f2f2f7;
    --nx-ink-soft: #9ba1ac;
    --nx-line: #32343d;
    --nx-accent: #d1a05a;
    --nx-accent-ink: #e0b876;
    --nx-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 4px 14px rgba(0, 0, 0, .3);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--nx-bg);
    color: var(--nx-ink);
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    font-size: 15px;
}

/* ---- Header ---- */

.nx-header {
    background: var(--nx-surface);
    border-bottom: 1px solid var(--nx-line);
    position: sticky;
    top: 0;
    z-index: 20;
}

.nx-header-inner {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 20px;
    height: 56px;
    display: flex;
    align-items: center;
    gap: 22px;
}

.nx-brand {
    font-weight: 650;
    font-size: 17px;
    color: var(--nx-ink);
    text-decoration: none;
    letter-spacing: .01em;
}

.nx-brand-mark { color: var(--nx-accent); margin-right: 3px; }

.nx-nav { display: flex; gap: 4px; flex: 1; }

.nx-nav-link {
    color: var(--nx-ink-soft);
    text-decoration: none;
    padding: 6px 12px;
    border-radius: 8px;
    font-size: 14px;
}

.nx-nav-link:hover { color: var(--nx-ink); background: var(--nx-surface-2); }

.nx-header-right { display: flex; align-items: center; gap: 12px; }
.nx-user { color: var(--nx-ink-soft); font-size: 13px; }
.nx-inline { display: inline; margin: 0; }

.nx-icon-btn {
    background: transparent;
    border: 1px solid var(--nx-line);
    color: var(--nx-ink);
    border-radius: 8px;
    width: 32px;
    height: 32px;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
}

.nx-icon-btn:hover { background: var(--nx-surface-2); }

/* ---- Layout ---- */

.nx-main { flex: 1; max-width: 1200px; width: 100%; margin: 0 auto; padding: 24px 20px 40px; }

/* An app page is a working surface, not reading matter: it takes the whole window width, with the same side
   gutter, so a graph editor or a live feed is not confined to a column with half the screen empty either side. */
.nx-main.nx-wide { max-width: none; padding: 16px 20px 24px; }

.nx-footer {
    border-top: 1px solid var(--nx-line);
    color: var(--nx-ink-soft);
    font-size: 12px;
    padding: 14px 20px;
    text-align: center;
}

.nx-footer a { color: var(--nx-ink-soft); }

.nx-page-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 18px;
}

.nx-page-head h1 { font-size: 22px; font-weight: 650; margin: 0; }
.nx-page-head p { color: var(--nx-ink-soft); font-size: 14px; margin: 4px 0 0; }

/* ---- Buttons ---- */

.nx-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border-radius: 9px;
    border: 1px solid var(--nx-line);
    background: var(--nx-surface);
    color: var(--nx-ink);
    font-size: 14px;
    cursor: pointer;
    text-decoration: none;
}

.nx-btn:hover { background: var(--nx-surface-2); color: var(--nx-ink); }
.nx-btn-primary { background: var(--nx-accent); border-color: var(--nx-accent); color: #fff; }
.nx-btn-primary:hover { background: var(--nx-accent-ink); border-color: var(--nx-accent-ink); color: #fff; }
.nx-btn-sm { padding: 4px 10px; font-size: 12.5px; }
.nx-btn-danger { border-color: rgba(200, 70, 70, .45); color: #c84646; }

/* ---- Cards and the widget grid ---- */

.nx-grid { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }

.nx-card {
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: 14px;
    box-shadow: var(--nx-shadow);
}

/* A dashboard widget IS its grid cell - no padding, and a shadow instead of a border, because a border would
   take two pixels out of the content box. That is what keeps a 250px widget exactly 250px wide in a one-cell
   column, and it is why Nixie's chrome overlays the widget rather than sitting above it: inset chrome is a
   constant that would get multiplied by the span, so a five-row widget would end up with a hundred-odd
   pixels of dead space. */
.nx-widget {
    position: relative;
    padding: 0;
    border: 0;
    overflow: hidden;
    box-shadow: 0 0 0 1px var(--nx-line), var(--nx-shadow);
}

.nx-widget iframe { display: block; width: 100%; height: 100%; border: 0; }

/* The veil covers a frame whose app is away; the live channel lifts it the moment content is pushed. It sits
   under the hover chrome, so the remove control stays reachable on a dead widget. */
.nx-widget-veil { position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 1; }
.nx-widget-bar { z-index: 2; }

/* The chrome sits over the widget and stays out of the way until wanted. It cannot be permanently visible:
   on a 50px-tall widget a persistent strip would eat a third of it. Attribution while idle comes from the
   app's own artwork; full-page mode keeps its always-visible header, which is where spoofing matters. */
.nx-widget-bar {
    position: absolute;
    top: 0; left: 0; right: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 3px 7px;
    z-index: 2;
    opacity: 0;
    transition: opacity .12s ease;
    background: linear-gradient(to bottom, var(--nx-surface) 55%, transparent);
}

.nx-widget:hover .nx-widget-bar,
.nx-widget:focus-within .nx-widget-bar { opacity: 1; }

.nx-widget-app { font-size: 11px; color: var(--nx-ink-soft); letter-spacing: .04em; text-transform: uppercase; }

/* ---- Dashboard board and grid ---- */

.nx-board-tabs { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }

.nx-board-tab {
    padding: 5px 13px;
    border-radius: 999px;
    border: 1px solid var(--nx-line);
    color: var(--nx-ink-soft);
    text-decoration: none;
    font-size: 13.5px;
    background: var(--nx-surface);
    cursor: pointer;
}

.nx-board-tab:hover { color: var(--nx-ink); }
.nx-board-tab.current { background: var(--nx-accent); border-color: var(--nx-accent); color: #fff; }
.nx-board-add { font-weight: 600; padding: 5px 11px; }

/* Items must stretch to fill the rows they span - this is what makes a 1-row widget 50px and a 5-row widget
   290px. With align-items:start they collapse to content height instead, the iframe's height:100% has no
   definite parent to resolve against, and every widget ends up the same default size regardless of its span. */
.nx-grid-board { display: grid; align-items: stretch; }

/* The handle is the app name. Dragging from anywhere else would fight the widget's own clicks. */
.nx-drag-handle { cursor: grab; user-select: none; }
.nx-drag-handle:active { cursor: grabbing; }

.nx-placed { overflow: hidden; }
.nx-dragging { opacity: .45; }

.nx-drop-ghost {
    border: 2px dashed var(--nx-accent);
    border-radius: 14px;
    background: rgba(182, 129, 60, .08);
    pointer-events: none;
}

.nx-widget-x {
    background: none;
    border: 0;
    color: var(--nx-ink-soft);
    font-size: 17px;
    line-height: 1;
    padding: 0 2px;
    cursor: pointer;
}

.nx-widget-x:hover { color: #c84646; }

.nx-widget-offline {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    height: 100%;
    color: var(--nx-ink-soft);
    font-size: 13px;
}

.nx-widget-offline small { font-size: 11px; opacity: .8; }

/* ---- Widget picker ---- */

.nx-widget-picker { position: relative; }

.nx-picker-menu {
    display: none;
    position: absolute;
    right: 0;
    top: 100%;
    margin-top: 4px;
    z-index: 30;
    min-width: 210px;
    padding: 6px;
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: 12px;
    box-shadow: var(--nx-shadow);
}

/* Hover or keyboard focus both open it, so it isn't mouse-only. */
.nx-widget-picker:hover .nx-picker-menu,
.nx-widget-picker:focus-within .nx-picker-menu { display: block; }

.nx-picker-group { padding: 4px 0; }
.nx-picker-group + .nx-picker-group { border-top: 1px solid var(--nx-line); }
.nx-picker-head { font-size: 12px; font-weight: 600; padding: 3px 8px; }
.nx-picker-dim { font-weight: 400; color: var(--nx-ink-soft); margin-left: 4px; }

.nx-picker-item {
    display: block;
    width: 100%;
    text-align: left;
    padding: 5px 8px;
    border: 0;
    border-radius: 7px;
    background: none;
    color: var(--nx-ink);
    font-size: 13px;
    cursor: pointer;
}

.nx-picker-item:hover { background: var(--nx-surface-2); }
.nx-picker-done { color: var(--nx-ink-soft); cursor: default; font-style: italic; }
.nx-picker-done:hover { background: none; }

/* ---- Instance list ---- */

.nx-list { display: flex; flex-direction: column; gap: 10px; }

.nx-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: 12px;
}

/* The instance the user just added, so it stands out in a list sorted by name. */
.nx-row-new { border-color: var(--nx-accent); box-shadow: 0 0 0 3px rgba(182, 129, 60, .22); }

.nx-row-main { flex: 1; min-width: 0; }
.nx-row-title { font-weight: 600; font-size: 15px; }
.nx-row-sub { color: var(--nx-ink-soft); font-size: 13px; margin-top: 2px; }
.nx-row-tools { display: flex; gap: 8px; align-items: center; }

.nx-tag {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 999px;
    border: 1px solid var(--nx-line);
    color: var(--nx-ink-soft);
}

.nx-tag-off { border-color: rgba(200, 70, 70, .4); color: #c84646; }

.nx-empty {
    text-align: center;
    padding: 48px 20px;
    color: var(--nx-ink-soft);
    border: 1px dashed var(--nx-line);
    border-radius: 14px;
}

/* ---- Add an app: the catalogue tiles ---- */

.nx-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 14px;
}

.nx-tile {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 16px;
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-radius: 14px;
    box-shadow: var(--nx-shadow);
    color: var(--nx-ink);
    cursor: pointer;
}

.nx-tile:hover, .nx-tile:focus-visible { border-color: var(--nx-accent); outline: none; }
.nx-tile-foot { margin-top: auto; padding-top: 10px; text-align: right; }

/* Bootstrap 5.1's card and muted text carry fixed light-theme colours (white background, grey text), so any
   page still using them follows the theme through these rather than drawing a white box in dark mode. */
.card { background-color: var(--nx-surface); color: var(--nx-ink); border-color: var(--nx-line); }
.card-footer, .card-header { background-color: transparent; border-color: var(--nx-line); }
.text-muted { color: var(--nx-ink-soft) !important; }

/* ---- Settings ---- */

.nx-settings { max-width: 720px; }
.nx-field { margin-bottom: 22px; }
.nx-field .nx-label { font-size: 13px; font-weight: 600; color: var(--nx-ink); margin-bottom: 8px; }
.nx-select { width: 100%; max-width: 560px; }
.nx-choices { display: flex; flex-direction: column; gap: 8px; }

.nx-choice {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border: 1px solid var(--nx-line);
    border-radius: 10px;
    background: var(--nx-surface);
    color: var(--nx-ink);
    cursor: pointer;
}

.nx-choice:hover { border-color: var(--nx-accent); }
.nx-choice input { margin: 0; accent-color: var(--nx-accent); }
.nx-choice-name { font-weight: 600; min-width: 64px; }
.nx-choice-hint { color: var(--nx-ink-soft); font-size: 13px; }
.nx-preview { margin-left: auto; color: var(--nx-ink-soft); font-variant-numeric: tabular-nums; white-space: nowrap; }
.nx-preview-line { padding: 10px 14px; border: 1px dashed var(--nx-line); border-radius: 10px; color: var(--nx-ink-soft); }

/* ---- Forms ---- */

.nx-input {
    padding: 7px 11px;
    border-radius: 9px;
    border: 1px solid var(--nx-line);
    background: var(--nx-surface);
    color: var(--nx-ink);
    font-size: 14px;
}

.nx-input:focus { outline: 2px solid var(--nx-accent); outline-offset: -1px; }
.nx-form-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* Where operationOutcome reports the result of an AJAX action.  Fixed and above the chrome, because the
   action that triggered it may have scrolled out of view by the time the answer arrives. */
.nx-notification {
    background: var(--nx-surface);
    border: 1px solid var(--nx-line);
    border-left: 3px solid var(--nx-accent);
    border-radius: 6px;
    box-shadow: var(--nx-shadow);
    color: var(--nx-ink);
    font-size: 13px;
    left: 50%;
    max-width: min(520px, calc(100vw - 32px));
    padding: 12px 16px;
    position: fixed;
    top: 16px;
    transform: translateX(-50%);
    white-space: pre-line;
    z-index: 1080;
}

/* ---- Automations: wiring one app's events to another app's actions ---- */

.nx-sub { color: var(--nx-ink-soft); font-size: 13px; margin: 2px 0 0; }
.nx-section { font-size: 15px; margin: 22px 0 10px; }
.nx-label { display: block; font-size: 12px; color: var(--nx-ink-soft); margin-bottom: 4px; }
.nx-dim { color: var(--nx-ink-soft); font-weight: 400; }
.nx-arrow { color: var(--nx-accent); margin: 0 6px; }

.nx-note {
    border: 1px solid var(--nx-line);
    border-left: 3px solid var(--nx-accent);
    border-radius: 8px;
    padding: 10px 14px;
    margin-bottom: 12px;
    font-size: 13px;
}
.nx-note-bad { border-left-color: #c84646; }
.nx-note-info { border-left-color: var(--nx-ink-soft); color: var(--nx-ink-soft); }

.nx-automation-form { padding: 16px; }
.nx-automation-row { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.nx-automation-side { flex: 1; min-width: 240px; display: flex; flex-direction: column; gap: 8px; }
.nx-automation-arrow { align-self: center; font-size: 20px; color: var(--nx-accent); }
.nx-automation-actions { margin-top: 14px; }

/* The consent surface: what crosses, and who can reach both ends. */
.nx-carries {
    margin-top: 14px;
    border-top: 1px solid var(--nx-line);
    padding-top: 12px;
    font-size: 13px;
}
.nx-carries-head { font-weight: 600; margin-bottom: 4px; }
.nx-carries-list { margin: 0 0 10px; padding-left: 20px; color: var(--nx-ink-soft); }
.nx-audience { margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--nx-line); }
.nx-automation-binding .nx-row-sub { margin-top: 3px; }
