html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    margin: 0;
    padding: 0;
    height: 100%;
    overflow: hidden; /* .wc-shell/.wc-main own their scroll — no outer page scrollbar */
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

/* ── "All Devices" shell (docs/dataflow.md — matches real UtiliCore's top bar +
   docked device-list panel look). Kept in this global app.css, NOT in per-component
   .razor.css files: this server runs `dotnet run` from source in Production mode
   (see deploy/run-web-task.ps1), which never serves the generated
   WaterCore.Web.styles.css bundle that isolated .razor.css relies on (confirmed the
   hard way — it 404s). Only physical wwwroot files like this one are served, so all
   "wc-*" component styling below has to live here instead. ── */

.wc-shell {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}

.wc-topbar {
    display: flex;
    align-items: center;
    height: 52px;
    flex: 0 0 auto;
    background: #00549f;
    color: #fff;
    padding: 0 1rem;
    box-shadow: 0 2px 6px rgba(0,0,0,.25);
    z-index: 20;
}

.wc-brand {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: 1.15rem;
    font-weight: 300;
    letter-spacing: .3px;
    margin-right: 1.5rem;
    white-space: nowrap;
}

.wc-brand strong {
    font-weight: 700;
}

.wc-brand-icon {
    font-size: 1.2rem;
}

.wc-topnav {
    display: flex;
    align-items: center;
    height: 100%;
    gap: .1rem;
    flex: 1 1 auto;
    /* NOT overflow-x:auto — per the CSS overflow spec, setting only one axis away from
       "visible" forces the OTHER axis to "auto" too, and the "Devices" dropdown (which is
       ~300px tall, absolutely positioned inside this 52px-tall bar) then counts as overflow
       content — that's exactly what put a scrollbar on the header. Only 4 short items here,
       no real need for horizontal scroll on desktop-width screens anyway. */
    overflow: visible;
}

.wc-topnav-item {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    height: 100%;
    padding: 0 .9rem;
    color: rgba(255,255,255,.9);
    text-decoration: none;
    font-size: .92rem;
    white-space: nowrap;
    border-bottom: 3px solid transparent;
}

.wc-topnav-item:hover {
    background: rgba(255,255,255,.08);
    color: #fff;
    text-decoration: none;
}

.wc-topnav-item.active {
    border-bottom-color: #fff;
    background: rgba(255,255,255,.08);
}

.wc-topnav-item.disabled {
    color: rgba(255,255,255,.45);
    cursor: default;
}

.wc-topnav-item.disabled:hover {
    background: transparent;
    color: rgba(255,255,255,.45);
}

.wc-caret {
    font-size: .65rem;
    opacity: .8;
}

/* "Devices" top-menu dropdown (docs/dataflow.md, mục "Alarms and Events") — real UtiliCore-style
   dropdown + 1-level flyout (Alerts > Alarms and Events...). A transparent full-screen overlay
   behind the menu closes it on outside click, without needing JS interop. */
.wc-topnav-item-dropdown {
    position: relative;
    height: 100%;
}

.wc-dropdown-overlay {
    position: fixed;
    inset: 0;
    z-index: 199;
    background: transparent;
}

.wc-dropdown-menu {
    position: absolute;
    top: 100%;
    left: 0;
    background: #fff;
    color: #222;
    min-width: 230px;
    box-shadow: 0 4px 16px rgba(0,0,0,.28);
    border-radius: 0 0 4px 4px;
    z-index: 200;
    padding: .25rem 0;
}

.wc-dropdown-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .5rem .9rem;
    font-size: .86rem;
    color: #222;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    position: relative;
}

.wc-dropdown-item:hover {
    background: #eef4fb;
    color: #222;
    text-decoration: none;
}

.wc-dropdown-item.disabled {
    color: #aaa;
    cursor: default;
}

.wc-dropdown-item.disabled:hover {
    background: transparent;
}

.wc-dropdown-arrow {
    font-size: .7rem;
    opacity: .6;
}

.wc-dropdown-flyout {
    position: absolute;
    top: -.25rem;
    left: 100%;
    background: #fff;
    min-width: 230px;
    box-shadow: 0 4px 16px rgba(0,0,0,.28);
    border-radius: 4px;
    z-index: 201;
    padding: .25rem 0;
}


.wc-topbar-right {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex: 0 0 auto;
    margin-left: auto;
}

.wc-icon-btn {
    background: transparent;
    border: none;
    color: #fff;
    font-size: 1rem;
    line-height: 1;
    padding: .4rem .5rem;
    border-radius: 4px;
    cursor: pointer;
}

.wc-icon-btn:hover {
    background: rgba(255,255,255,.12);
}

.wc-user {
    display: flex;
    align-items: center;
    gap: .35rem;
    padding: .3rem .6rem;
    border-radius: 4px;
    font-size: .92rem;
    cursor: default;
}

.wc-user:hover {
    background: rgba(255,255,255,.1);
}

.wc-main {
    position: relative;
    flex: 1 1 auto;
    overflow: auto;
    background:
        radial-gradient(ellipse at 30% 20%, #e9ecef 0%, #dcdfe2 55%, #cfd3d6 100%);
}

.wc-map-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.wc-map-caption {
    color: #9aa1a7;
    font-size: 1.1rem;
    font-weight: 300;
    letter-spacing: .5px;
}

.wc-version-tag {
    position: absolute;
    left: 1rem;
    bottom: .6rem;
    color: #9aa1a7;
    font-size: .8rem;
}

.wc-panel {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    bottom: 0.75rem;
    width: min(46rem, calc(100vw - 1.5rem));
    background: #fff;
    border-radius: 4px;
    box-shadow: 0 4px 18px rgba(0,0,0,.28);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    z-index: 10;
}

/* Docked to the LEFT instead — sits beside "All Devices" without touching _sites/LoadAsync at
   all (pure component state), so opening/closing it never reloads the site list. */
.wc-values-panel {
    left: 0.75rem;
    right: auto;
    width: min(46rem, calc(55vw));
    z-index: 15;
}

/* All the "Devices" top-menu report popups (Alarms and Events, Manage Device Faults, ...) —
   stretch to fill the gap right up to "All Devices"'s left edge (left+right set, no width, so
   the browser computes it) instead of a fixed width, matching the real UtiliCore layout where
   the two panels sit snugly side by side with no horizontal scrollbar (2026-09-01: same size for
   every menu popup, not just Alarms — per the user's instruction). */
.wc-menu-popup-panel {
    width: auto !important;
    right: calc(1.5rem + min(46rem, calc(100vw - 1.5rem))) !important;
}

.wc-panel-header {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .65rem .9rem;
    background: #00549f;
    border-bottom: 1px solid #003d75;
    flex: 0 0 auto;
}

.wc-panel-header-icon {
    color: #fff;
}

.wc-panel-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: #fff;
    flex: 1 1 auto;
}

.wc-panel-header-actions {
    display: flex;
    gap: .3rem;
}

.wc-icon-btn-flat {
    background: transparent;
    border: none;
    color: rgba(255,255,255,.85);
    font-size: .95rem;
    padding: .2rem .4rem;
    border-radius: 3px;
    cursor: not-allowed;
}

.wc-icon-btn-flat:not(:disabled) {
    cursor: pointer;
}

.wc-icon-btn-flat:not(:disabled):hover {
    background: rgba(255,255,255,.15);
    color: #fff;
}

.wc-toolbar {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .9rem;
    border-bottom: 1px solid #e1e4e6;
    flex-wrap: wrap;
    flex: 0 0 auto;
}

.wc-search-box {
    display: flex;
    align-items: center;
    gap: .4rem;
    border: 1px solid #ccd1d4;
    border-radius: 3px;
    padding: .3rem .55rem;
    flex: 1 1 12rem;
    min-width: 9rem;
}

.wc-search-box input {
    border: none;
    outline: none;
    flex: 1 1 auto;
    font-size: .9rem;
    min-width: 0;
}

.wc-search-icon {
    color: #8a9198;
    font-size: .85rem;
}

.wc-add-btn {
    flex: 0 0 auto;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 3px;
    border: none;
    background: #00549f;
    color: #fff;
    font-size: 1.1rem;
    line-height: 1;
    cursor: not-allowed;
    opacity: .6;
}

.wc-count {
    flex: 0 0 auto;
    font-size: .85rem;
    color: #5a6167;
    white-space: nowrap;
}

.wc-filter-select {
    flex: 0 0 auto;
    font-size: .85rem;
    padding: .3rem .4rem;
    border: 1px solid #ccd1d4;
    border-radius: 3px;
    background: #fff;
    color: #5a6167;
}

.wc-table-wrap {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: auto;
    position: relative;
}

.wc-table {
    width: 100%;
    border-collapse: collapse;
    font-size: .88rem;
}

.wc-table thead th {
    position: sticky;
    top: 0;
    background: #00549f;
    text-align: left;
    padding: .5rem .9rem;
    font-weight: 600;
    color: #fff;
    border-bottom: 1px solid #003d75;
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.wc-table thead th:hover {
    background: #003d75;
}

/* Values popup's column headers aren't sortable — no pointer cursor/hover darkening — and wrap
   the channel label onto 2 lines (Measurand / "siteId_channel unit"), matching the real
   UtiliCore Values grid's header format. */
.wc-values-table thead th {
    cursor: default;
    white-space: normal;
    line-height: 1.25;
}

.wc-values-table thead th:hover {
    background: #00549f;
}

.wc-values-table thead th span {
    display: block;
}

.wc-values-table thead th span:last-child {
    font-weight: 400;
    font-size: .78rem;
    opacity: .9;
}

.wc-table tbody td {
    padding: .5rem .9rem;
    border-bottom: 1px solid #edf0f1;
    color: #2b3338;
    vertical-align: middle;
}

.wc-row {
    cursor: pointer;
}

.wc-row:hover {
    background: #eef5fb;
}

.wc-status-cell {
    white-space: nowrap;
}

.wc-status-icon {
    display: inline-block;
    margin-right: .5rem;
    opacity: .55;
    filter: grayscale(60%);
}

.wc-status-on {
    opacity: 1;
    filter: none;
}

/* Real UtiliCore renders this bell via a custom icon font (font-family: UtiliCoreSymbols — a
   letter glyph mapped to a bell shape, confirmed straight from their own devtools) so a plain
   `color: red` just works. We don't have that font, but the same principle applies with an inline
   SVG instead of a color emoji: `fill: currentColor` lets `color` recolor it normally, no filter
   hacks needed (an earlier version of this used brightness/invert on an emoji — replaced). */
.wc-bell-svg {
    width: .8em;
    height: .8em;
    fill: currentColor;
    vertical-align: -.05em;
}

/* Same "double size inside expand" rule already applied to the comms icon (.wc-icon-img-lg). */
.wc-bell-svg-lg {
    width: 1.6em;
    height: 1.6em;
}

/* Real icons downloaded from cello.viwater.vn (docs/dataflow.md) — used as-is, not an emoji/CSS
   dot, so they render identically everywhere instead of varying per OS/browser or looking like a
   cheap stand-in. CommsList.png turned out to be a 2-frame sprite (white icon for the "active"/
   blue-background state, black icon for "inactive") — cropped into CommsList-active.png/
   CommsList-inactive.png, one real asset per state instead of a single icon plus a CSS filter.
   Indexes.png/Indexes-lg.png were the same trick (2-frame sprite, white left half + black right
   half) — only the white half is used (icon always sits on the blue .wc-expand-icon background,
   no "inactive" state needed), cropped down to a single real asset the same way. */
.wc-icon-img {
    width: 1rem;
    height: 1rem;
    vertical-align: -.15rem;
    object-fit: contain;
}

/* Expand panel is double the list's icon size (still inside the same 2rem .wc-expand-icon box). */
.wc-icon-img-lg {
    width: 2rem;
    height: 2rem;
    object-fit: contain;
}

/* Small, understated comms indicator in the site-list row — a colored circle (matching the
   alarm-bell badge's size/shape) rather than a full-size icon, to stay visually quiet next to the
   other plain-emoji status icons in that cell. */
.wc-comms-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.2rem;
    height: 1.2rem;
    border-radius: 50%;
}

.wc-comms-dot-on {
    background: #00549f;
}

.wc-comms-dot-off {
    background: #b0bec5;
}

.wc-alarm-bell {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.2rem;
    height: 1.2rem;
    border-radius: 50%;
    background: #d32f2f;
    color: #fff;
    opacity: 1;
    filter: none;
}

/* Resets <button> defaults for the status-cell alarm bell (it's a button now, not a bare span —
   needs to open the Alarms popup — but should still look identical to the other plain-emoji
   status icons in that cell). */
.wc-bell-btn {
    appearance: none;
    -webkit-appearance: none;
    border: none;
    padding: 0;
    margin-right: .5rem;
    font-family: inherit;
    cursor: pointer;
}

/* Inside the expand panel, alarm reuses the same blue action-icon box shape — just recolored. */
.wc-expand-icon.wc-alarm-bell {
    background: #d32f2f;
    border-radius: 4px;
    width: 2rem;
    height: 2rem;
    font-size: 1rem;
}

.wc-status-off {
    opacity: .35;
    filter: grayscale(100%);
}

.wc-loading {
    text-align: center;
    padding: 1rem;
    color: #8a9198;
    font-size: .88rem;
}

.wc-load-more {
    display: block;
    width: 100%;
    padding: .6rem;
    border: none;
    background: #f4f6f7;
    color: #00549f;
    font-size: .85rem;
    cursor: pointer;
    border-top: 1px solid #e1e4e6;
}

.wc-load-more:hover {
    background: #eef5fb;
}

.wc-row-active {
    background: #eaf2fa;
}

.wc-expand-row td {
    padding: 0 !important;
    background: #f7f9fa;
    border-bottom: 1px solid #e1e4e6;
    cursor: default;
}

.wc-expand-panel {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .8rem 1rem;
}

.wc-expand-image {
    width: 64px;
    height: 64px;
    object-fit: contain;
    flex: 0 0 auto;
}

.wc-expand-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

/* Action icons (⚙️ config, 🔢 values, 📈 detail) — always solid blue/white, whether they're an
   <a> or a <button>. Status icons (📷 has-photos, 📶 active) reuse the plain .wc-status-on/
   .wc-status-off classes for their dim/bright state — see below, this base rule intentionally
   sets no opacity/filter so it never fights with those. */
.wc-expand-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: none;
    border-radius: 4px;
    background: #00549f;
    color: #fff;
    font-size: 1rem;
    line-height: 1;
    padding: 0;
    margin: 0;
    font-family: inherit;
    appearance: none;
    text-decoration: none;
    cursor: pointer;
}

.wc-expand-icon:hover {
    background: #003d75;
    color: #fff;
}

.wc-expand-icon-disabled {
    opacity: .3;
    filter: grayscale(100%);
    background: #b7bfc5;
    cursor: default;
}

.wc-expand-icon-disabled:hover {
    background: #b7bfc5;
}

/* Mimics the real Technolog icon's 2-row stacked-text format (e.g. its "123/124" channel-count
   badge) for the Values button, instead of a flat single-line emoji. */
.wc-expand-icon-2line {
    flex-direction: column;
    justify-content: center;
    line-height: 1;
    gap: 1px;
}

.wc-expand-icon-2line span {
    font-size: .6rem;
    font-weight: 700;
}

.wc-expand-badge {
    display: inline-flex;
    align-items: center;
    padding: 0 .5rem;
    height: 2rem;
    border-radius: 4px;
    background: #00549f;
    color: #fff;
    font-size: .8rem;
    font-weight: 600;
}

.wc-page {
    max-width: 1100px;
    margin: 0 auto;
    padding: 1.25rem 1.5rem 3rem;
    background: #fff;
    min-height: 100%;
    box-shadow: 0 0 12px rgba(0,0,0,.08);
}

/* "Logger Settings" popup — tab bar matches the real one's look, but only General is wired up
   (docs/dataflow.md) — the rest link out to the existing full detail page, which already has that
   logic, instead of a half-built duplicate here. */
.wc-settings-tabs {
    display: flex;
    gap: .3rem;
    padding: .6rem .9rem;
    border-bottom: 1px solid #e1e4e6;
    flex-wrap: wrap;
}

.wc-settings-tab {
    border: none;
    background: #00549f;
    color: #fff;
    padding: .35rem .8rem;
    border-radius: 3px;
    font-size: .82rem;
    text-decoration: none;
    cursor: pointer;
}

.wc-settings-tab:hover {
    background: #003d75;
    color: #fff;
    text-decoration: none;
}

.wc-settings-tab.active {
    background: #fff;
    color: #00549f;
    border: 1px solid #00549f;
    font-weight: 700;
    cursor: default;
}

.wc-settings-body {
    padding: .9rem;
    overflow-y: auto;
}

.wc-settings-info {
    display: flex;
    align-items: center;
    gap: 1rem;
    background: #f4f6f7;
    border-radius: 4px;
    padding: .7rem .9rem;
    margin-bottom: .9rem;
}

.wc-settings-device-img {
    width: 56px;
    height: 56px;
    object-fit: contain;
    flex: 0 0 auto;
}

.wc-settings-info-text {
    font-size: .85rem;
    color: #2b3338;
    line-height: 1.5;
}

.wc-settings-fields {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .8rem 1.2rem;
    margin-bottom: 1rem;
}

.wc-settings-fields label {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    font-size: .82rem;
    color: #5a6167;
    font-weight: 600;
}

.wc-settings-fields input {
    font-size: .9rem;
    font-weight: 400;
    color: #2b3338;
    padding: .4rem .55rem;
    border: 1px solid #ccd1d4;
    border-radius: 3px;
}

.wc-settings-fields input:disabled {
    background: #f4f6f7;
    color: #8a9198;
}

.wc-settings-actions {
    display: flex;
    gap: .6rem;
    justify-content: center;
    padding-top: .5rem;
    border-top: 1px solid #e1e4e6;
}

.wc-settings-btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    border: none;
    background: #00549f;
    color: #fff;
    padding: .5rem 1.1rem;
    border-radius: 3px;
    font-size: .88rem;
    cursor: pointer;
}

.wc-settings-btn:hover:not(:disabled) {
    background: #003d75;
}

.wc-settings-btn:disabled {
    background: #b0bec5;
    cursor: not-allowed;
}

/* Logger Settings > Channel tab (Ln. Colour/Ln. Type) — see LineColourPalette's doc comment for
   where these hues came from. No wc-table-wrap here (unlike every other popup table): the colour
   popover is position:fixed (see .wc-colour-popover below), so it doesn't need a scroll container
   to escape into — it's not a descendant of any scrollable box's layout at all. */
.wc-channel-table td, .wc-channel-table th {
    text-align: center;
}
.wc-channel-table td:nth-child(2), .wc-channel-table th:nth-child(2) {
    text-align: left;
}
.wc-colour-picker {
    position: relative;
    display: inline-flex;
}
.wc-colour-swatch-btn {
    width: 2.6rem;
    height: 1.9rem;
    border-radius: 2px;
    border: 1px solid rgba(0, 0, 0, .3);
    padding: 0;
    cursor: pointer;
}
.wc-colour-swatch-btn:hover {
    border-color: rgba(0, 0, 0, .55);
}
/* Popover of plain colour swatches — no numbers/labels, matching the real UtiliCore picker's own
   swatch-only dropdown (jsLineOptions) rather than a native <select> showing the palette index. A
   single vertical column, each swatch the same size as the closed display block — a real
   dropdown list of colours, not a small grid of dots.
   position:fixed with top/left set inline from real getBoundingClientRect() coordinates (see
   Home.razor's ToggleColourPicker + wwwroot/js/colourPicker.js) — NOT position:absolute anchored
   to the table cell. That approach fought wc-table's sticky header (badly misplaced popover) and,
   being inside wc-settings-body's normal flow, could inflate that flex child's content height
   past the fixed-size wc-panel, forcing the whole page to scroll. A fixed-position element is
   removed from layout entirely — it can't do either of those things. */
.wc-colour-popover {
    position: fixed;
    z-index: 30;
    display: flex;
    flex-direction: column;
    gap: .3rem;
    background: #fff;
    border: 1px solid #cfd6da;
    border-radius: 4px;
    padding: .4rem;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
    max-height: min(60vh, 20rem);
    overflow-y: auto;
}
.wc-colour-swatch-opt {
    width: 2.6rem;
    height: 1.9rem;
    border-radius: 2px;
    border: 1px solid rgba(0, 0, 0, .2);
    padding: 0;
    cursor: pointer;
}
.wc-colour-swatch-opt:hover {
    transform: scale(1.12);
}
.wc-colour-swatch-opt.selected {
    outline: 2px solid #00549f;
    outline-offset: 1px;
}
.wc-channel-table select {
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .15rem .3rem;
    font-size: .85rem;
    background: #fff;
}

/* Logging tab — "Global Logging Parameters"/"Configure Channel" boxes. Plain <fieldset>/<legend>
   gives the bordered-box-with-inset-title look from the real screenshot for free. */
.wc-logging-fieldset {
    border: 1px solid #dde2e5;
    border-radius: 4px;
    padding: 1rem 1.2rem;
    margin: 0 0 1rem;
}
.wc-logging-fieldset legend {
    padding: 0 .5rem;
    font-size: .82rem;
    font-weight: 600;
    color: #37474f;
    display: flex;
    align-items: center;
    gap: .6rem;
    width: auto;
}
.wc-logging-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: .7rem;
}
.wc-logging-row:last-child {
    margin-bottom: 0;
}
.wc-logging-row label {
    width: 130px;
    flex-shrink: 0;
    color: #37474f;
}
/* A checkbox+its own text (e.g. "Regular Send Settings", "Enable Clock Synchronisation") isn't a
   field label prefix like the others — don't clip it to the fixed 130px width. */
.wc-logging-row label.wc-checkbox-label {
    width: auto;
    display: flex;
    align-items: center;
    gap: .5rem;
}
/* Browsers give checkbox inputs a small default margin — left unreset, that nudges the checkbox
   a few px right of x=0, throwing off its alignment against the label text of the rows below it
   (e.g. "Frequency:"), which have no such margin. */
.wc-logging-row label.wc-checkbox-label input[type="checkbox"] {
    margin: 0;
}
.wc-logging-row select, .wc-logging-row input {
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .35rem .5rem;
    font-size: .88rem;
    min-width: 12rem;
}
.wc-logging-row input:disabled, .wc-logging-row select:disabled {
    background: #f4f6f7;
    color: #607076;
}
.wc-logging-channel-select {
    font-weight: 400;
    font-size: .85rem;
    padding: .25rem .5rem;
    border: 1px solid #cfd6da;
    border-radius: 3px;
}

/* Alarms tab — one editable High/Low pair per channel row, ONE shared Update button below the
   table (see SaveAlarmsAsync's doc comment for why it can't be per-row: the real backend only
   allows one alarm-category Request in flight per SITE at a time). table-layout:fixed + explicit
   widths keep High/Low/their unit labels lined up column-to-column across every row. */
.wc-alarms-table {
    table-layout: fixed;
}
.wc-alarms-table th:first-child, .wc-alarms-table td:first-child {
    width: 40%;
    text-align: left;
}
.wc-alarms-table th:not(:first-child), .wc-alarms-table td:not(:first-child) {
    width: 30%;
    text-align: center;
}
.wc-alarm-value-cell {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: .35rem;
    width: 100%;
}
.wc-alarm-value-cell input {
    width: 6rem;
    flex-shrink: 0;
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .25rem .4rem;
    font-size: .85rem;
    text-align: right;
}
.wc-alarm-value-cell span {
    width: 3.5rem;
    flex-shrink: 0;
    text-align: left;
    color: #607076;
    font-size: .82rem;
}
.wc-alarm-value-cell input:disabled {
    background: #f4f6f7;
    color: #607076;
}
.wc-alarm-sending-tag {
    margin-left: .5rem;
    color: #00549f;
    font-size: .78rem;
    font-style: italic;
}

/* Dialout tab — top row: LEFT = "Regular Send Settings" (taller, 4 rows), RIGHT = a vertical
   stack of "Sub-daily data send" + "Regular Listen for Messages" (each 1 row) — deliberately NOT
   a plain 2x2 grid since the right column's 2 boxes together are still shorter than the left.
   Weekly Clock Sync and General Settings both then span the full width below, each their own row. */
.wc-dialout-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    margin-bottom: 1rem;
    align-items: stretch;
    min-width: 0;
}
.wc-dialout-grid > * {
    min-width: 0;
    overflow-x: hidden;
}
.wc-dialout-grid > fieldset {
    margin-bottom: 0;
}
.wc-dialout-stack {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-width: 0;
}
.wc-dialout-stack fieldset {
    margin-bottom: 0;
    flex: 1;
}
.wc-dialout-clocksync-row {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    margin-bottom: .7rem;
}
.wc-dialout-clocksync-row label {
    color: #37474f;
}
.wc-dialout-clocksync-row input:not([type="checkbox"]) {
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .35rem .5rem;
    font-size: .88rem;
    flex: 1;
}
/* Narrower half-width fieldsets in .wc-dialout-grid (Regular Send Settings/Sub-daily) are too
   tight for the default 130px label + 12rem-min select — that's what overflowed into the other
   column originally. Note: the checkbox row ("Regular Send Settings") does NOT use .wc-logging-row
   at all any more (see .wc-dialout-clocksync-row reused for it below) — that sidesteps all of
   this entirely, matching how "Weekly Clock Synchronisation" always worked correctly. */
.wc-dialout-grid .wc-logging-row {
    flex-wrap: wrap;
}
.wc-dialout-grid .wc-logging-row label {
    width: 100px;
}
.wc-dialout-grid .wc-logging-row select,
.wc-dialout-grid .wc-logging-row input:not([type="checkbox"]) {
    min-width: 0;
    flex: 1;
}

/* General Settings' 2-column split (kept — needed to keep the popup's total height down, not
   just cosmetic) — label ABOVE its select/stacked block layout inside each column, deliberately
   NOT the label-beside-select .wc-logging-row pattern, which has repeatedly overflowed in a
   narrow column (a select's min-content is wider than half this panel). flex:1 1 0 + min-width:0
   forces both columns to actually respect their share of the width regardless of content. */
.wc-dialout-2col {
    display: flex;
    gap: 1.5rem;
}
.wc-dialout-2col > * {
    flex: 1 1 0;
    min-width: 0;
}
.wc-dialout-2col-field {
    margin-bottom: .7rem;
}
.wc-dialout-2col-field label {
    display: block;
    margin-bottom: .25rem;
    color: #37474f;
    font-size: .85rem;
}
.wc-dialout-2col-field select {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .35rem .5rem;
    font-size: .88rem;
}
.wc-dialout-2col-field select:disabled {
    background: #f4f6f7;
    color: #607076;
}
/* General Settings' checkbox list — one full-width-of-its-column row per checkbox. */
.wc-dialout-checkboxes {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}
.wc-dialout-checkboxes label {
    display: flex;
    align-items: center;
    gap: .5rem;
    color: #37474f;
    cursor: default;
}
.wc-dialout-checkboxes input[type="checkbox"]:not(:disabled) {
    cursor: pointer;
}

/* "Cancel Remote" — a real destructive action, styled distinctly from the blue action buttons
   everywhere else (docs/dataflow.md: this only writes StatusID=7 via the real SetRequestStatus
   stored procedure, same as the rest — but visually it needs to read as "stop this", not just
   another blue button, hence the earlier ad-hoc reuse of .wc-load-more looking so out of place). */
.wc-cancel-btn {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    border: 1px solid #c62828;
    background: #fff;
    color: #c62828;
    padding: .35rem .9rem;
    border-radius: 3px;
    font-size: .82rem;
    font-weight: 600;
    cursor: pointer;
}

.wc-cancel-btn:hover:not(:disabled) {
    background: #c62828;
    color: #fff;
}

.wc-cancel-btn:disabled {
    border-color: #ccd1d4;
    color: #b0bec5;
    background: #fff;
    cursor: not-allowed;
}

/* Row highlight for a Request that's genuinely "sent, awaiting device ack" (docs/dataflow.md —
   confirmed via a real screenshot: only rows with an outstanding un-acked step get this, not
   every non-terminal StatusID). */
.wc-row-inflight {
    background: #fbdcda;
}

.wc-row-inflight:hover {
    background: #f8c9c6;
}

/* Sub-row for the request-history popup's expanded Step/Sent/Ack detail — needs to read as
   "belongs to the row right above it", not a disconnected grey block (the site-list's device
   panel expand — .wc-expand-row — already looks fine floating full-width since it IS its own
   distinct panel; this one is genuinely a child of one specific table row, hence the accent
   border + indent + explicit "↳ Chi tiết ..." label tying it back). */
.wc-subrow td {
    padding: 0 !important;
    background: #f7f9fa;
    border-bottom: 1px solid #e1e4e6;
    cursor: default;
}

.wc-subrow-inner {
    border-left: 4px solid #00549f;
    margin-left: .75rem;
    padding: .5rem .75rem .5rem 1rem;
}

.wc-subrow.wc-subrow-inflight .wc-subrow-inner {
    border-left-color: #c62828;
}

/* Sub-table headers (Step/Sent Time/Acknowledged) stay grey/black — a lesser visual weight than
   the main blue table headers, so a nested table never looks like its own separate primary grid. */
.wc-subrow-inner .wc-table thead th {
    background: #eceff1;
    color: #2b3338;
    cursor: default;
}

/* ── Power tab (Backup Cell / Internal Pack gauges + trend) ──
   Layout/colors are inlined directly on the elements in Home.razor rather than via classes here —
   an earlier class-based version rendered broken (CSS not taking effect on these specific SVG/flex
   elements for reasons that didn't reproduce anywhere else in the app; not worth chasing further
   when inlining is just as maintainable for a single-use tab and guaranteed to render correctly
   regardless of any cascade/caching mystery). Only the one class actually still used remains. */
.wc-power-empty {
    padding: 1rem;
    color: #5c6b73;
    text-align: center;
}

/* Compact blue-square/white-icon action buttons inside a table row (the real "Manage Device
   Faults" report's "Action Options" column, e.g. Start Logging/Delete) — same white-icon-on-blue
   look as .wc-expand-icon, just sized down for a table cell instead of the expand panel's toolbar. */
.wc-row-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    background: #00549f;
    border: none;
    border-radius: 4px;
    padding: 0;
    margin-right: .3rem;
    cursor: pointer;
}

.wc-row-icon-btn:hover:not(:disabled) {
    background: #006bb7;
}

.wc-row-icon-btn:disabled {
    background: #a9bfd1;
    cursor: default;
}

.wc-row-icon-btn img {
    width: 1rem;
    height: 1rem;
}

/* Cello6 "IP" tab (Logger Settings) — a real 2-column grid (NOT the reused .wc-logging-row/
   .wc-dialout-2col-field combo from the first attempt, which fought each other: one wants a fixed
   130px label + flex row, the other wants a stacked block label — together they produced an
   uneven, cramped result). Each column gets equal width via grid, with its own inline label. */
.wc-ip-2col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .7rem 1.5rem;
}
.wc-ip-field {
    display: flex;
    align-items: center;
    gap: .6rem;
    min-width: 0;
}
.wc-ip-field label {
    flex-shrink: 0;
    color: #37474f;
}
.wc-ip-field input {
    flex: 1 1 auto;
    min-width: 0;
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .35rem .5rem;
    font-size: .88rem;
}
.wc-ip-field input:disabled {
    background: #f4f6f7;
    color: #607076;
}

/* Login.razor — dedicated classes (not reused/mismatched from elsewhere, per the earlier
   Cello6-IP-tab lesson: write the exact layout needed rather than repurposing a class that
   almost-but-not-quite fits). */
.wc-login-shell {
    display: flex;
    flex-direction: column;
    height: 100vh;
}
.wc-login-topbar {
    display: flex;
    align-items: center;
    gap: .4rem;
    height: 52px;
    flex: 0 0 auto;
    background: #00549f;
    color: #fff;
    padding: 0 1rem;
    box-shadow: 0 2px 6px rgba(0,0,0,.25);
    font-size: 1.15rem;
    font-weight: 300;
}
.wc-login-center {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(#e9edef, #f7f8f9);
}
.wc-login-card {
    width: 22rem;
    max-width: calc(100vw - 2rem);
    background: #fff;
    border-radius: 4px;
    box-shadow: 0 4px 18px rgba(0,0,0,.18);
    overflow: hidden;
}
.wc-login-card-header {
    background: #00549f;
    color: #fff;
    font-size: 1.05rem;
    padding: .75rem 1.1rem;
}
.wc-login-form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.5rem 1.1rem;
}
.wc-login-label {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    font-size: .85rem;
    color: #37474f;
}
.wc-login-input {
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .5rem .6rem;
    font-size: .95rem;
}
.wc-login-input:focus {
    outline: none;
    border-color: #00549f;
    box-shadow: 0 0 0 2px rgba(0,84,159,.15);
}
.wc-login-submit {
    background: #00549f;
    color: #fff;
    border: none;
    border-radius: 3px;
    padding: .6rem 1rem;
    font-size: .95rem;
    cursor: pointer;
}
.wc-login-submit:hover {
    background: #003f7a;
}
.wc-login-error {
    background: #fdecea;
    color: #b71c1c;
    border: 1px solid #f5c6cb;
    border-radius: 3px;
    padding: .5rem .7rem;
    font-size: .85rem;
}

/* "Administration > User Administration..." popup (MainLayout.razor) — direct child of
   .wc-panel (flex column, see line ~299), so flex:1 1 auto here fills the remaining height
   below .wc-panel-header exactly like the other popups' toolbar/table content does. */
.wc-useradmin-body {
    display: grid;
    grid-template-columns: 20rem 1fr;
    gap: 1rem;
    flex: 1 1 auto;
    min-height: 0;
    padding: .75rem;
}
.wc-useradmin-list {
    overflow-y: auto;
    border: 1px solid #dde3e6;
    border-radius: 4px;
    padding: .5rem;
    background: #fff;
}
.wc-useradmin-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .5rem .4rem;
    border-radius: 3px;
    cursor: pointer;
    font-size: .88rem;
}
.wc-useradmin-row:hover {
    background: #f4f6f7;
}
.wc-useradmin-row.selected {
    background: #e3f0fb;
}
.wc-useradmin-row-sub {
    color: #78909c;
    font-size: .78rem;
}
.wc-useradmin-badge {
    font-size: .72rem;
    padding: .15rem .4rem;
    border-radius: 3px;
    white-space: nowrap;
}
.wc-useradmin-badge.on {
    background: #e1f5e5;
    color: #1e7d32;
}
.wc-useradmin-badge.off {
    background: #f0f2f3;
    color: #90a4ae;
}
.wc-useradmin-detail {
    overflow-y: auto;
    border: 1px solid #dde3e6;
    border-radius: 4px;
    padding: 1rem;
    background: #fff;
}

/* License.razor — dedicated classes, layout tham khảo trang License thật của viwater (ảnh user
   gửi 2026-09-03), không tái dùng nhầm class của trang khác. */
/* Sống trong popup (.wc-panel, flex column, overflow:hidden — xem dòng ~299) chứ không phải 1
   trang riêng nữa (user: "nên show trang này trong main như các menu khác nhen") — .wc-panel-header
   đã có sẵn icon/title/nút Tải lại/Đóng, nên chỉ còn phần nội dung cuộn được bên dưới. */
.wc-lic-shell {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 1rem 1.2rem 1.5rem;
}

.wc-lic-card {
    background: #fff;
    border: 1px solid #dde3e6;
    border-radius: 6px;
    padding: 1.1rem 1.2rem;
    margin-bottom: 1rem;
}
.wc-lic-card-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .9rem;
}
.wc-lic-card-title { font-weight: 600; color: #263238; }
.wc-lic-badge {
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .03em;
    padding: .3rem .8rem;
    border-radius: 20px;
    color: #fff;
}
.wc-lic-badge-active { background: #00549f; }
.wc-lic-badge-expired { background: #c62828; }
.wc-lic-badge-missing { background: #78909c; }

.wc-lic-field {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .3rem 0;
    font-size: .9rem;
    color: #37474f;
}
.wc-lic-field-label { color: #78909c; }
.wc-lic-field-value { font-weight: 600; color: #263238; }
.wc-lic-mono { font-family: 'Consolas', 'Courier New', monospace; font-size: .82rem; word-break: break-all; }
.wc-lic-detail-link { margin-left: .4rem; font-size: .82rem; }

.wc-lic-modules {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    padding: .5rem 0 .3rem 1.6rem;
}
.wc-lic-module-chip {
    background: #eceff1;
    color: #37474f;
    font-size: .78rem;
    padding: .2rem .6rem;
    border-radius: 12px;
}

.wc-lic-progress-track {
    height: 6px;
    background: #eceff1;
    border-radius: 4px;
    margin-top: .7rem;
    overflow: hidden;
}
.wc-lic-progress-fill { height: 100%; background: #00549f; }
.wc-lic-progress-fill.expired { background: #c62828; }
.wc-lic-progress-label { font-size: .78rem; color: #78909c; margin-top: .3rem; }

.wc-lic-divider {
    text-align: center;
    color: #90a4ae;
    font-size: .8rem;
    margin: 1.2rem 0;
    position: relative;
}
.wc-lic-divider::before, .wc-lic-divider::after {
    content: "";
    position: absolute;
    top: 50%;
    width: 40%;
    border-top: 1px solid #dde3e6;
}
.wc-lic-divider::before { left: 0; }
.wc-lic-divider::after { right: 0; }

.wc-lic-provider-name { font-weight: 600; color: #263238; margin-bottom: .5rem; }

.wc-lic-activate-btn {
    display: block;
    width: 100%;
    background: #3f51b5;
    color: #fff;
    border: none;
    border-radius: 4px;
    padding: .7rem;
    font-size: .92rem;
    cursor: pointer;
}
.wc-lic-activate-btn:hover { background: #303f9f; }

.wc-lic-textarea {
    width: 100%;
    border: 1px solid #cfd6da;
    border-radius: 3px;
    padding: .5rem .6rem;
    font-family: 'Consolas', 'Courier New', monospace;
    font-size: .8rem;
    resize: vertical;
}
