:root {
    --vh: 100vh; /* Fallback for browsers that do not support env() */
    --vh: calc(var(--vh-safe-area-inset-bottom, 0px) + 100vh - env(safe-area-inset-bottom));

    /* background: var(--bg-window); */

    /* --bg-window: #F3F4F6; */
    --bg-toolbar: #ccc;
    /* --bg-core: white; */
    --bg-core: #F3F4F6;
    --bg-active: #dde1e5;
    --bg-hover: #cdcfd2;

    --text-primary: #333;
    --text-secondary: #666;
    --text-error: #ff0000;
    --text-success: #008000;
    --text-notice: #333;

    --text-menubar-primary: #F7F7F7;
    --text-menubar-secondary: #BBC9DA;

    --text-secondary-breadcrumb: #666;

    --text-patient-id: #800080;

    --text-message-core: #343434;
    --text-message-core-self: #ffffff;
    --text-message-author: rgb(150, 149, 149);
    --text-message-author-self: #003a90;
    --text-message-date: #9e9d9d;
    --text-message-date-self: #b9d5ff;

    --text-code: #333;
    --bg-code: rgba(0,0,0,0.12);
    --font-code: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier,
        monospace;

    --border-wss-grid-minor: #ccc;
    --border-wss-grid-medium: #999;
    --border-wss-grid-major: #777;

    --border-table: #c4c4c4;
    --bg-table-data: #fffee9;
    --bg-table-header: #82b0ff;

    --bg-menuselect: #0d5a8c;
    --bg-cursor: #f8ba68;
    --bg-cursor-readonly: #a6a6a6;
    --bg-dirty: #b0f868;
    --bg-menubar-top: #2C5C97;
    --bg-menubar-bot: #2C5C97;
    --bg-breadcrumb-bar: #ccc;
    --bg-row-hover: #ffff00;
    /* --bg-message: #f1e6c1; */
    --bg-message: #E9E8EB;
    --bg-message-self: #4088F6;

    --bg-chat-panel: #CFDBB8;
    --bg-wss-panel: #E7EAD3;

    --bg-row-odd: #fffdec;
    --bg-row-even: #deeafe;

    --bg-nav-quick: #E5E5E5;
    /* --bg-nav-quick: #e27bfe; */
    --bg-side-context_menu: #ffffff;
    /* --bg-side-context_menu: #e69200; */
    --bg-side-button-active: #2C5C97;

    /* A NET Device Link id is written the same way everywhere it is referred to, so it is
       recognisable at a glance in a breadcrumb trail, on a card, or in a sentence. */
    --text-device-link-id: #008B8B;

    /* Administrative surfaces — a supervisor-only button, a supervisor-only table cell —
       so it is visible at a glance which parts of a page are not ordinary clinical work. */
    --bg-admin: #fabc6f;
    /* Corrective actions: ordinary clinician work, but work that puts the record somewhere
       the normal flow could not. Coloured apart from the administrative surfaces because
       the distinction is who may press it, not how careful they should be. */
    --bg-corrective: #f5a9b8;

    --border-device-status: #4d75ac;
    /* The indicator's own background, separate from the menubar's so it can be made to
       stand out against it (or match it) without touching the bar. */
    --bg-device-status: #49688e;
    /* The patient id inside the indicator. Its own token rather than --text-patient-id
       because that one is chosen against a white table row, and this sits on a dark
       background where the same purple has far less contrast. */
    --text-menubar-patient-id: #ff9eff;
    --bg-device-none: #7f8c9b;
    --bg-device-on: #6cc07a;

    --bg-clear: rgba(0, 0, 0, 0.0);
    --bg-obscure: rgba(0, 0, 0, 0.5);

    --indent-context: 10px;
    --width-context-menu: 190px;
    --width-button-bar: 50px;

    --padding-panel: 10px;

    /* Plots have a 40px area for labels, so to align the plots
    * with the WSS grid the plot heading width needs to be 40px narrower
    * than the WSS heading width (+9px to match padding and border)
    */
    --width-wss-heading: 250px;
    --width-plot-heading: 219px;

    /* -webkit-font-smoothing: antialiased; */
}
html, body {
    height: var(--vh);
    margin: 0;
    padding: 0;
    overflow-x: hidden; /* Prevent horizontal scrolling */
}
h1 {
    font-size: 20px;
    margin: 0;
    padding: 0px;
    color: var(--text-primary);
}
input {
    font-size: 12pt;
}
code {
    color: var(--text-code);
    background-color: var(--bg-code);
    white-space: pre-wrap;
    word-wrap: break-word;
    padding: 2px 5px;
    font-family: var(--font-code);
    font-size: 75%;
    border: none;
    border-radius: 0;
}
.layout-row{
    display: flex;
    flex-flow: row;
    flex: 1 1;
    justify-content: space-between;
}
.layout-column{
    display: flex;
    flex-flow: column;
    flex: 1 1;
    justify-content: space-between;
}
.layout-column-start-nogrow{
    display: flex;
    flex-flow: column;
    flex: 0 1;
    justify-content: start;
}
.box {
    display: flex;
    /* flex: 1 1 auto; */
    flex-flow: column;
    height: 100%;
    min-height: 0;
}
.core{
    align-items: stretch;
    /* background-color:  orange; */
}

/* The "Main" large panel, includes breadcrumb bar */
.content-panel {
    justify-content: flex-start;
    align-items: stretch;
    height: 100%;
    width: 100%;
    min-height: 0;
    min-width: 0;

    background-color: var(--bg-core);
}
/* The "Content" area, below breadcrumb bar */
.content {
    padding: 10px 10px 10px 15px;
    justify-content: flex-start;
    align-items: stretch;
    height: 100%;
    min-height: 0;
    background-color: var(--bg-core);
}
.content.login {
    justify-content: center;
    align-items: center;
    overflow-y: scroll;
}
.content.admin {
    justify-content: start;
    /* `stretch`, NOT `center`. In a flex column, a child wider than the container is
       CENTRED by align-items:center, so it overflows equally on both sides — and the
       overflow to the LEFT of the scroll origin cannot be reached by scrolling, which
       silently clipped the first column of every admin table. Stretch also matches the
       other .content variants. */
    align-items: stretch;
    overflow-y: auto;
    /* Horizontal scrolling belongs to the table's own wrapper
       (.container-mobile-scroll), so the page itself never scrolls sideways and the
       headings stay put while a wide table is panned. */
    overflow-x: hidden;
    min-width: 0;
}
.content.beta-test-info {
    justify-content: center;
    align-items: center;
}
.login-button-field {
    margin-top: 30px;
    display: flex;
    justify-content: center;
}
.patient-panel-container{
    /* Flexbox overflow fix */
    min-height: 0;
}
.patient-panel-left{
    display: flex;
    flex: 0 1;
    min-width: 400px;
    /* background-color: aqua; */
    /* Flexbox overflow fix */
    min-height: 0;
    padding: var(--padding-panel);
    /* padding-left: 5px; */
    /* padding-bottom: 5px; */
    background-color: var(--bg-core);
    border-right: 1px solid #ccc;
}
.patient-panel-left.hidden{
    display: none;
}
.patient-panel-right{
    flex: 1 1;
    justify-content: flex-start;
    /* Flexbox overflow fix */
    min-height: 0;
    overflow-y: scroll;
    padding: var(--padding-panel);
    /* background-color: greenyellow; */
    /* background-color: var(--bg-wss-panel); */
    background-color: var(--bg-core);
}
.panel-heading{
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    font-size: 20px;
    font-weight: 700;
    color: #777;
    margin: -5px 0 5px 0;
}
.panel-chat-mobile{
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    align-items: stretch;
    height: 500px;
    padding-top: 8px;
    margin-bottom: 15px;
}

.link-as-button {
    display: inline-block;
    text-decoration: none;
    text-align: center;
    margin-left: 0.5rem;
    font-size: 1em;
    color: var(--text-primary);
    border: 0;
    background: var(--bg-active);
    border-radius: 5px;
    padding: 4px 10px;
    cursor: pointer;
    /* white-space: nowrap; */

    /* No text selection inside the button/link */
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE10+/Edge */
    user-select: none; /* Standard */
}
/* Same darkening as a real button's hover, and for the same reason: this is an anchor
   dressed as a button, so it must not be the one place left that replaces a colour instead
   of shading it. */
.link-as-button:hover {
    background-image: linear-gradient(rgba(0, 0, 0, 0.08), rgba(0, 0, 0, 0.08));
}
.nostretch{
    display: flex;

    justify-content: center;
    align-content: center;
    flex-direction: column;
}
.error-text{
    color: var(--text-error);
}
/* ----------------------------
 * Navigation
 * ---------------------------- */
 .main {
    display: flex;
    /* flex: 1 1 auto; */

    height: 100%;
    min-height: 0;
 }
 .nav-side {
    display: flex;
    flex: 1 1 auto;
    min-width: calc(var(--width-button-bar) + var(--width-context-menu));
    max-width: calc(var(--width-button-bar) + var(--width-context-menu));
    height: 100%;
    background-color: var(--bg-nav-quick);
    z-index: 20;
 }
 .nav-side-button-bar {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: flex-start;

    min-width: var(--width-button-bar);
    max-width: var(--width-button-bar);
    height: 100%;
    background-color: var(--bg-nav-quick);
 }
 .nav-side-context-menu {
    display: flex;
    flex: 1 1 auto;
    align-items: stretch;
    gap: 10px;

    min-width: var(--width-context-menu);
    max-width: var(--width-context-menu);

    background-color: var(--bg-side-context_menu);
    border-right: 1px solid #ccc;
 }
 .nav-side-context-content {
    display: flex;
    margin: 10px;
    align-items: stretch;
    gap: 10px;
 }
.nav-side-context-menu .button {
    margin: 0 0 0 var(--indent-context);
    border: 1px solid #a0a0a0;
    border-radius: 5px;
    height: 25px;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #313131;
}
.nav-side-context-menu h1 {
    font-size: 14px;
    margin: 0;
    border-bottom: 1px solid #5b76a6;
    color: #3A4E6E;
}
.nav-round-button {
    margin-top: 8px;
    display: flex;
    align-items: center;
    justify-content: center;

    width: 34px;
    height: 34px;
    border-radius: 50%;

    color: #404040;
    background-color: #CECECE;
    text-decoration: none;
}
.nav-round-button:hover{
    background-color: #B6B6B6;
}
.nav-round-button.active{
    color: #f2f2f2;
    background-color: var(--bg-side-button-active);
}
.nav-context-button{
    height: auto;
    display: inline-block;
    text-decoration: none;
    text-align: center;
    margin: 0;
    margin-bottom: 5px;
    font-size: 1em;
    color: var(--text-primary);
    border: 1px solid #999;
    background: var(--bg-active);
    border-radius: 5px;
    padding: 4px 10px;
    cursor: pointer;
    /* white-space: nowrap; */

    /* No text selection inside the button/link */
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE10+/Edge */
    user-select: none; /* Standard */
}

/* Muted secondary variant. A modifier — keep the base class alongside it in markup:
   class="nav-context-button nav-context-button--secondary". Themed via tokens. */
.nav-context-button--secondary {
    background: transparent;
    color: var(--text-primary);
}

/* An administrative context button, rendered only for supervisors. Coloured so that it is
   obvious at a glance which buttons on a patient page are not part of ordinary clinical
   work: reversing a discharge and collecting telemetry on demand are both things a
   supervisor does to a record rather than things a clinician does to a patient. */
.nav-context-button--admin {
    background: var(--bg-admin);
}

/* A read-only fact in the context sidebar, as opposed to an action. Laid out to line up
   under the buttons of its section rather than beside them, because the label needs the
   width more than the value does. */
.nav-context-fact {
    margin-top: 2px;
    margin-bottom: 5px;
    padding: 0 2px;
    font-size: 0.85em;
    line-height: 1.35;
}
.nav-context-fact__label {
    color: var(--text-secondary);
}
.nav-context-fact__value {
    color: var(--text-primary);
    white-space: nowrap;
    margin-left: 8px;
}
.nav-context-fact__value--none {
    color: var(--text-secondary);
    font-style: italic;
    margin-left: 8px;
}

/* A context button for a corrective action — abandoning a device that cannot be reached,
   stopping one that is running for nobody. Any clinician may press these; they are coloured
   because each one asserts something about a device we could not confirm, or acts on a
   record the ordinary flow has already finished with. */
.nav-context-button--corrective {
    background: var(--bg-corrective);
}

/* A context button the current patient state does not allow. Dimmed rather than hidden so
   the action stays discoverable and its title can say what would make it available. */
.nav-context-button:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* ----------------------------
 * Dimmer
 * ---------------------------- */
.dimmer{
    /* This div fills the whole screen and acts as a "dimmer" for
    * the base content of the page. The mp-card-detail element inherits
    * its visibility from this root, so we show/hide the card detail by
    * toggling the visibility of this element.
    */
    z-index: 10;
    position: absolute;
    pointer-events: none;

    width: 100%;
    left: 0px;

    height: 100%;
    top: 0px;

    background-color: var(--bg-clear);
    -webkit-transition: background-color 400ms linear;
    -ms-transition: background-color 400ms linear;
    transition: background-color 400ms linear;
}
.dimmer.obscure{
    pointer-events: auto;
    background-color: var(--bg-obscure);
}

/* ----------------------------
 * Login
 * ---------------------------- */
.login-item {
    display: flex;
    margin: 7px;
    /* text-align: center; */
    align-items: center;
}
.login-label {
    padding-right: 10px;
    width: 100px;
    text-align: right;
}
.login-error-text,
.login-success-text,
.login-notice-text,
.password-change-error-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    margin: 10px;
    width: 360px;
    color: var(--text-error);
}
.login-error-text:empty,
.login-success-text:empty,
.login-notice-text:empty,
.password-change-error-text:empty {
    margin: 0;
}
/* Being timed out is information, not a failure -- the user did nothing wrong, so this does
   not get the error red. */
.login-notice-text {
    color: var(--text-notice);
    font-weight: bold;
}
.login-success-text {
    color: var(--text-success);
}
.password-change-error-text {
    min-height: 50px;
}
.login-info {
    display: inline-block;
    text-align: center;
    margin: 10px;
    width: 360px;
    color: var(--text-error);
}
.login-message-password-reset-required {
    display: inline-block;
    text-align: center;
    color: #ec9100;
}
.login-message-password-reset-required.hidden{
    display: none;
}
/* ----------------------------
 * Breadcrumb bar
 * ---------------------------- */
.breadcrumb-bar {
    background-color: var(--bg-breadcrumb-bar);
    border-bottom: 1px solid var(--border-wss-grid-minor);

    /* No text selection */
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE10+/Edge */
    user-select: none; /* Standard */

    font-size: 16px;
}
.controls {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 30px;
    margin: 0.5rem;
}
.controls.breadcrumbs {
    justify-content: left;
    align-items: left;
    height: 10px;
    margin-left: 1rem;
    color: var(--text-secondary-breadcrumb);
    white-space: nowrap;
}
.controls.breadcrumbs a {
    text-decoration: none;
    color: var(--text-secondary-breadcrumb);
}
.controls.breadcrumbs a:hover {
    text-decoration: underline;
}

/* The step you are on: same colour as the rest of the bar, but not a link, so weight is
   what distinguishes it. */
.breadcrumbs__current {
    font-weight: 600;
}

.breadcrumbs__separator {
    margin: 0 0.35rem;
    font-size: 0.75em;
    opacity: 0.7;
}

.patient-list-item .link-as-button {
    border: 1px solid #999;
    padding: 2px 10px;
    margin: 3px 0px;
}

.patient-id {
    font-weight: bold;
    color: var(--text-patient-id);
    cursor: default;
}

.core-child {
    /* As flex child */
    flex-grow: 1;
    flex-direction: column;

    /* As flex parent */
    display: flex;

    min-height: 0;

    /* background-color: (var) */
    margin: 10px;
    max-height: 100%;
}

/* ----------------------------
 * Menu Bar
 * ---------------------------- */
.menubar {
    justify-content: space-between;
}
.menugroup {
    display: flex;
    margin: 8px;
}
.menubar .text {
    display: flex;
    justify-content: center;
    align-content: center;
    flex-direction: column;
}
.menubar .title{
    font-size: 16px;
}
.menubar .version{
    display: flex;
    align-content: center;
    flex-direction: column;
    justify-content: center;
}
.menubar .nonStandardHostName{
    display: flex;
    flex-direction: column;
    align-content: center;
    justify-content: center;

    color: #ffbf00;

    margin-left: 0;
}
.toggle-menu{
    display: none;
    align-items: center;
    justify-content: center;
    margin-right: 8px;

    width: 30px;
    height: 30px;
    border-radius: 50%;

    color: #f2f2f2;
    background-color: #324772;
}
.menubar .user-info {
    display: flex;
    align-items: center;
}

/* ----------------------------
 * Patient List
 * ---------------------------- */
.patient-list{
    flex: 1 1;
    justify-content: flex-start;
    overflow-y: scroll;
    overflow-x: scroll;
    height: 100%;
    min-height: 0;

    margin-top: 10px;
}
.patient-list-patient.mobile {
    display: flex;
    flex-direction: column;
    margin-bottom: 10px;
    align-items: center;
}
.patient-box {
    border: 1px solid #ccc;
}
.patient-list-row{
    flex: 1 1;
    width: fit-content;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    background-color: var(--bg-row-even);

    cursor:default;
}
.patient-list-row.odd{
    background-color: var(--bg-row-odd);
}
.mobile .patient-list-row{
    background-color: var(--bg-row-odd);
}
.patient-list-row.data.deleted{
    background-color: #f9dada;
}
.patient-list-patient:not(.mobile) .patient-list-row.data:hover{
    background-color: var(--bg-row-hover);
}

.patient-list-item{
    flex-shrink: 0;
    display: flex;

    text-align: center;

    flex-direction: row;
    align-items: center;
    justify-content: center;

    padding: 0 6px 0 6px;
    margin: 2px 6px 2px 6px;
    width: 160px;
    overflow-wrap: break-word;
}
.patient-list-item.narrow{
    width: 60px;
}
.patient-list-item.narrow2{
    width: 70px;
}
.patient-list-item.narrow3{
    width: 80px;
}
.patient-list-item.wide{
    width: 190px;
}
.patient-list-item.wide2{
    width: 215px;
}

.mobile .patient-list-item{
    min-height: 27px;
    padding: 0;
    margin: 0;
    font-size: 15px;
}
.mobile .first .patient-list-item{
    /* height: 37px; */
    height: 42px;
}

/* Mobile heading */
.mobile .patient-list-item.heading{
    display: flex;
    align-items: center;
    justify-content: right;
    background-color: var(--bg-table-header);
    padding: 0 8px 0 0;
    margin: 0;
    font-weight: 700;
    width: 130px;
}
.patient-list-item.mobile{
    display: flex;
    align-items: left;
}

.patient-list-row.heading{
    display: flex;
    flex-direction: row;
    background-color: var(--bg-table-header);
}
.patient-list-item.heading{
    font-weight: 700;
}

.page-heading-row{
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    gap: 10px;
}
.page-heading-icon{
    display: flex;
    flex-direction: row;
    margin-bottom: 10px;
}
.page-heading-item{
    text-align: center;
    vertical-align:middle;
    /* padding: 0 6px 0 6px; */
    margin: 0;
    /* margin: 0px 10px 0px 0px; */
    /* width: 160px; */
    /* overflow-wrap: break-word; */
}
.page-heading-item.title{
    font-size: 20px;
    font-weight: 700;
}
/* An action repeated from the side context menu into the page heading. On a wide screen
   that menu is always on-screen, so this copy is hidden and only the sidebar one shows;
   the narrow-screen rule below turns it on, because there the menu is off-canvas behind
   the hamburger and the action is otherwise invisible. */
.page-heading-action{
    display: none;
    margin-bottom: 0;
    white-space: nowrap;
}

/* ----------------------------
 * Patients pagination controls
 * ---------------------------- */
.patient-list__pagination__controls{
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 12px;
    font-size: 14px;
    color: var(--text-secondary);
}
.patient-list__pagination__status{
    white-space: nowrap;
}
.patient-list__pagination__pagesize{
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}
.patient-list__pagination__pagesize select{
    font-size: 14px;
    padding: 2px 4px;
    border: 1px solid #999;
    border-radius: 5px;
    background: var(--bg-active);
    color: var(--text-primary);
    cursor: pointer;
}
.patient-list__pagination__nav{
    display: flex;
    align-items: center;
    gap: 8px;
}
.patient-list__pagination__pageinfo{
    white-space: nowrap;
    min-width: 90px;
    text-align: center;
}
.patient-list__pagination__btn{
    margin-bottom: 0;       /* override nav-context-button's bottom margin here */
    font-size: 14px;
    padding: 3px 10px;
}
.patient-list__pagination__btn:disabled{
    opacity: 0.45;
    cursor: default;
}

.login-items-centered {
    display: flex;
    flex-direction: column;
    align-items: center;
}
.login-authenticator-prompt,
.beta-tester-prompt {
    display: inline-block;
    text-align: center;
    margin: 10px;
}
#text-search{
    border: 1px solid #aaa;
    /* width: 500px; */
}
.mobile .patient-list-item.data{
    display: flex;
    align-items: center;
    justify-content: left;
    padding-left: 8px;
}
.mobile .patient-list-item.data:not(.first){
    box-shadow: inset 0 1px 0 #ccc;
}
.mobile .patient-list-item.heading:not(.first){
    /* box-shadow: inset 0 1px 0 #9090f0; */
    box-shadow: inset 0 1px 0 #779BB0;
}

/* ----------------------------
 * Patient Messages
 * ---------------------------- */
 .patient-messages{
    display: flex;
    flex-direction: column;

    flex: 1 1;

    align-items: stretch;
    padding: 10px;
    border: 1px solid #a5a5a5;

    background-color: #ffffff;
    /* width: 380px; */
    font-size: 15px;
    overflow-y: scroll;
    /* overflow-x: scroll; */
 }
 .patient-message{
    background-color: var(--bg-message);
    /* width: 350px; */
    margin-bottom: 4px;
    padding: 5px 10px;
    border-radius: 14px;
    margin-right: 20px;
 }
 .patient-message.self-authored{
    background-color: var(--bg-message-self);
    margin-right: 0px;
    margin-left: 20px;
}
.patient-messages > .patient-message:last-of-type{
    margin-bottom: 0px;
}
.patient-message .heading{
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    margin-bottom: 5px;
}
.patient-message .name{
    color: var(--text-message-author);
    font-weight: 600;
}
.patient-message.self-authored .name{
    visibility: hidden;
    color: var(--text-message-author-self);
 }
 .patient-message .date{
    color: var(--text-message-date);
    font-size: 12px;
 }
 .patient-message.self-authored .date{
    color: var(--text-message-date-self);
    font-size: 12px;
 }
 .patient-message .text{
    white-space: pre-wrap;
    color: #343434;
 }
 .patient-message.self-authored .text{
    color: var(--text-message-core-self);
 }
.patient-message-compose-area{
    display: flex;
    flex-direction: column;
    border: 1px solid #a5a5a5;
    /* padding: 0 0 5px 0; */
    /* background-color: orange; */
    /* background-color: #8ca5af; */
    background-color: #a2b9db;
}
#patient-message-compose-text{
    flex: 1 0;
    min-height: 100px;
    width: auto;
    margin: 8px;
    padding: 5px;
    /* IMPORTANT: 16px is the min font size to avoid iOS "auto zooming" on the text field when
    it gets focus. DO NOT reduce it. */
    font-size: 16px;
    /* background-color: #80F080; */
    background-color: white;
    overflow-y: scroll;
    outline: none;
    resize: none;
}
.patient-message-row{
    display: flex;
    justify-content: flex-end;
    padding: 5px;
    /* background-color:#ffff00; */
 }
 /* ----------------------------
  * Patient WSS
  * ---------------------------- */
.patient-wss {
    display: flex;
    flex-direction: column;
    align-items: flex-start;

    color: #555;

    /* overflow-y: scroll; */
    /* overflow-x: scroll; */

    /* No text selection */
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE10+/Edge */
    user-select: none; /* Standard */

    cursor: default;
}
.nv-wss-mobile-scroll-container{
    border: 1px solid #757575;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    overflow-x: scroll;
    overflow-y: none;
    width: 100% - 16px;
    height: 400px;
    min-height: 1150px;
    padding: 8px;
    margin-bottom: 15px;
}
.wss-row{
    display: flex;
    /* flex: 0 0; */
    flex-direction: row;
    background-color: #ddd;
    min-height: 21px;
}
.wss-row.tod-label{
    color: #888;
    min-height: 25px;
}
.wss-row.totals{
    background-color: #CBC7B4;
}
.wss-row.data{
    background-color: var(--bg-row-even);
}
.wss-row.data.odd{
    background-color: var(--bg-row-odd);
}
.patient-wss.discharged .wss-row.data{
    background-color: #e8e8e8;
}
.patient-wss.discharged .wss-row.data.odd{
    background-color: #f8f8f8;
}
.wss-row.data:hover{
    background-color: var(--bg-row-hover);
}
.wss-heading{
    width: var(--width-wss-heading);
    overflow-wrap: break-word;
    border-left: 1px solid var(--border-wss-grid-minor);
    border-top: 1px solid var(--border-wss-grid-minor);
    margin: 0;
    padding: 0px 4px;/
}
.wss-heading.void{
    background-color: var(--bg-core);
    border-left: 1px solid var(--bg-core);
    border-top: 1px solid var(--bg-core);
}
.wss-heading.void.last{
    border-top:  1px solid var(--border-wss-grid-minor);
}
.wss-cell{
    display: flex;
    justify-content: center;
    align-items: center;
    min-width: 26px;
    max-width: 26px;
    border-left: 1px solid var(--border-wss-grid-minor);
    border-top: 1px solid var(--border-wss-grid-minor);
    /* margin: -1px 0 0 -1px; */
    margin: 0;
    box-sizing: border-box;
}
.wss-cell.total{
    border-left: 1px solid var(--border-wss-grid-medium);
}
.wss-row .wss-cell:last-child{
    border-right: 1px solid var(--border-wss-grid-major);
}
.patient-wss .wss-row:last-child .wss-cell{
    border-bottom: 1px solid var(--border-wss-grid-major);
    border-top: 1px solid var(--border-wss-grid-major);
}
.patient-wss .wss-row:first-child .wss-cell,
.wss-cell.first-row{
    border-top: 1px solid var(--border-wss-grid-major);
}
.patient-wss .wss-row .wss-cell.day-start{
    border-left: 1px solid var(--border-wss-grid-major);
}
.wss-cell.day-start{
    border-left: 1px solid var(--border-wss-grid-major);
}
.wss-cell.dirty{
    background-color: var(--bg-dirty);
}
.wss-cell.cursor{
    background-color: var(--bg-cursor);
}
.patient-wss.discharged .wss-cell.cursor{
    background-color: var(--bg-cursor-readonly);
}
.wss-cell.full-day{
    /* This cell spans a full day */
    min-width: 78px;
    max-width: 78px;
    border-bottom: 1px solid var(--border-wss-grid-medium);
}
.wss-cell.date{
    font-size: 12px;
}

 /* ----------------------------
  * Patient Plots
  * ---------------------------- */
.plot-row{
    display: flex;
    flex-direction: row;
    /* background-color: var(--bg-wss-panel); */
}
.plot-heading{
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-end;
    text-align: center;

    min-width: var(--width-plot-heading);
    font-size: 20px;
    font-weight: 700;
    color: #777;
    margin: -5px 0 5px 0;
}
 /* ----------------------------
  * Treatment History
  * ---------------------------- */
.treatment-history{
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;

    padding: 0;
    margin-left: 37px;
    /* width: 1088px; */
    background-color: none;
    /* font-family: Monaco, monospace; */
    font-size: 14px;
    color: #aaa;
}
.treatment-history.mobile{
    width: auto;
    margin-left: 0;
}
.treatment-value{
    /* color: rgb(0, 119, 141); */
    color: var(--text-primary);
    font-weight: 700;
}
 /* ----------------------------
  * Plot row content
  * ---------------------------- */
.plot-row-content-generic{
    padding: 5px;
    margin-left: 37px;
    width: 1088px;
}
.telemetry-button{
    border: 1px solid #999;
    margin: 0;
    margin-bottom: 5px;
}

/* ----------------------------
 * Data Grid
 * ---------------------------- */
.nv-data-grid {
    border: 1px solid var(--border-table);
    color: black;
}
.nv-data-grid-row{
    flex: 1 1;
    width: fit-content;
    display: flex;
    flex-direction: row;
    align-items: stretch;

    cursor:default;
}
.nv-data-grid-item{
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: left;
    padding: 0 0 0 8px;

    /* text-align: center; */
    vertical-align:middle;
    min-height: 27px;
    width: 223px;
    margin: 0;
    font-size: 15px;
    overflow-wrap: break-word;
    background-color: var(--bg-row-odd);

}
.nv-data-grid-item .link-as-button {
    margin: 8px 0px;
}
.nv-data-grid-item.heading{
    display: flex;
    align-items: center;
    justify-content: right;
    background-color: var(--bg-table-header);
    /* Padding on BOTH sides, and a text alignment as well as a flex alignment.
       A label short enough to fit is one flex item that justify-content can push to the
       right edge. One long enough to wrap becomes a single multi-line item that fills the
       content box, so there is nothing left for justify-content to move and the lines fall
       back to the text alignment — which was the default left, hard against a left edge
       that had no padding. The vertical padding keeps two lines off the cell edges without
       affecting one line, which min-height still governs. */
    text-align: right;
    padding: 3px 8px;
    margin: 0;
    font-weight: 700;
    width: 130px;
}
/* The same for a value long enough to wrap: without the right-hand padding its second
   line runs into the cell edge. */
.nv-data-grid-item.data{
    padding: 3px 8px;
}
.nv-data-grid-item.data:not(.first){
    box-shadow: inset 0 1px 0 #ccc;
}
.nv-data-grid-item.heading:not(.first){
    box-shadow: inset 0 1px 0 #779BB0;
}

/* ----------------------------
 * Generic Table
 * ---------------------------- */
 table.generic-table{
    border-spacing: 0px;
    border-collapse: collapse;
    margin: 1rem;
}
.generic-table td,
.generic-table th {
    border: 1px solid var(--border-table);
    padding: 2px 10px;
}
.generic-table th {
    background: var(--bg-table-header);
}
.generic-table td {
    background: var(--bg-table-data);
}

/* Wraps a table so that a table wider than the window scrolls WITHIN its own box rather
   than dragging the page sideways. Long used by the admin tables but never actually
   defined, which is why they overflowed. min-width:0 is required: a flex item defaults to
   min-width:auto, which refuses to shrink below its content and so defeats the overflow. */
.container-mobile-scroll {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Below the mobile breakpoint a 6-column table cannot be read by panning, so the table
   layout is dropped entirely and each row becomes a labelled card. The labels come from
   the data-label attribute buildResponsiveTable() puts on every cell — see
   cmd/netvue/util.html.table.go.

   768px is the stylesheet's existing mobile breakpoint (see the Media section below), so
   the nav collapse and the table restyle happen at the same width rather than leaving a
   band where the page is half-converted. */
@media screen and (max-width: 768px) {
    .container-mobile-scroll {
        /* Nothing left to scroll: the cards are as wide as the screen. */
        overflow-x: visible;
    }
    table.generic-table {
        margin: 0.5rem 0;
        width: 100%;
        display: block;
    }
    .generic-table thead {
        /* Each cell carries its own label now. */
        display: none;
    }
    .generic-table tbody,
    .generic-table tr,
    .generic-table td {
        display: block;
    }
    .generic-table tr {
        border: 1px solid var(--border-table);
        border-radius: 6px;
        margin-bottom: 10px;
        overflow: hidden;
    }
    .generic-table td {
        /* Two columns: the ::before label, then everything the cell contains (contiguous
           inline content collapses into a single anonymous grid item). Wrapping the long
           privilege lists is the whole point of the 1fr. */
        display: grid;
        grid-template-columns: minmax(7em, 38%) 1fr;
        gap: 10px;
        align-items: baseline;
        border: none;
        border-bottom: 1px solid var(--border-table);
        padding: 6px 10px;
        overflow-wrap: anywhere;
    }
    .generic-table tr td:last-child {
        border-bottom: none;
    }
    .generic-table td::before {
        content: attr(data-label);
        font-weight: 700;
    }
    /* A cell with no value would otherwise render as a label pointing at nothing. Empty
       cells are genuinely empty (the builder emits no whitespace), so :empty matches. */
    .generic-table td:empty {
        display: none;
    }
}
/* ----------------------------
 * NET Device Links
 * ---------------------------- */
.content.device-links {
    justify-content: start;
    /* `stretch`, NOT `center`: in a flex column a child wider than the container is
       centred, which puts part of it to the left of the scroll origin where it cannot be
       reached. */
    align-items: stretch;
    overflow-y: auto;
    overflow-x: hidden;
    min-width: 0;
}
/* An NDL id wherever it is a REFERENCE to a link. The detail page's own heading is the id
   written as a title rather than as a reference, and deliberately does not take this. */
.device-link-id {
    color: var(--text-device-link-id);
    font-weight: 700;
}

.device-link-list__scope {
    font-size: 0.85em;
    opacity: 0.75;
    margin: 0 0 10px 0;
}
/* Empty unless the last poll failed, so the space it would take is not reserved. */
.device-link-status:empty {
    display: none;
}
.device-link-status--error {
    color: var(--text-error);
    font-size: 0.85em;
    white-space: normal;
}
.device-link-list {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 12px;
}
.device-link-card {
    display: block;
    padding: 10px 14px;
    width: 300px;
    border: 1px solid var(--border-table);
    border-radius: 6px;
    background: var(--bg-table-data);
    color: var(--text-primary);
    text-decoration: none;
}
.device-link-card:hover {
    background: var(--bg-table-header);
}
.device-link-card__head {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
}
.device-link-card__id {
    font-weight: 700;
}
.device-link-card__owner {
    font-size: 0.85em;
    color: var(--text-secondary);
    /* A commit-qualified NDL version is long and must not widen the card. */
    overflow-wrap: anywhere;
}
.device-link-card__rule {
    border-top: 1px solid var(--border-table);
    margin: 8px 0;
}
.device-link-card__device {
    font-weight: 700;
}
.device-link-card__device-detail {
    font-size: 0.85em;
    color: var(--text-secondary);
}
/* An NDL with nothing attached is the common resting state, so it is stated in the same
   place the device would be rather than left as a gap in the card. */
.device-link-card__device--none {
    font-style: italic;
    color: var(--text-secondary);
}
/* Distinct from "no device attached": that is a fact, this is the absence of one. */
.device-link-card__device--unknown {
    font-style: italic;
    color: var(--text-secondary);
}
.device-link-card__footer {
    font-size: 0.85em;
    color: var(--text-secondary);
    margin-top: 8px;
}
/* The liveness badge. The dot carries the state as colour and the text carries it as a
   word, so neither the colour nor the label is load-bearing on its own. */
.device-link-liveness {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-size: 0.85em;
    white-space: nowrap;
}
.device-link-liveness__dot {
    font-size: 0.7em;
}
.device-link-liveness--online .device-link-liveness__dot {
    color: var(--text-success);
}
.device-link-liveness--stale .device-link-liveness__dot {
    color: #c47f00;
}
.device-link-liveness--lost .device-link-liveness__dot {
    color: var(--text-error);
}
.device-link-liveness--unknown .device-link-liveness__dot {
    color: var(--text-secondary);
}
/* The detail view is a short column of narrow tables. Centring it keeps a wide window from
   stranding them against the left edge with the rest of the page empty. */
.device-link-detail {
    display: flex;
    flex-direction: column;
    align-items: center;
}
.device-link-detail__panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 14px;
}
/* The grid is as wide as its content and no wider, so it does not stretch to the page. */
.device-link-detail__panel .nv-data-grid {
    width: fit-content;
    max-width: 100%;
}
.device-link-detail__empty:empty {
    display: none;
}
.device-link-detail__empty {
    font-style: italic;
    color: var(--text-secondary);
    padding: 8px 0;
}
.device-link-detail__age {
    color: var(--text-secondary);
}

@media screen and (max-width: 768px) {
    /* One card per row: the fixed width is a nicety on a wide screen and a horizontal
       scrollbar on a 320px one. */
    .device-link-card {
        width: 100%;
    }
    /* The heading row is built for a lone title; with a status message beside it, both
       have to be able to fall onto two lines. */
    .device-links .page-heading-row {
        flex-wrap: wrap;
    }
}

/* ----------------------------
 * Admin sections
 * ---------------------------- */
.admin-sections {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 1rem;
}
.admin-sections__card {
    display: block;
    padding: 12px 16px;
    min-width: 220px;
    border: 1px solid var(--border-table);
    border-radius: 6px;
    background: var(--bg-table-data);
    color: var(--text-primary);
    text-decoration: none;
}
.admin-sections__card:hover {
    background: var(--bg-table-header);
}

/* ----------------------------
 * Narrow screens: the admin section
 *
 * The tables already stack into labelled cards above, and the left nav (which carries the
 * context menu with it) already slides off-canvas behind the hamburger. What was left
 * unhandled is the chrome around them — chiefly the breadcrumb bar, which on an admin page
 * is now the ONLY navigation, since that menu carries actions and nothing else.
 * ---------------------------- */
@media screen and (max-width: 768px) {
    /* The bar was built for exactly one fixed step ("Patients"): nowrap, at a fixed 10px
       height. An admin trail is up to three steps with icons, which at phone width has to
       WRAP rather than run off the side of a screen that cannot be scrolled sideways. */
    .controls.breadcrumbs {
        height: auto;
        align-items: center;
        white-space: normal;
        line-height: 1.7;
        margin: 0.4rem 0.75rem;
    }
    /* A flex item's min-width defaults to auto, which lets it overflow its container
       rather than wrap inside it. The trail lives in a single span, so without this the
       white-space change above has nothing to act on. */
    .controls.breadcrumbs > span {
        min-width: 0;
    }
    .breadcrumbs__separator {
        margin: 0 0.2rem;
    }

    /* One card per row. The 220px floor is a nicety on a wide screen and a horizontal
       scrollbar on a 320px one. */
    .admin-sections {
        margin: 1rem 0.5rem;
    }
    .admin-sections__card {
        min-width: 0;
        width: 100%;
    }

    /* Submit and Cancel sit side by side until they do not fit. */
    .add-patient__actions {
        flex-wrap: wrap;
    }

    /* The only place the context menu's actions are reachable without opening the
       hamburger. See .page-heading-action. */
    .page-heading-action {
        display: inline-block;
    }
    /* The heading row is a space-between flex row built for a lone title; with a button
       beside it, a long title and the button have to be able to fall onto two lines. */
    .admin .page-heading-row {
        flex-wrap: wrap;
    }
}
.admin-sections__title {
    font-weight: 700;
}
.admin-sections__detail,
.admin-section__detail {
    font-size: 0.85em;
    opacity: 0.75;
}
.admin-section__detail {
    margin: 0 1rem 0.5rem 1rem;
}
.admin-section__empty {
    margin: 1rem;
    opacity: 0.75;
}

/* ----------------------------
 * Clinician permissions panel
 * ---------------------------- */
.add-clinician__hint {
    font-size: 0.8em;
    opacity: 0.75;
    font-weight: 400;
}
.perm-panel {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.perm-group {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 24px;
    align-items: center;
    border: 1px solid var(--border-table);
    border-radius: 6px;
    background: var(--bg-table-data);
    padding: 10px 14px;
    margin: 0;
}
.perm-group legend {
    font-weight: 700;
    font-size: 0.9em;
    padding: 0 4px;
}
/* Supervisor privileges when the administrator may not grant them. The inputs carry a
   real `disabled` attribute; this only makes that state legible. */
.perm-group--disabled {
    opacity: 0.5;
}
.perm-group--disabled .radio-option {
    cursor: not-allowed;
}

/* ----------------------------
 * Table row action button (e.g. Edit on the clinicians list)
 * ---------------------------- */
.table-action-button {
    padding: 2px 12px;
    cursor: pointer;
    white-space: nowrap;
}

/* ----------------------------
 * Edit modal (clinician editor)
 * ---------------------------- */
.edit-modal {
    border: 1px solid var(--border-table);
    border-radius: 6px;
    padding: 0;
    /* Bounded by the VIEWPORT, not by content: the permissions panel makes this dialog
       taller than a short window, and without the cap the actions row would sit off-screen
       with no way to reach Save. */
    width: min(560px, calc(100vw - 24px));
    max-height: calc(100vh - 40px);
    color: var(--text-primary);
    background: var(--bg-core);
    /* The dialog itself must not scroll — only its body does, so the title and the
       Save/Cancel row stay pinned. */
    overflow: hidden;
}
.edit-modal::backdrop {
    background: rgba(0, 0, 0, 0.35);
}
.edit-modal form {
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 40px);
}
.edit-modal__title {
    font-weight: 700;
    font-size: 1.1em;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-table);
}
.edit-modal__body {
    /* The only scrolling region. min-height:0 is required for a flex child to be allowed
       to shrink below its content and therefore to scroll at all. */
    overflow-y: auto;
    min-height: 0;
    padding: 14px 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.edit-modal__body .field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.edit-modal__body .field-inline {
    flex-direction: row;
    align-items: center;
    gap: 8px;
}
.edit-modal__body label {
    font-weight: 600;
    font-size: 0.9em;
}
.edit-modal__body .input {
    padding: 8px;
    width: 100%;
    box-sizing: border-box;
    height: auto;
}
.edit-modal__section-title {
    font-weight: 700;
    margin-top: 4px;
    padding-top: 10px;
    border-top: 1px solid var(--border-table);
}
/* The read-only facility. Styled to look deliberately inert rather than like a disabled
   input someone might try to re-enable. */
.edit-modal__readonly {
    padding: 8px;
    background: var(--bg-table-data);
    border: 1px dashed var(--border-table);
    border-radius: 4px;
    font-size: 0.95em;
}
.edit-modal__actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    padding: 12px 18px;
    border-top: 1px solid var(--border-table);
}

/* ----------------------------
 * WSS Tooltip
 * ---------------------------- */
 .wss-tooltip{
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    box-sizing: border-box;
    /* Never wider than the viewport, so a narrow window wraps the text
       instead of running it off the (overflow-x: hidden) page edge. */
    max-width: min(420px, calc(100vw - 20px));
    padding: 5px;
    background-color: #fffebf;
    border: 1px solid #ccc;
    border-radius: 5px;
    font-size: 14px;
    color: #333;
    z-index: 10;
    position: absolute;
    /* opacity: 90%; */
    /* left: 300px; */
    /* top: 300px; */
}
.wss-tooltip__display_label{
    font-weight: 700;
}
.wss-tooltip__row{
    margin-left: 10px;
}
/* ----------------------------
 * ISO-8601 Date
 * ---------------------------- */
 /* The display:inline makes it so that the span does not cause a
    line break during copy-paste */
/* A data-grid cell holding something only a supervisor is shown. Coloured for the same
   reason the administrative buttons are: so which parts of a page are outside ordinary
   clinical work is visible without reading them. */
.nv-data-grid-item.data.admin-only {
    background: var(--bg-admin);
}

.iso8601-t, .iso8601-offset{
    opacity: 0.3;
    display: inline;
}
.patient-message .iso8601-t,
.patient-message .iso8601-offset{
    opacity: 0.5;
}

 /* ----------------------------
 * Media
 * ---------------------------- */

@media screen and (max-width: 768px) {
    .toggle-menu{
        display: flex;
    }
    .menubar .user-info{
        display: none;
    }
    .menubar .nonStandardHostName{
        display: none;
    }
    .nav-side{
        position: absolute;
        transform: translateX(-100%);
        -webkit-transform: translateX(-100%);
        /* Must force height because auto-height no longer works when this
         * menu is hidden.  The value below leaves a big gap but has enough
         * margin so scroll bars won't start appearing if the heading bar
         * ever changes height slightly.
         */
        height: 90dvh;
    }
    .slide-in {
        animation: sp-slide-in 0.5s forwards;
        -webkit-animation: sp-slide-in 0.5s forwards;
    }

    .slide-out-immediate {
        animation: sp-slide-out 0s forwards;
        -webkit-animation: sp-slide-out 0s forwards;
    }

    .slide-out {
        animation: sp-slide-out 0.5s forwards;
        -webkit-animation: sp-slide-out 0.5s forwards;
    }

    /* The dropzone js library is already using the animation
     * names `slide-in` and `slide-out`, so we prefix with `sp-`
     * to avoid the name collision.
     */
    @keyframes sp-slide-in {
        100% { transform: translateX(0%); }
    }

    @-webkit-keyframes sp-slide-in {
        100% { -webkit-transform: translateX(0%); }
    }

    @keyframes sp-slide-out {
        0% { transform: translateX(0%); }
        100% { transform: translateX(-100%); }
    }

    @-webkit-keyframes sp-slide-out {
        0% { -webkit-transform: translateX(0%); }
        100% { -webkit-transform: translateX(-100%); }
    }

    /* Patients pagination: on narrow screens keep the controls hugging the
     * right edge and clear of the "Patients" heading. Right-aligning the
     * wrapped rows stops "‹ Prev" from crowding the title. */
    .patient-list__pagination__controls{
        justify-content: flex-end;
        text-align: right;
        row-gap: 6px;
        padding-left: 24px;   /* separation from the "Patients" heading */
    }
}

/* ---- Add Patient ---- */
#add-patient-btn {
    margin-left: auto;
    align-self: center;
    text-decoration: none;
}
.add-patient__form {
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-width: 460px;
    margin-top: 8px;
}
.add-patient__form .field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.add-patient__form .field-inline {
    flex-direction: row;
    align-items: center;
    gap: 8px;
}
.add-patient__form label {
    font-weight: 600;
    font-size: 0.9em;
}
.add-patient__form .input {
    padding: 8px;
    width: 100%;
    box-sizing: border-box; /* keep padding+border inside 100% so inputs don't overflow */
    height: auto;           /* override shoestring input{height:24px}: with border-box that
                               fixed height squishes the field */
}
.add-patient__form .radio-row {
    display: flex;
    flex-direction: row;
    gap: 20px;
    align-items: center;
}
.add-patient__form .radio-option {
    font-weight: 400;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
}
.add-patient__actions {
    display: flex;
    gap: 10px;
    margin-top: 8px;
}
.add-patient__error {
    color: #b00020;
    font-weight: 600;
}

/* The shared modal dialog frame, and the family of content elements below it: title, text,
   field, label, input, error, actions, button. A dialog needs no component block of its own
   unless it has something genuinely particular to say — .treatment-start mixes in only to
   be wider, and .ap-confirm only for its message. Wiring lives in App.Util.openDialog. */
.nv-dialog {
    border: 1px solid var(--border-table);
    border-radius: 6px;
    padding: 20px 22px;
    max-width: 360px;
    color: var(--text-primary);
    font-size: 14px;
}
.nv-dialog::backdrop {
    background: rgba(0, 0, 0, 0.35);
}
.nv-dialog__actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
}
/* Make the focused (default) button clearly visible so it's obvious Enter will click it.
   Uses :focus (not just :focus-visible) so the ring shows on programmatic focus too.
   .nv-dialog__button is a mix: the buttons also carry .nav-context-button, so this
   stays a flat single-class selector instead of reaching into another block. */
.nv-dialog__button:focus {
    outline: 2px solid var(--bg-menuselect);
    outline-offset: 2px;
}

/* Confirm dialog (e.g. the under-18 / over-100 warning on Add Patient). */
.ap-confirm__message {
    margin-bottom: 18px;
    line-height: 1.4;
}

/* The dialog CONTENT elements, alongside .nv-dialog__actions and .nv-dialog__button above.
 *
 * These began life as .patient-discharge__* and were copied wholesale into
 * .treatment-start__* — four of them byte for byte. The name was the problem: it read as
 * belonging to one dialog, so the next dialog copied it instead of using it. They are here,
 * under the block that is actually on every dialog element, and a component block now
 * carries only what is genuinely its own.
 */
.nv-dialog__title {
    font-weight: 600;
    margin-bottom: 16px;
}
/* A label and its input, stacked. A FLEX container, which is what makes the stacking and
   the gap work — and which is why prose must not use it: in a flex container every child
   becomes a flex item, INCLUDING the anonymous items formed by bare text runs either side
   of inline markup. A sentence containing a <b> therefore breaks into three items and, in a
   column, three lines. Prose goes in .nv-dialog__text. */
.nv-dialog__field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 16px;
}
/* A paragraph of explanation in a dialog. An ordinary block, so inline markup stays
   inline. */
.nv-dialog__text {
    margin-bottom: 16px;
    line-height: 1.4;
}
.nv-dialog__label {
    font-weight: 600;
    font-size: 0.9em;
}
/* The global reset strips borders and padding from inputs, so a field in here needs its
   own frame — without one, an empty text input is invisible against the dialog. */
.nv-dialog__input {
    padding: 8px;
    width: 100%;
    box-sizing: border-box;
    font-size: 1em;
    border: 1px solid var(--border-table);
    border-radius: 3px;
    background: var(--bg-core);
    color: var(--text-primary);
}
.nv-dialog__error {
    color: var(--text-error);
    font-weight: 600;
    margin-bottom: 12px;
}

/* ----------------------------
 * Start treatment dialog (patient page)
 * ---------------------------- */
/* Frame, backdrop, title, fields, labels and errors all come from .nv-dialog and its
   content elements. This block carries only what is genuinely this dialog's own: it is
   wider than the shared default, because a treatment's display name carries its id and the
   description needs room to be read rather than skimmed. */
.treatment-start {
    max-width: 460px;
}
/* The global reset strips borders and padding from form controls, so a control in here
   needs its own frame — without one, a select is invisible against the dialog. */
.treatment-start__select {
    padding: 8px;
    width: 100%;
    box-sizing: border-box;
    font-size: 1em;
    border: 1px solid var(--border-table);
    border-radius: 3px;
    background: var(--bg-core);
    color: var(--text-primary);
}
/* Read-only, and styled to say so: no focus ring, no caret, and a flatter ground than the
   controls above it, so it does not invite editing. A fixed minimum height keeps the
   dialog from resizing as the selection moves between a short description and a long one. */
.treatment-start__description {
    padding: 8px;
    min-height: 3.4em;
    box-sizing: border-box;
    border: 1px solid var(--border-table);
    border-radius: 3px;
    background: var(--bg-active);
    color: var(--text-primary);
    line-height: 1.4;
    overflow-wrap: anywhere;
}
/* Session idle-timeout warning (layout.html).
 *
 * Follows the .ap-confirm pattern: a native <dialog> opened with showModal(), so the backdrop
 * and focus trapping come from the platform rather than from us. A little wider than
 * .ap-confirm because the countdown makes the message a line longer.
 */
.session-timeout {
    border: 1px solid var(--border-table);
    border-radius: 6px;
    padding: 20px 22px;
    max-width: 420px;
    color: var(--text-primary);
    font-size: 14px;
}
.session-timeout::backdrop {
    background: rgba(0, 0, 0, 0.35);
}
.session-timeout__title {
    font-weight: bold;
    font-size: 16px;
    margin-bottom: 10px;
}
.session-timeout__message {
    margin-bottom: 18px;
    line-height: 1.4;
}
/* Tabular figures so the countdown does not jitter as digits change, and bold so the number
   the user is deciding against is the thing they see first. */
.session-timeout__countdown {
    font-variant-numeric: tabular-nums;
    font-weight: bold;
}
.session-timeout__actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
}
/* Show the focus ring on programmatic focus too: "Stay signed in" is focused when the dialog
   opens, and the user needs to see that Enter will keep them signed in. */
.session-timeout__button:focus {
    outline: 2px solid #3f6fb0;
    outline-offset: 2px;
}

/* ----------------------------
 * Device status (menubar, right)
 * ---------------------------- */
.device-status {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    margin-right: 12px;
    background: var(--bg-device-status);
    border: 1px solid var(--border-device-status);
    border-radius: 12px;
    font-size: 0.85em;
    color: var(--text-menubar-secondary);
    white-space: nowrap;
    cursor: default;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.device-status__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--bg-device-none);
    flex: 0 0 auto;
}
.device-status--unknown {
    visibility: hidden;
}

/* The indicator's two texts. Both are anchors, and both are styled by whether they
   currently HAVE an href: an anchor without one is not a link and must not look like one.
   Only the text responds to hover, not the box, so it is clear which of the two is about
   to be followed. */
.device-status__link {
    color: inherit;
    text-decoration: none;
    cursor: default;
    /* Dimmed slightly so that full opacity on hover reads as brightening. Opacity rather
       than a second colour per link, so it goes on working whatever the background and
       the patient-id colour are set to. */
    opacity: 0.82;
}
.device-status__link[href] {
    cursor: pointer;
}
.device-status__link[href]:hover,
.device-status__link[href]:focus-visible {
    opacity: 1;
}
.device-status__nid {
    font-weight: bold;
    color: var(--text-menubar-patient-id);
}
.device-status--none .device-status__dot {
    background: var(--bg-device-none);
}
.device-status--on {
    color: var(--text-menubar-primary);
}
.device-status--on .device-status__dot {
    background: var(--bg-device-on);
}

@media (max-width: 700px) {
    .device-status__label {
        display: none;
    }
    .device-status {
        padding: 3px 6px;
        margin-right: 6px;
    }
}

/* ----------------------------
 * Hidden
 * ---------------------------- */

/* The one way anything in this app is hidden.
 *
 * NOT the `hidden` attribute. That is implemented by a single user-agent rule,
 * `[hidden] { display: none }`, and an author rule beats a user-agent rule whatever its
 * specificity — so `hidden` is silently inert on any element whose class sets `display`,
 * which is most components. It looked right in the markup and in devtools while the
 * element stayed on screen.
 *
 * Deliberately LAST in this file. It is one class, so it has the same specificity as the
 * component rules it has to beat, and source order is what decides between them. Anything
 * added below this line that sets `display` on a class will win over it.
 *
 * Also deliberately not `!important`: nothing here needs to outrank a considered rule, only
 * to come after it.
 */
.is-hidden {
    display: none;
}
