.nav-fixed .topnav {
    z-index: 1039;
}

.fixed-top{
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1030;
}

.topnav {
    padding-left: 0;
    height: 3.5rem;
    z-index: 1039;
}

.navbar .form-control, .topnav {
    font-size: 1rem;
}

.form-control {
    display: block;
    padding: .375rem .75rem;
    font-size: 1rem;
    line-height: 1.5;
    color: #495057;
    background-color: #fff;
    background-clip: padding-box;
    border: 1px solid #ced4da;
    border-radius: .25rem;
    transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}

.form-control-inline {
    display: inline-block;
}

.shadow {
    box-shadow: 0 .15rem 1.75rem 0 rgba(31,45,65,.15);
}
.bg-white {
    background-color: #fff;
}

.bg-gray {
    background-color: #eee;
}

.profile {
    width: 230px;
}

.profile-logo {
    float: left;
    width: 50px;
    height: 50px;
    background: #b681c3;
    border-radius: 25px;
    text-align: center;
    vertical-align: middle;
    font-size: 1.4em;
    padding: 7px;
    color: #f9f9f9;
}

.profile-info {
    float: left;
    margin-left: 10px;
    margin-top: 8px;
    color: #616263;
    width: 120px;
}

.user-logout {
    float: right;
    text-align: center;
}

.logout-icon {
    display: block;
    font-size: 1.5em;
}

.logout-text {
    font-size: .7em;
}

.profile-info span {
    display: block;
    line-height: 1.2;
    text-transform: capitalize;
}

#permspan {
    font-size: .9em;
    color: #108e07;
    font-style: italic;
}

#chpwspan a {
    padding: 4px 0;
    font-size: 0.9em;
    color: #e4157e;
}

#chpwspan.invisible {
    display: none;
}

.sidenav .user-logout a {
    font-size: 1em;
    padding: 7px 0 0;
    color: #e4157e;
    cursor: pointer;
    line-height: .7;
}

.sidenav .user-logout a:hover {
    color: #ab0659;
}

.navbar, .navbar .container, .navbar .container-fluid, .navbar .container-lg, .navbar .container-md, .navbar .container-sm, .navbar .container-xl {
    display: -webkit-box;
    display: flex;
    flex-wrap: wrap;
    -webkit-box-align: center;
    align-items: center;
    -webkit-box-pack: justify;
    justify-content: space-between;
    background: #610a86;
}
.navbar {
    position: relative;
    padding: .1rem;
}

.topnav .navbar-brand {
    width: 15rem;
    padding-left: 1rem;
    padding-right: 1rem;
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
}

.btn {
    display: inline-block;
    font-weight: 400;
    font-size: 1em;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    border: 1px solid transparent;
    padding: 0.255rem .75rem;
    line-height: 1.5;
    border-radius: .25rem;
    transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}

.btn {
    transition-duration: 0.4s;
}

.btn-default:hover {
    color: #fff;
    background-color: #545b62;
    border-color: #4e555b;
}

.btn-default {
    color: #fff;
    background-color: #6c757d;
    border-color: #6c757d;
}

.btn:not(:disabled):not(.disabled) {
    cursor: pointer;
}

.btn-success {
    color: #fff;
    background-color: #28a745;
    border-color: #28a745;
}

.btn-success:hover {
    color: #fff;
    background-color: #218838;
    border-color: #1e7e34;
}

.btn-cancel {
    color: #fff;
    background-color: #dc3545;
    border-color: #dc3545;
}

.btn-cancel:hover {
    color: #fff;
    background-color: #c82333;
    border-color: #bd2130;
}

.btn-blue {
    color: #fff;
    background-color: #007bff;
    border-color: #007bff;
}

.btn-blue:hover {
    color: #fff;
    background-color: #0069d9;
    border-color: #0062cc;
}

.btn-warn {
    color: #ffc107;
    background-color: transparent;
    background-image: none;
    border-color: #ffc107;
}

.btn-warn:hover {
    color: #212529;
    background-color: #ffc107;
    border-color: #ffc107;
}

.btn-large {
    font-size: 110%;
}

.app {
    background-color: #f4f4f4;
    overflow: hidden;
    margin: 0;
    padding: 0;
    box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .06), 0 2px 5px 0 rgba(0, 0, 0, .2);
}

.coln-left {
    flex: 30%;
    padding: 0;
    margin: 0;
}

.coln-left-hide {
  flex: 0;
}

.coln-right {
    flex: 70%;
    position: relative;
}

/* Clear floats after the columns */
.row {
    display: flex;
}

.full-height {
    height: calc(var(--vh, 1vh) * 100);
}

.full-width {
    width: calc(100vw - 200px);
    height: calc(var(--vh, 1vh) * 100);
}

.full-width-active {
    width: 100vw;
}

.container {
    width: 100%;
}

.users-header {
    height: 3.5rem;
    padding: 10px;
    background: #610a86;
    font-size: .95rem;
    font-weight: 500;
}

.users-header:after, .profile-user:after, .users-header:before {
    display: table;
    content: " ";
}

.users-header:after, .profile-user:after {
    clear: both;
}

.reply {
    height: 53px;
    width: 100%;
    background-color: #eae7e5;
    padding: 10px 5px 10px 5px;
    margin: 0;
    z-index: 1000;
}

.reply textarea {
    width: 100%;
    resize: none;
    overflow: hidden;
    padding: 5px;
    outline: none;
    border: none;
    text-indent: 5px;
    box-shadow: none;
    height: 100%;
}

textarea.form-reply {
    height: 2.1em;
    margin-right: .5em;
}

.form-reply {
    display: block;
    width: 100%;
    height: 34px;
    padding: 6px 12px;
    font-size: 1rem;
    color: #555;
    background-color: #fff;
    background-image: none;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
    transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
}

.form-reply::placeholder {
  opacity: .7;
}

.select {
    display: block;
    width: 100%;
    padding: .275rem .75rem;
    font-size: 1rem;
    line-height: 1.5;
    color: #495057;
    background-color: #fff;
    background-clip: padding-box;
    border: 1px solid #ced4da;
    border-radius: .25rem;
    transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}

.select-inline {
    display: inline-block;
}

.message {
    width: auto !important;
    padding: 4px 10px 7px !important;
    background: #daf1c6;
    font-size: 12px;
    box-shadow: 0 1px 1px rgba(43, 43, 43, 0.16);
    border-radius: 5px;
    word-wrap: break-word;
    display: inline-block;
    margin: 1em 0 0;
    max-width: 90%;
    text-align: left;
}

.message-sender {
    background: #e6e6e6;
}

.message-private {
    background: white;
}

.message-private .message-header:after {
    content: "(private)";
    margin-left: 1em;
}

.message-system {
    font-size: 10px;
    background: #ececec;
}

.message-row:after, .message-row:before {
    display: table;
    content: " ";
}

.message-row:after {
    clear: both;
}

.message-content {
    white-space: pre-wrap;
    margin: 0;
    padding: 0;
    padding-left: 5px;
    word-wrap: break-word;
    word-break: break-word;
    font-weight: 400;
    font-size: 14px;
    color: #202035;
}

.message-header {
    margin: 0;
    font-style: italic;
    text-shadow: none;
}

.message-footer {
    margin: 0;
    padding: 0;
    margin-bottom: -5px;
    line-height: .9;
    text-align: right;
}

.message-time {
    margin-left: 1em;
}

.message-me-asterisk, .message-me-user {
    margin-right: 0.33em;
}

.message-me-content {
    white-space: pre-wrap;
}

.video-container {
    height: calc(var(--vh, 1vh) * 100);
    position: relative;
    background: rgba(0, 0, 0, 0.91);
    /* Display only when showing video */
    display: block;
}

.chat-btn {
    display: block;
    /*on top of video peers*/
    z-index: 1002;
    font-size: 1.8em;
    position: absolute;
    top: 10px;
    left: 10px;
    cursor: pointer;
}

.chat-btn .icon-chat {
    color: #cac7c7;
    height: 50px;
    padding: 10px;
    text-shadow: 0px 0px 1px #b3adad;
}

.collapse-video {
    left: inherit;
    right: 30px;
}

.video-controls, .top-video-controls {
    position: absolute;
    width: 100%;
    left: 0;
    bottom: 25px;
    text-align: center;
    color: #eaeaea;
    font-size: 1.1em;
    opacity: 0;
    height: 32px;
}

.video-controls:after, .top-video-controls:after {
    clear: both;
    display: table;
    content: " ";
}

.top-video-controls {
    text-align: right;
    bottom: inherit;
    top: 0;
    line-height: 1.1;
    font-size: 1.3em;
    text-shadow: 1px 1px 2px rgb(90 86 86);
}

.controls-button {
    padding: 3px 10px;
    vertical-align: middle;
    height: 100%;
}

.controls-left {
    float: left;
    text-align: left;
}

.controls-right {
    float: right;
    text-align: right;
}

.vc-overlay {
    background: linear-gradient(180deg, rgb(0 0 0 / 20%) 0%, rgb(0 0 0 / 50%) 0%, rgb(0 0 0 / 70%) 100%);
}

.peer:hover > .video-controls, .peer:hover > .top-video-controls {
    opacity: 1;
}

.video-controls span, .top-video-controls span {
    margin-right: 20px;
    transition: opacity .7s ease-out;
    opacity: 1;
    cursor: pointer;
}

.video-controls span:last-child, .top-video-controls span:last-child {
    margin-right: 0;
}

.video-controls span:hover, .top-video-controls span:hover {
    opacity: .8;
    transition: opacity .5s ease-out;
}

/* The hide-self button is now an eye icon (fa-eye when self is visible,
   fa-eye-slash in the floating pill when self is hidden). The pill below
   has its own visual treatment. (Oryn) */
.top-video-controls .video-hide,
.self-controls-pill .video-hide {
    display: inline-flex;
    width: 1.5em;
    height: 1.5em;
    background: rgba(0,0,0,0.5);
    border-radius: 50%;
    justify-content: center;
    align-items: center;
    color: #eaeaea;
    font-size: 0.9em;
    cursor: pointer;
    user-select: none;
    vertical-align: middle;
}
.top-video-controls .video-hide:hover,
.self-controls-pill .video-hide:hover { opacity: .85; }

.video-controls .volume {
    display: inline-block;
    text-align: center;
}

.video-controls .video-play {
    font-size: 0.85em;
}

.video-controls .video-stop {
    color: #d03e3e;
}

.video-controls span.disabled, .video-controls span.disabled:hover, .top-video-controls span.disabled:hover{
    opacity: .2;
    color: #c8c8c8
}

.mobile-container {
    display: block !important;
}

.login-container {
    height: calc(var(--vh, 1vh) * 100);
    position: relative;
    display: flex;
    justify-content: center;
    overflow: scroll;
}

.login-box {
    width: 20em;
    padding: 1em;
    margin: 5em auto;
    height: 23em;
    background: #fcfcfc;
}

.login-box .connect {
    width: 100%;
    text-align: center;
}

.login-box h2 {
    text-align: center;
    margin-bottom: 40px;
}

.label-fallback {
    opacity: 0.5;
}

.label {
    left: 0;
    position: absolute;
    bottom: 0;
    width: 100%;
    z-index: 1;
    text-align: center;
    line-height: 24px;
    color: #ffffff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}

.nav-link {
    padding: 0;
    color: #dbd9d9;
    min-width: 30px;
    display: block;
    text-align: center;
    margin: 0 10px;
    position: relative;
    line-height: 1.1;
}

.nav-link span {
    display: block;
}

.nav-link label {
    display: block;
    cursor: pointer;
    color: #fff;
    font-size: 55%;
}

.nav-link:hover {
    color: #c2a4e0;
}
.nav-link label:hover {
    color: #c2a4e0;
}

.nav-cancel, .muted, .nav-cancel label, .muted label {
    color: #d03e3e
}

.nav-cancel:hover, .muted:hover, .nav-cancel label:hover, .muted label:hover {
    color: #d03e3e
}

.nav-button {
    cursor: pointer;
    font-size: 25px;
}

.nav-more {
    padding-top: 5px;
    margin-left: 0;
}

.header-title {
    float: left;
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
    color: #ebebeb;
    line-height: 2em;
}

#title {
    text-align: center;
}

h1 {
    white-space: nowrap;
}

#statdiv {
    white-space: nowrap;
    margin-bottom: 16px;
}

#errspan {
    margin-left: 1em;
}

.connected {
    color: green;
}

.disconnected {
    color: red;
    font-weight: bold;
}

.login {
    display: inline
}

.loginform label {
    min-width: 3em;
    display: inline-block;
    padding-top: 10px;
}

.loginform input[type="text"], .loginform input[type="password"] {
    width: 100%;
}

.switch-radio {
    margin: 0;
}

.invisible {
    display: none;
}

.error {
    color: red;
    font-weight: bold;
}

.noerror {
    display: none;
}

.clear {
    clear: both;
    content: "";
}

#optionsdiv {
    margin-bottom: 4px;
}

#optionsdiv input[type="checkbox"] {
  vertical-align: middle;
}

#presentbutton, #unpresentbutton {
    white-space: nowrap;
    margin-right: 0.4em;
    margin-top: .1em;
    font-size: 1.1em;
    text-align: left;
    width: 5.8em;
}

#videoselect {
    text-align-last: center;
    margin-right: 0.4em;
}

#audioselect {
    text-align-last: center;
}

#sharebutton, #unsharebutton {
    white-space: nowrap;
}

#unsharebutton {
    margin-right: 0.4em;
}

#filterselect {
    text-align-last: center;
    margin-right: 0.4em;
}

#sendselect {
    text-align-last: center;
    margin-right: 0.4em;
}

#simulcastselect {
    text-align-last: center;
    margin-right: 0.4em;
}

#requestselect {
    text-align-last: center;
}

#chatbox {
    height: 100%;
    position: relative;
}

#chat {
    padding: 0;
    margin: 0;
    background-color: #f8f8f8;
    background-size: cover;
    overflow-y: scroll;
    border: none;
    border-right: 4px solid #e6e6e6;
    /* force to fill height */
    height: 100% !important;
    width: 100%;
    min-width: 300px;
    overflow: hidden;
}

#inputform {
    display: flex;
}

#box {
    overflow: auto;
    height: calc(100% - 53px);
    padding: 10px;
}

.close-chat {
    position: absolute;
    top: 2px;
    right: 14px;
    width: 25px;
    font-size: 1em;
    text-align: center;
    font-weight: 700;
    color: #8f8f8f;
    cursor: pointer;
    border: 1px solid transparent;
}

.close-chat:hover, .close-chat:active {
    border: 1px solid #dfdfdf;
    border-radius: 4px;
}

#connectbutton {
    margin-top: 1em;
    padding: 0.37rem 1.5rem;
}

#input {
    width: 100%;
    border: none;
    resize: none;
    overflow-y: hidden;
}

#input:focus {
    outline: none;
}

#inputbutton:focus {
    outline: none;
}

#resizer {
    width: 4px;
    margin-left: -4px;
    z-index: 1000;
}

#resizer:hover {
    cursor: ew-resize;
}

#peers {
    padding: 10px;
    display: grid;
    grid-template-columns: repeat(1, 1fr);
    grid-template-rows: repeat(1, auto);
    row-gap: 5px;
    column-gap: 10px;
    position: absolute;
    top: 0;
    right: 0; 
    bottom: 0;
    min-width: 100%; 
    min-height: 100%;
    width: auto; 
    height: auto; 
    z-index: 1000;
    background-size: cover;
    overflow: hidden;
    vertical-align: top!important;
}

.peer {
    margin-top: auto;
    margin-bottom: auto;
    position: relative;
    border: 2px solid rgba(0,0,0,0);
    background: #80808014;
}

.peer-active {
    border: 2px solid #610a86;
}

.peer-hidden {
    display: none;
}

.media {
    width: 100%;
    max-height: calc(var(--vh, 1vh) * 100 - 76px);
    padding-bottom: 20px;
    object-fit: contain;
}

.media-failed {
    filter: grayscale(0.5) contrast(0.5);
}

.mirror {
    transform: scaleX(-1);
}

#inputform {
    width: 100%;
}

.sidenav {
    background-color: #4d076b;
    box-shadow: 0 0 24px 0 rgba(71,77,86,.1), 0 1px 0 0 rgba(71,77,86,.08);
    display: block;
    position: fixed;
    -webkit-transition: all .2s ease-out;
    transition: all .2s ease-out;
    width: 0px;
    /* on top of everything */
    z-index: 2999;
    top: 0;
    right: 0;
    height: calc(var(--vh, 1vh) * 100);
    overflow-x: hidden;
    overflow-y: hidden;
}

.sidenav a {
    padding: 10px 20px;
    text-decoration: none;
    font-size: 30px;
    color: #dbd9d9;
    display: block;
    transition: 0.3s;
    line-height: 1.0;
}

.sidenav a:hover {
    color: #c2a4e0;
}

.sidenav .closebtn {
    cursor: pointer;
    position: absolute;
    top: 0;
    right: 0;
    height: 56px;
}

.sidenav-label {
    display: block;
    margin-top: 15px;
}

.sidenav-label-first {
    display: block;
    margin-top: 0;
}

.sidenav form{
    margin-top: 15px;
}

.sidenav-header {
    height: 56px;
    display: flex;
    align-items: center;
    padding: 0 14px;
    border-bottom: 1px solid var(--divider);
}

.sidenav-header h2{
    color: #fff;
    padding: 10px;
    margin: 0;
    max-width: 70%;
    line-height: 36px;
}

.sidenav-content {
    padding: 10px;
    background: #fff;
    height: calc(100% - 56px);
    overflow-y: auto;
    overflow-x: hidden;
}

.sidenav-content h2 {
    margin: 0;
}

fieldset {
    margin: 0;
    margin-top: 20px;
    border: 1px solid #e9e8e8;
    padding: 8px;
    border-radius: 4px;
}
legend {
    padding: 2px;
    color: #4d4f51;
}

.nav-menu {
    margin: 0;
    padding: 0;
}

.nav-menu li {
    float: left;
    max-height: 70px;
    list-style: none;
}

.show-video {
    position: absolute;
    right: 30px;
    bottom: 120px;
    color: white;
    width: 50px;
    height: 50px;
    text-align: center;
    line-height: 50px;
    font-size: 150%;
    border-radius: 30px;
    background: #600aa0;
    box-shadow: 4px 4px 7px 1px rgba(0,0,0,0.16);
}

.blink {
    -ms-animation: blink 1.0s linear infinite;
    -o-animation: blink 1.0s linear infinite;
    animation: blink 1.0s linear infinite;
}

@keyframes blink {
    0% { box-shadow: 0 0 15px #600aa0; }
    50% { box-shadow: none; }
    100% { box-shadow: 0 0 15px #600aa0; }
}

@-webkit-keyframes blink {
    0% { box-shadow: 0 0 15px #600aa0; }
    50% { box-shadow: 0 0 0; }
    100% { box-shadow: 0 0 15px #600aa0; }
}

/*  Sidebar left */

#left-sidebar {
    min-width: 200px;
    max-width: 200px;
    /* z-index is meaningless without a non-static position; pin relative so
       the visible panel can sit above the fixed E2EE lock (z:1041) and
       physically cover it at the top-left. */
    position: relative;
    transition: all 0.3s;
    background: #ffffff;
    border-right: 1px solid #dcdcdc;
}

#left-sidebar .galene-header {
    display: inline-block;
}

header .collapse {
    float: left;
    text-align: center;
    cursor: pointer;
    font-size: 20px;
    color: #dbd9d9;
    margin-right: 20px;
    margin-left: 5px;
}

header .collapse:hover {
    color: #c2a4e0;
}

.galene-header {
    font-size: 1.3rem;
    font-weight: 900;
    color: #dbd9d9;
    line-height: 34px;
}

.header-sep {
    height: 20px;
}

/* Shrinking the sidebar from 200px to 0px */
#left-sidebar.active {
    min-width: 0;
    max-width: 0;
}

#left-sidebar .sidebar-header strong {
    display: none;
}
#left-sidebar.active .sidebar-header h3 {
    display: none;
}
#left-sidebar.active .sidebar-header strong {
    display: block;
}

#users {
    padding: 0;
    margin: 0;
    height: calc(100% - 84px);
    width: 100%;
    position: relative;
    display: block;
    background-color: #fff;
    overflow-y: auto;
    border: 1px solid #f7f7f7;
}

#users .user-p {
    position: relative;
    padding: 10px !important;
    border-bottom: 1px solid #f0f0f0;
    height: 40px;
    line-height: 18px;
    margin: 0 !important;
    cursor: pointer;
    overflow: hidden;
    white-space: pre;
}

#left-sidebar.active #users > div {
    padding: 10px 5px !important;
}

#users > div:hover {
    background-color: #f2f2f2;
}

#users .knock-p {
    background-color: #fff4d6;
    cursor: default;
    height: auto;
    white-space: normal;
}

#users .knock-p .knock-label {
    display: block;
    font-weight: bold;
    margin-bottom: 6px;
}

#users .knock-p button {
    margin-right: 6px;
    padding: 3px 10px;
    cursor: pointer;
}

#users .knock-p .knock-admit {
    background-color: #2e7d32;
    color: #fff;
    border: none;
    border-radius: 3px;
}

#users .knock-p .knock-deny {
    background-color: #c62828;
    color: #fff;
    border: none;
    border-radius: 3px;
}

.lobby-note {
    margin: 0 0 14px 0;
    font-style: italic;
    color: #555;
}

#lobby-waiting .login-box {
    text-align: center;
}

#lobby-waiting h2 {
    margin-top: 0;
}

#lobby-waiting-text {
    font-size: 1.1em;
}

#users > div::before {
    content: "\f111";
    font-family: 'Font Awesome 6 Free';
    color: #20b91e;
    margin-right: 5px;
    font-weight: 900;
}

#users > div.user-status-raisehand::before {
    content: "\f256";
}

#users > div::after {
    font-family: 'Font Awesome 6 Free';
    color: #808080;
    margin-left: 5px;
    font-weight: 900;
    float: right;
}

#users > div.user-status-microphone::after {
    content: "\f130";
}

#users > div.user-status-camera::after {
    content: "\f030";
}

/* ==========================================================================
   Oryn — per-user volume slider in the participant list
   Each user row gets a small mute icon and a slider that controls the audio
   element for that user's stream(s). The state lives in memory only (a
   refresh resets it). The slider sits at the far right of the row alongside
   the existing mic/cam glyph, with stopPropagation so clicking it doesn't
   open the row's context menu. (Oryn)
   ========================================================================== */
#users .user-p .up-volume {
    float: right;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 6px;
}
#users .user-p .up-volume .up-volume-mute {
    cursor: pointer;
    font-size: 0.9em;
    width: 18px;
    text-align: center;
    color: #808080;
}
#users .user-p .up-volume .up-volume-mute.muted {
    color: #d03e3e;
}
#users .user-p .up-volume .up-volume-slider {
    width: 60px;
    height: 4px;
    cursor: pointer;
    vertical-align: middle;
}
/* Dark theme: keep the slider legible. */
@media (prefers-color-scheme: dark) {
    #users .user-p .up-volume .up-volume-mute { color: #b0b0b0; }
    #users .user-p .up-volume .up-volume-mute.muted { color: #ff6b6b; }
}

.close-icon {
    font: normal 1em/1 Arial, sans-serif;
    display: inline-block;
}

.close-icon:before{ content: "\2715"; }

/* END Sidebar Left */

@media only screen and (min-width: 1025px) {
    .coln-right .collapse-video, .coln-right .show-video {
        display: none;
    }
}

@media only screen and (max-width: 1024px) {
    #presentbutton, #unpresentbutton {
        width: auto;
    }
    .nav-link {
        margin: 0 4px;
        line-height: 1.5;
    }

    .nav-link label {
        display: none;
    }

    .nav-text {
        display: none;
    }

    .nav-more {
        padding-top: 0;
        margin-left: inherit;
    }

    .full-width {
        height: calc(var(--vh, 1vh) * 100);
    }

    .close-chat, .show-chat {
        display: none;
    }

    .video-container {
        position: fixed;
        height: calc(var(--vh, 1vh) * 100);
        top: 0;
        right: 0;
        left: 0;
    }

    .top-video-controls {
        opacity: 1;
    }

    /* No hover on touch.  The old tap-to-reveal fought the immersive tap (which
       toggles the whole chrome): the tap that should have shown these controls
       slid the bar away and stripped them, so volume / fullscreen / picture-in-
       picture were effectively dead.  Show the on-video controls whenever the
       chrome is up instead, and hide them with the chrome when going immersive
       (body.nav-hidden) so the picture is still clean full-screen. (Oryn) */
    .video-controls {
        opacity: 1;
        pointer-events: auto;
        transition: opacity .3s ease-out;
    }
    /* Immersive (chrome hidden): clear the picture of every on-video control. */
    body.nav-hidden .video-controls,
    body.nav-hidden .top-video-controls {
        opacity: 0;
        pointer-events: none;
    }
    .vc-overlay {
        background: linear-gradient(180deg,
            rgba(0, 0, 0, 0) 0%,
            rgba(0, 0, 0, 0.4) 100%);
        -webkit-backdrop-filter: blur(1px);
        backdrop-filter: blur(1px);
    }

    .login-container {
        position: fixed;
        height: calc(var(--vh, 1vh) * 100 - 56px);
        top: 56px;
        right: 0;
        left: 0;
        background: #eff3f9;
    }

    .login-box {
        background: transparent;
    }

    .coln-left {
        flex: 100%;
        width: 100vw;
        /* chat is always visible here */
        display: block !important;
    }

    .coln-right {
        flex: none;
        position: relative;
    }

    .full-width {
        width: 100vw;
    }

    #left-sidebar.active {
        min-width: 200px;
        max-width: 200px;
        /* on top of video peers and on top of the E2EE lock (z:1041) — when
           the panel is open it physically covers the lock, no hide/show
           needed. */
        z-index: 1050;
    }

    /* The people+chat panel overlays the video on mobile; the floating chat /
       show-video buttons live in the video pane and would otherwise peek out
       beside the open panel as an orphaned chat bubble. Hide them while the
       panel is open. (Oryn) */
    #left-sidebar.active ~ .container .collapse-video,
    #left-sidebar.active ~ .container .show-video {
        display: none !important;
    }

    #left-sidebar {
        min-width: 0;
        max-width: 0;
    }

    /* Reappearing the sidebar on toggle button click */
    #left-sidebar {
        margin-left: 0; 
    }

    #left-sidebar .sidebar-header strong {
        display: none;
    }

    #left-sidebar.active .sidebar-header h3 {
        display: none;
    }

    #left-sidebar.active .sidebar-header strong {
        display: block;
    }

    .sidenav a {padding: 10px 10px;}

    .sidenav-header h2 {
        line-height: 36px;
    }

    #peers {
        padding: 3px;
    }

    #resizer {
        display: none;
    }

    #chat {
        border-right: none;
    }

    .dropdown-content {
        margin-top: 10px;
    }

}

#captions-container {
    position: absolute;
    bottom: 40px;
    width: 100%;
    pointer-events: none;
    z-index: 1390;
    alpha: 0;
}

#captions {
    margin: auto;
    padding: 0 0.4rem 0 0.4rem;
    width: max-content;
    font-size: 1.2rem;
    text-align: center;
    pointer-events: none;
    background-color: rgba(255,255,255,.7);
    color: #000;
}

:root{
    --contextualMenuBg: #eee;
    --contextualMenuShadow: 1px 1px 1px #444; */
    --contextualMenuRadius: 0px; */
    --contextualMenuText: black;

    --contextualSubMenuBg: #eee;

    --contextualHover: #ddd;

    --contextualOverflowIcon: #999;
    --contextualSeperator: #999;
}

.contextualMenu{
    z-index: 2999;
}

.file-progress {
    accent-color: #610a86;
    margin-left: 10px;
    margin-right: 10px;
}

#invite-dialog {
    background-color: #eee;
}

#invite-dialog {
    border: solid 2px #610a86;
}

#invite-dialog button {
    background-color: #3355ff;
    color: white;
    border-radius: .5em;
    padding: .5em;
    margin-top: 1em;
    margin-bottom: 1em;
    margin-right: 2em;
    display: inline-block;
    width: 7em;
}

#invite-dialog button:hover {
   background-color: #0022ff;
}

#invite-dialog input {
    margin-top: 1em;
    width: 16em;
    padding: .2em
}

#invite-dialog label {
    margin-top: 1em;
    display: inline-block;
    width:12em;
}

/* Style for the toastify  messages shall be within a css file */
.toastify.error {
    background: linear-gradient(to right, #e20a0a, #df2d2d);
    color: #fff;
}
.toastify.error .toast-close {
    color: #fff;
}
.toastify.warning {
    background: linear-gradient(to right, #bdc511, #c2cf01);
    color: #000;
}
.toastify.warning .toast-close {
    color: #000;
}
.toastify.info {
    background: linear-gradient(to right, #529518, #96c93d);
    color: #000;
}
.toastify.info .toast-close {
    color: #000;
}

/* ==========================================================================
   Oryn — dark theme + rebrand
   --------------------------------------------------------------------------
   This block restyles the upstream Galène UI to the Oryn design system
   (dark-first, blue->violet accent, soft shapes). The original rules above
   are left untouched so that `git merge upstream/master` stays clean; this
   section simply overrides their colours/shapes by source order. Tokens are
   defined in common.css (:root).
   ========================================================================== */

/* --- Brand lockup (left sidebar) ----------------------------------------- */
#left-sidebar .galene-header {
    display: flex;
    align-items: center;
    color: var(--text);
}

/* --- Top bar ------------------------------------------------------------- */
.navbar,
.navbar .container, .navbar .container-fluid, .navbar .container-lg,
.navbar .container-md, .navbar .container-sm, .navbar .container-xl {
    background: var(--surface);
}
.topnav {
    border-bottom: 1px solid var(--divider);
}
.header-title { color: var(--text); }
header .collapse { color: var(--text-2); transition: color var(--t-fast) var(--ease); }
header .collapse:hover { color: var(--accent); }

/* --- Immersive mode (Oryn) ----------------------------------------------- */
/* A tap (mobile) or click (desktop) on the central video area hides the dock
   + E2EE lock + panel-toggle; the next tap/click brings them back. The video
   itself does NOT move: there's no top bar to clear any more (the top bar was
   removed — its 56px strip was the source of the old up-shift on desktop and
   the grey strip on mobile), so the picture stays anchored to the viewport.
   Driven by the `nav-hidden` body class, toggled in galene.js. */

/* ==========================================================================
   Oryn — bottom control dock
   The call controls (camera / mic / share / view / more + Leave) live in a
   floating pill at the bottom centre of the stage, like every other call app.
   We do NOT rebuild them: the existing, already-wired .nav-menu is lifted out of
   the top bar and re-laid-out here, so every button keeps its id and handler.
   The top bar keeps only identity (panel toggle + E2EE lock). The dock hides
   with the rest of the chrome in immersive mode.
   ========================================================================== */
.nav-menu {
    position: fixed;
    /* Centre with left/right:0 + margin:auto rather than left:50% +
       translateX(-50%): the latter mis-resolved against this fixed flex pill
       (left:50% landed at the video-area centre, not the viewport). */
    left: 0;
    right: 0;
    bottom: 22px;
    width: max-content;
    max-width: calc(100vw - 24px);
    margin: 0 auto;
    z-index: 1040;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    list-style: none;
    background: rgba(18, 22, 28, 0.72);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    border: 1px solid var(--divider);
    border-radius: var(--radius-pill);
    box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.7);
    transition: opacity var(--t-base) var(--ease),
                transform var(--t-base) var(--ease);
}
.nav-menu li {
    margin: 0;
    padding: 0;
    list-style: none;
    /* Every li wraps a fixed-size 50px circle; lock the li itself to its
       content size so flex can't distribute leftover space unevenly between
       a button and a button-with-slightly-different-content. */
    flex: 0 0 auto;
}

/* Each control becomes a round button; the stacked text label is dropped (the
   title attribute still gives a tooltip). */
.nav-menu .nav-button {
    box-sizing: border-box;        /* the buttons live in the dock as either
                                      <button> or <div> — normalise so the
                                      <button>'s UA-default 2px padding does
                                      not push it 4px wider than its <div>
                                      siblings and break the equal gaps. */
    width: 50px;
    height: 50px;
    margin: 0;
    padding: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-3);
    border: 1px solid var(--divider);
    transition: background var(--t-fast) var(--ease);
}
/* The dock's display:flex must not override galene hiding the inactive control:
   the camera start/stop pair and the view toggle swap via .invisible, so keep
   that winning here — otherwise both camera buttons show at once. */
.nav-menu .nav-button.invisible { display: none; }
.nav-menu .nav-button:hover { background: var(--surface-2); }
/* Geometrically centre the glyph: flex the span and force line-height:1 so the
   varied FontAwesome glyph metrics (share / gear / phone-slash) don't sit low. */
.nav-menu .nav-button span {
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
.nav-menu .nav-button label { display: none; }
.nav-menu .nav-button i { font-size: 20px; display: block; line-height: 1; }
/* undo the top-bar camera-button sizing now that it is a dock circle */
.nav-menu #presentbutton,
.nav-menu #unpresentbutton { width: 50px; margin: 0; font-size: inherit; }
/* The dock is a flex pill — the only spacing between round buttons must come
   from `gap` on .nav-menu, not from the legacy .nav-link margins or the
   .nav-leave divider nudge. Both would otherwise add a hidden second gap and
   make the spacing drift between buttons of slightly different content. */
.nav-menu .nav-link { margin: 0; }
.nav-menu .nav-leave { margin-left: 0 !important; }
/* The decorative divider was drawn via ::before positioned at -7px from the
   leave button; with margin-left zeroed, push it back to sit between Leave
   and its neighbour by anchoring it to the left edge of the button. */

/* The people + chat toggle now lives in the dock too: undo its old fixed
   top-left pinning and render it as a dock circle. It keeps its id (so its
   click handler and the unread alert dot still work) and its composite
   person+chat icon. */
.nav-menu #sidebarCollapse {
    position: static;
    top: auto;
    left: auto;
    width: 50px;
    height: 50px;
    padding: 0;
    margin: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-3);
    border: 1px solid var(--divider);
    color: var(--text-2);
    cursor: pointer;
}
.nav-menu #sidebarCollapse:hover { background: var(--surface-2); color: var(--accent); }
.nav-menu #sidebarCollapse .panel-toggle-icon { font-size: 20px; }

/* Leave: a round red button, set off from the rest by a thin divider. */
.nav-leave {
    position: relative;
    margin-left: 6px !important;
    background: linear-gradient(135deg, #E0564F, #C2443F) !important;
    border: none !important;
    color: #fff !important;
}
.nav-leave::before {
    content: "";
    position: absolute;
    left: -4px;
    top: 50%;
    transform: translateY(-50%);
    width: 1px;
    height: 28px;
    background: var(--divider);
}
.nav-leave:hover { filter: brightness(1.08); }

/* The top bar is gone: the controls live in the dock and the E2EE lock floats
   above it. Make the (now empty) bar invisible and click-through, so taps on the
   top of the video still toggle immersive mode; the dock re-enables clicks. */
.topnav {
    background: none;
    border-bottom: none;
    pointer-events: none;
}
.nav-menu { pointer-events: auto; }

/* The empty top bar still took a ~56px strip in flow (and slid in/out with
   immersive mode). Collapse it to nothing so the video fills the whole viewport;
   the dock + lock float over the video and immersive just hides them via their
   own rules. */
header,
.topnav {
    height: 0;
    min-height: 0;
    padding: 0;
    border: none;
}
.full-width,
.video-container {
    height: calc(var(--vh, 1vh) * 100);
}

/* E2EE lock + SAS: pinned to the top-left corner. Only shows when the call
   is actually encrypted (.invisible otherwise); hidden in immersive mode. */
#header #e2ee-indicator {
    position: fixed;
    top: 16px;
    left: 16px;
    margin: 0;
    width: max-content;
    max-width: calc(100vw - 24px);
    z-index: 1041;
    pointer-events: auto;
    transition: opacity var(--t-base) var(--ease);
}
body.nav-hidden #e2ee-indicator {
    opacity: 0;
    pointer-events: none;
}

/* ✕ to close the people + chat panel from its own header (the toggle now lives
   in the dock, which fades when the panel is open on mobile, so this is the
   always-visible way out). */
.panel-close {
    margin-left: auto;
    flex: none;
    background: none;
    border: none;
    color: var(--text-2);
    cursor: pointer;
    font-size: 1.05rem;
    line-height: 1;
    padding: 6px 8px;
    border-radius: var(--radius-sm);
}
.panel-close:hover { color: var(--text); background: var(--hover); }

/* Immersive mode: the dock drops away with the rest of the chrome. */
body.nav-hidden .nav-menu {
    opacity: 0;
    transform: translateY(160%);
    pointer-events: none;
}

/* Phone: the dock sizes to its content and sits centred at the bottom, like
   the desktop pill — the old "span the screen and space-between" looked
   stretched on a phone. */
@media only screen and (max-width: 600px) {
    .nav-menu {
        left: 0;
        right: 0;
        width: max-content;
        max-width: calc(100vw - 24px);
        margin: 0 auto;
        justify-content: center;
        gap: 6px;
        padding: 8px 10px;
    }
    .nav-menu .nav-button,
    .nav-menu #presentbutton,
    .nav-menu #unpresentbutton { width: 46px; height: 46px; }
    .nav-menu .nav-button i { font-size: 18px; }
    body.nav-hidden .nav-menu { transform: translateY(160%); }
}

/* --- App shell ----------------------------------------------------------- */
.app {
    background-color: var(--bg);
    box-shadow: none;
}

/* --- Left sidebar + participants ----------------------------------------- */
#left-sidebar {
    background: var(--surface);
    border-right: 1px solid var(--divider);
}
.users-header {
    background: var(--surface);
    border-bottom: 1px solid var(--divider);
}
#users {
    background: var(--surface);
    border: none;
}
#users .user-p { border-bottom: 1px solid var(--divider); }
#users > div:hover { background-color: var(--hover); }
#users > div::before { color: var(--ok); }
#users > div::after { color: var(--text-3); }

/* Participant rows: round avatar (initial + presence dot) + name. The mic/cam
   glyph still floats in via ::after; presence moved off the old leading dot onto
   the avatar. Scoped :not(.knock-p) so lobby knock cards keep their own layout. */
#users .user-p:not(.knock-p) {
    display: flex;
    align-items: center;
    gap: 10px;
    height: auto;
    min-height: 46px;
    white-space: normal;
    overflow: visible;
}
#users .user-p:not(.knock-p)::before { content: ""; margin: 0; }
#users .user-p.user-status-raisehand:not(.knock-p)::before {
    content: "\f256";
    color: var(--warn);
    margin-right: 4px;
    flex: none;
}
#users .user-p:not(.knock-p)::after { float: none; flex: none; margin-left: 8px; }
.up-avatar {
    position: relative;
    flex: none;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 13px;
    font-weight: 500;
}
.up-ini { line-height: 1; }
.up-dot {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--ok);
    border: 2px solid var(--surface);
}
.up-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.up-avatar.av-0 { background: linear-gradient(135deg, #5B8CFF, #7A6CFF); }
.up-avatar.av-1 { background: linear-gradient(135deg, #2E9E5B, #1F7D49); }
.up-avatar.av-2 { background: linear-gradient(135deg, #D88C3A, #B56A25); }
.up-avatar.av-3 { background: linear-gradient(135deg, #7A6CFF, #9B5BD8); }
.up-avatar.av-4 { background: linear-gradient(135deg, #3FA9C9, #2F86A3); }

/* --- Lobby / knock requests ---------------------------------------------- */
#users .knock-p {
    background-color: var(--surface-2);
    border-left: 2px solid var(--accent);
}
#users .knock-p .knock-admit { background-color: #2E9E5B; }
#users .knock-p .knock-deny  { background-color: #B5524F; }
#users .knock-p .knock-admit,
#users .knock-p .knock-deny {
    min-width: 32px;
    padding: 5px 9px;
    border-radius: 6px;
    font-size: 0.95rem;
    line-height: 1;
}
.lobby-note { color: var(--text-2); }

/* --- Nav buttons --------------------------------------------------------- */
.nav-link { color: var(--text-2); transition: color var(--t-fast) var(--ease); }
.nav-link label { color: var(--text); }
.nav-link:hover, .nav-link label:hover { color: var(--accent); }
.nav-cancel, .muted, .nav-cancel label, .muted label,
.nav-cancel:hover, .muted:hover, .nav-cancel label:hover, .muted label:hover {
    color: var(--danger);
}

/* --- Chat ---------------------------------------------------------------- */
#chat {
    background-color: var(--surface);
    border-right: 1px solid var(--divider);
}
.close-chat { color: var(--text-2); }
.close-chat:hover, .close-chat:active { border-color: var(--divider); }
.reply {
    background-color: var(--surface-2);
    border-top: 1px solid var(--divider);
}
.reply textarea,
.form-reply {
    color: var(--text);
    background-color: var(--surface-3);
    border: 1px solid var(--divider);
    border-radius: var(--radius-sm);
    box-shadow: none;
}
.form-reply::placeholder { color: var(--text-3); }
#inputbutton { color: var(--accent); }

/* --- Messages: chat bubbles ---------------------------------------------- */
/* Received messages sit left on a neutral surface; your own (.message-sender)
   align right with an accent gradient; private messages keep the accent edge;
   system notes are centred and quiet. Builds on the upstream inline-block
   .message inside a clearfix .message-row. */
.message {
    background: var(--surface-2);
    box-shadow: none;
    border-radius: 13px;
    padding: 7px 11px 8px !important;
    margin-top: 0.7em;
}
.message-content { color: var(--text); font-size: 0.92rem; }
.message-header { color: var(--text-2); font-style: normal; font-size: 0.82rem; }
.message-time { color: var(--text-3); font-size: 0.72rem; }

/* Your own messages: pushed to the right with an accent gradient bubble. */
.message-row:has(.message-sender) { text-align: right; }
.message-sender {
    background: linear-gradient(135deg, rgba(91, 140, 255, 0.22), rgba(122, 108, 255, 0.20));
    border: 1px solid rgba(91, 140, 255, 0.28);
}

/* A private message you received keeps the accent edge. */
.message-private {
    background: var(--surface-3);
    border-left: 2px solid var(--accent);
}

/* System notices: centred, quiet, no bubble. */
.message-system {
    background: transparent;
    color: var(--text-3);
    display: block;
    text-align: center;
    max-width: 100%;
    font-size: 0.8rem;
}

/* --- Inputs / selects ---------------------------------------------------- */
.form-control,
.select {
    color: var(--text);
    background-color: var(--surface-3);
    border: 1px solid var(--divider);
    border-radius: var(--radius-sm);
}
.form-control::placeholder { color: var(--text-3); }

/* Focus: soft glow, not a hard outline */
.form-control:focus,
.select:focus,
.reply textarea:focus,
.form-reply:focus,
textarea:focus,
input:focus-visible,
.btn:focus-visible,
a:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--focus-ring);
}

/* --- Buttons ------------------------------------------------------------- */
.btn {
    border-radius: var(--radius-sm);
    letter-spacing: 0.01em;
}
.btn-default {
    color: var(--text);
    background-color: var(--surface-3);
    border-color: var(--divider);
}
.btn-default:hover {
    color: var(--text);
    background-color: var(--surface-2);
    border-color: var(--divider);
}
.btn-blue,
.btn-blue:hover {
    background: var(--accent-grad);
    border: none;
    color: #fff;
}
.btn-blue:hover { filter: brightness(1.08); }
.btn-success { background-color: #2E9E5B; border-color: #2E9E5B; }
.btn-success:hover { background-color: #2A8E52; border-color: #2A8E52; }
.btn-cancel { background-color: #B5524F; border-color: #B5524F; }
.btn-cancel:hover { background-color: #A24845; border-color: #A24845; }
.btn-warn { color: var(--warn); border-color: var(--warn); background: transparent; }
.btn-warn:hover { color: #1C1F24; background-color: var(--warn); border-color: var(--warn); }

/* --- Profile ------------------------------------------------------------- */
.profile-logo { background: var(--accent-grad); color: #fff; }
.profile-info { color: var(--text-2); }
#permspan { color: var(--ok); }
#chpwspan a,
.sidenav .user-logout a { color: var(--accent); }
.sidenav .user-logout a:hover { color: var(--accent-2); }

/* --- Login / join card --------------------------------------------------- */
.login-container { background: var(--bg); }
.login-box {
    background: var(--surface);
    border: 1px solid var(--divider);
    border-radius: var(--radius-lg);
    height: auto;
    align-self: flex-start;   /* don't let the flex container stretch (and clip) the card */
    padding: 1.75em;
}
.loginform label { color: var(--text-2); }

/* Quiet depth for the first screen, so it isn't a flat black field. A soft
   blue->violet aurora behind the card (echoes the brand-mark glow), a faint
   film grain so the near-black has texture, an elevated card with a 1px top
   highlight, and a gentle glow on the primary action. Scoped to body.pre-join
   — the only state in which the join card is shown. */
body.pre-join .login-container {
    background:
        radial-gradient(62% 52% at 20% 16%, rgba(91, 140, 255, 0.20), transparent 68%),
        radial-gradient(58% 48% at 84% 90%, rgba(122, 108, 255, 0.18), transparent 70%),
        var(--bg);
    position: relative;
    overflow-x: hidden;   /* clip grain overlay horizontally */
    overflow-y: auto;     /* allow scroll on short screens (landscape mobile) */
}
body.pre-join .login-container::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    opacity: 0.05;
}
body.pre-join .login-box {
    box-shadow:
        0 24px 60px -20px rgba(0, 0, 0, 0.65),
        inset 0 1px 0 rgba(255, 255, 255, 0.08);
    border-color: rgba(140, 148, 180, 0.18);
    position: relative;
    z-index: 1;
}
body.pre-join .btn-blue {
    box-shadow: 0 8px 24px -6px rgba(91, 140, 255, 0.55);
}

/* --- Settings drawer ----------------------------------------------------- */
.sidenav {
    background-color: var(--surface);
    box-shadow: var(--shadow-modal);
}
.sidenav-content {
    background: var(--surface);
    border-top: 1px solid var(--divider);
}
.sidenav-header h2,
.sidenav-content h2 { color: var(--text); }
.sidenav a { color: var(--text-2); }
.sidenav a:hover { color: var(--accent); }
fieldset { border: 1px solid var(--divider); border-radius: var(--radius-sm); }
legend { color: var(--text-2); }
/* The settings drawer drops the fieldset frames and section legends ("Media
   Options" / "Other Settings") to save space; the controls read as one list. */
.sidenav-content fieldset { border: none; padding: 0; margin: 0 0 0.5rem; }
.sidenav-content legend { display: none; }

/* Oryn — render the on/off settings as toggle switches. Upstream markup is
   <form><input type=checkbox><label>; we flex the row (label left, switch right
   via row-reverse) and restyle the native checkbox into a pill switch, with no
   HTML change so upstream merges stay clean. Scoped to the drawer, so the login
   "remember me" and pre-join checkboxes keep their native look. */
.sidenav-content form:has(> input[type="checkbox"]) {
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 4px 0;
}
.sidenav-content form:has(> input[type="checkbox"]) label {
    margin: 0;
    color: var(--text);
    font-size: 0.94rem;
    cursor: pointer;
}
.sidenav-content input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex: none;
    width: 42px;
    height: 24px;
    margin: 0;
    border-radius: var(--radius-pill);
    background: var(--surface-3);
    border: 1px solid var(--divider);
    cursor: pointer;
    transition: background var(--t-fast) var(--ease),
                border-color var(--t-fast) var(--ease);
}
.sidenav-content input[type="checkbox"]::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #aeb6c2;
    transition: transform var(--t-fast) var(--ease),
                background var(--t-fast) var(--ease);
}
.sidenav-content input[type="checkbox"]:checked {
    background: var(--accent);
    border-color: transparent;
}
.sidenav-content input[type="checkbox"]:checked::after {
    transform: translateX(18px);
    background: #fff;
}
.sidenav-content input[type="checkbox"]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--focus-ring);
}

/* App-level settings (shown only inside the Android app): unlike the rest of
   the drawer this group keeps a visible header and a divider so "Change server"
   / "Reset login" read as their own section, rendered as full-width tappable
   links. (Oryn) */
#app-settings {
    margin-top: 0.75rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--divider);
}
#app-settings legend {
    display: block;
    color: var(--text-2);
    font-size: 0.85rem;
    margin-bottom: 0.25rem;
}
.app-settings-link {
    display: block;
    padding: 11px 4px;
    color: var(--accent);
    text-decoration: none;
    cursor: pointer;
}
.app-settings-link:hover { color: var(--accent-2); }

/* Oryn brand lockup, relocated here from the people panel header so it no
   longer competes with the participant list. Quiet header for the drawer. */
.sidenav-brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0;
    margin: 0;
}
.sidenav-brand .brand-mark { width: 24px; height: 24px; }
.sidenav-brand .brand-word { font-size: 1.1rem; letter-spacing: 0.22em; }

/* --- Video tiles --------------------------------------------------------- */
.video-container { background: #000; }
.peer {
    background: rgba(255, 255, 255, 0.03);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.peer-active { border-color: var(--accent); }
.media { border-radius: inherit; }
.chat-btn .icon-chat { color: var(--text-2); text-shadow: none; }

/* Floating "show video" pill */
.show-video { background: var(--accent); }
@keyframes blink {
    0%   { box-shadow: 0 0 16px var(--accent); }
    50%  { box-shadow: none; }
    100% { box-shadow: 0 0 16px var(--accent); }
}

/* --- Captions ------------------------------------------------------------ */
#captions {
    background-color: rgba(10, 12, 18, 0.72);
    color: var(--text);
    border-radius: var(--radius-sm);
}

/* --- Status text --------------------------------------------------------- */
.connected { color: var(--ok); }
.disconnected { color: var(--danger); }
.error { color: var(--danger); }

/* --- Invite dialog ------------------------------------------------------- */
.file-progress { accent-color: var(--accent); }
#invite-dialog {
    background-color: var(--surface);
    color: var(--text);
    border: 1px solid var(--divider);
    border-radius: var(--radius-lg);
}
#invite-dialog button,
#invite-dialog button:hover { background: var(--accent-grad); }
#invite-dialog button:hover { filter: brightness(1.08); }
#invite-dialog input {
    background: var(--surface-3);
    color: var(--text);
    border: 1px solid var(--divider);
    border-radius: var(--radius-sm);
}
#invite-dialog label { color: var(--text-2); }
::backdrop { background: rgba(0, 0, 0, 0.55); }

/* --- Contextual menu (dark) ---------------------------------------------- */
:root {
    --contextualMenuBg: #161B22;
    --contextualMenuText: #E6EAF0;
    --contextualSubMenuBg: #161B22;
    --contextualHover: #1B2129;
    --contextualOverflowIcon: #9AA4B2;
    --contextualSeperator: rgba(255, 255, 255, 0.08);
}

/* --- Toastify: muted, never shouting ------------------------------------- */
/* Note: toastify.css is loaded *after* galene.css in galene.html, so the
   upstream `.toastify` rules override ours by source order.  We bump the
   selector specificity (`body .toastify.toastify`) to win the cascade
   without resorting to !important. */
body .toastify.toastify {
    /* Oryn: softly rounded rectangle.  A percentage of the short side
       squashes wide toasts into ovals, so use a fixed value that
       matches the dock buttons' visual weight. */
    border-radius: 12px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}
.toastify.error {
    background: linear-gradient(95deg, #B5524F, #A24845);
    color: #fff;
}
.toastify.error .toast-close { color: #fff; }
.toastify.warning {
    background: linear-gradient(95deg, #C9A24A, #B8923F);
    color: #1C1F24;
}
.toastify.warning .toast-close { color: #1C1F24; }
.toastify.info {
    background: var(--accent-grad);
    color: #fff;
}
.toastify.info .toast-close { color: #fff; }
/* The upstream close "×" is barely visible (opacity 0.4); make it legible. */
.toastify .toast-close {
    opacity: 0.95;
    font-size: 1.3em;
    line-height: 1;
    padding: 0 8px;
    align-self: center;
}

/* ==========================================================================
   Oryn — camera control, clean login screen, language toggle
   ========================================================================== */

/* --- Camera button: render present/unpresent as icon nav buttons --------- */
button.nav-button {
    background: transparent;
    border: none;
    padding: 0;
    font-family: inherit;
    cursor: pointer;
}
button.nav-button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--focus-ring);
    border-radius: var(--radius-sm);
}
#presentbutton, #unpresentbutton {
    width: auto;
    margin: 0 10px;
    font-size: 25px;            /* match the other nav icons */
    text-align: center;
}
.nav-cam-on, .nav-cam-on label { color: var(--accent); }

/* --- Share screen toggle (Oryn) ------------------------------------------
   The share button is blue while a screen share is live, mirroring the mic/
   camera state colours. The .sharing class is set/torn down in galene.js
   based on the presence of an up-stream with label 'screenshare'. */
#sharebutton.sharing,
#sharebutton.sharing label,
#sharebutton.sharing:hover,
#sharebutton.sharing label:hover {
    color: var(--accent);
}

/* --- Media toggles reflect the device's current state (no neutral grey) ---
   The mic and camera buttons colour by what is LIVE right now, not by the
   action a click performs:
     on  -> accent (blue), upright glyph
     off -> danger (red), slashed glyph
   This removes the old ambiguous in-between where "mic on" and "camera off"
   both sat at the neutral --text-2 grey. */
#mutebutton:not(.muted),
#mutebutton:not(.muted) label,
#mutebutton:not(.muted):hover,
#mutebutton:not(.muted) label:hover {
    color: var(--accent);
}
.nav-cam:not(.nav-cam-on),
.nav-cam:not(.nav-cam-on) label,
.nav-cam:not(.nav-cam-on):hover,
.nav-cam:not(.nav-cam-on) label:hover {
    color: var(--danger);
}

/* --- View toggle: a picture-in-picture glyph for "switch to speaker view" ---
   The old icon was a plain person (fa-user), which both looked unclear and
   duplicated the participants toggle. Draw a framed rectangle with a smaller
   inset rectangle in the lower-right corner — two nested camera frames — using
   borders so it inherits the nav colour (and hover) exactly like a font icon.
   updateViewToggle() in galene.js swaps this in for grid view and the
   fa-th-large grid glyph back in for speaker view. */
.view-pip {
    position: relative;
    display: inline-block;
    box-sizing: border-box;
    width: 1.05em;
    height: 0.8em;
    border: 0.13em solid currentColor;
    border-radius: 0.12em;
    vertical-align: -0.04em;
}
.view-pip::after {
    content: "";
    position: absolute;
    right: 0.12em;
    bottom: 0.1em;
    width: 0.42em;
    height: 0.32em;
    background: currentColor;
    border-radius: 0.06em;
}

/* --- Clean login / waiting-room screen (hide sidebar, chat + top bar) ----- */
body.pre-join #left-sidebar,
body.pre-join #left,
body.pre-join #resizer,
body.pre-join #sidebarCollapse,
body.pre-join header {
    display: none !important;   /* beat the mobile `.coln-left { ...!important }` rule */
}
body.pre-join .full-width { width: 100vw; height: calc(var(--vh, 1vh) * 100); }
body.pre-join .coln-right { flex: 1 1 100%; }
/* With no top bar, let the card centre over the full viewport height
   (covers both #login-container and #lobby-waiting). */
body.pre-join .login-container {
    top: 0;
    height: calc(var(--vh, 1vh) * 100);
}

/* Clip the sidebar so a collapsed (width:0) sidebar hides its content
   instead of letting it spill. */
#left-sidebar { overflow: hidden; }

/* Brand + language row on the login card */
.login-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.6rem;
}
.login-brand .brand-mark { width: 26px; height: 26px; }
.login-brand .brand-word { font-size: 1.25rem; letter-spacing: 0.26em; }

/* "Remember me on this device" checkbox on the login card. */
.rememberform { margin: 0.5rem 0; }
.remember-label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
    font-size: 0.95rem;
}
.remember-label input {
    width: auto;
    margin: 0;
}

/* --- Language toggle ----------------------------------------------------- */
.lang-toggle {
    display: inline-flex;
    border: 1px solid var(--divider);
    border-radius: var(--radius-pill);
    overflow: hidden;
    flex: none;
}
.lang-toggle button {
    background: transparent;
    border: none;
    color: var(--text-2);
    font-family: inherit;
    font-size: 0.78rem;
    letter-spacing: 0.04em;
    padding: 3px 11px;
    cursor: pointer;
    transition: color var(--t-fast) var(--ease),
                background var(--t-fast) var(--ease);
}
.lang-toggle button:hover { color: var(--text); }
.lang-toggle button.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.lang-form {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

/* ==========================================================================
   Oryn — speaker view (Zoom-style 1-on-1)
   In a 1-on-1 call the remote video fills the stage and the local video is a
   small self-thumbnail in the corner. Toggled by the `speaker` class on
   #peers from resizePeers().
   ========================================================================== */
#peers.speaker {
    display: block;
    padding: 0;
}
#peers.speaker .peer-remote {
    position: absolute;
    inset: 0;
    margin: 0;
    border: none;
    border-radius: 0;
    background: transparent;
}
#peers.speaker .peer-remote .media {
    width: 100%;
    height: 100%;
    max-height: none !important;
    padding-bottom: 0;
    object-fit: contain;
}
/* Oryn — smart framing: fill the stage edge-to-edge when cropping stays
   modest (.framing-fill, toggled by applyRemoteFraming); otherwise show the
   whole frame (contain). */
#peers.speaker .peer-remote.framing-fill .media {
    object-fit: cover;
}
#peers.speaker .peer-self {
    position: absolute;
    right: 16px;
    top: 16px;
    width: 22%;
    min-width: 120px;
    max-width: 260px;
    aspect-ratio: 4 / 3;
    margin: 0;
    z-index: 1100;
    border: 1px solid var(--divider);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow-modal);
    background: #000;
}
#peers.speaker .peer-self .media {
    width: 100%;
    height: 100%;
    max-height: none !important;
    padding-bottom: 0;
    object-fit: cover;
}
#peers.speaker .peer-self .label,
#peers.speaker .peer-self .video-controls {
    display: none;
}
/* The hide-self eye on the speaker-view thumbnail had two problems:
   1) Default `.top-video-controls { opacity: 0 }` — only visible on
      hover, brittle on a 120-260px-wide thumbnail you barely notice.
      Force opacity 1 so the eye is always there.
   2) The <video> element below it was swallowing clicks — `e.target`
      ended up as `.peer-self` itself instead of `.video-hide`, so
      the eye's onclick handler never fired and self-hidden never
      toggled. Making the video pass-through for pointer events lets
      the absolutely-positioned top-controls catch the click instead.
   The eye is the only interactive element on the self-thumbnail in
   speaker / speaker-many view, so disabling pointer events on the
   video is safe. (Oryn) */
#peers.speaker .peer-self .top-video-controls,
#peers.speaker-many .peer-self .top-video-controls {
    opacity: 1;
}
/* The self-thumb's hide ("eye") button is the only control on the thumbnail,
   so it must stay visible AND tappable even in immersive mode (body.nav-hidden),
   where the generic mobile rule sets the on-video controls to
   pointer-events:none — the eye showed but did nothing on mobile. Its click
   handler stopPropagation()s, so re-enabling it won't toggle the chrome. (Oryn) */
body.nav-hidden #peers.speaker .peer-self .top-video-controls,
body.nav-hidden #peers.speaker-many .peer-self .top-video-controls {
    opacity: 1;
    pointer-events: auto;
}
#peers.speaker .peer-self .media,
#peers.speaker-many .peer-self .media {
    pointer-events: none;
}
/* The self-view thumbnail can be picked up and moved out of the way while in
   speaker view (see makeSelfThumbDraggable in galene.js). touch-action:none so
   a touch-drag moves the tile instead of scrolling the page. */
#peers.speaker .peer-self {
    cursor: grab;
    touch-action: none;
    transition: box-shadow var(--t-fast) var(--ease);
}
#peers.speaker .peer-self.dragging {
    cursor: grabbing;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
    transition: none;
}

/* ==========================================================================
   Oryn — speaker-many view (self-thumbnail overlaid on a remote grid)
   For 3+ participants: remotes are laid out as a regular grid, and only the
   self tile is pulled out as a small floating overlay in the top-right
   corner. The user can still drag the self tile away. (Oryn)
   ========================================================================== */
#peers.speaker-many .peer-self {
    position: absolute;
    right: 16px;
    top: 16px;
    width: 22%;
    min-width: 120px;
    max-width: 260px;
    aspect-ratio: 4 / 3;
    margin: 0;
    z-index: 1100;
    border: 1px solid var(--divider);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow-modal);
    background: #000;
    cursor: grab;
    touch-action: none;
    transition: box-shadow var(--t-fast) var(--ease);
}
#peers.speaker-many .peer-self.dragging {
    cursor: grabbing;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
    transition: none;
}
#peers.speaker-many .peer-self .media {
    width: 100%;
    height: 100%;
    max-height: none !important;
    padding-bottom: 0;
    object-fit: cover;
}
#peers.speaker-many .peer-self .label,
#peers.speaker-many .peer-self .video-controls {
    display: none;
}

/* ==========================================================================
   Oryn — self-view hidden: floating controls pill
   When the user clicks "_" on their self tile, .peer-self is taken out of
   layout (display: none) so it stops claiming grid space, and a small
   pill with the show ("_") and stop ("✕") buttons is anchored to the
   top-right of #video-container. The pill lives on the container, NOT on
   the hidden tile (so it can't be hidden with it). The stream keeps
   flowing the whole time — the remote still sees us. (Oryn)
   ========================================================================== */
#video-container.self-hidden .peer-self { display: none; }

.self-controls-pill {
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: 1300;
    display: none;
    align-items: center;
    gap: 6px;
    padding: 4px 6px;
    background: rgba(0, 0, 0, 0.45);
    border-radius: 22px;
    pointer-events: auto;
}
.self-controls-pill.visible { display: inline-flex; }
/* The pill now only hosts the show ("eye") button — the stop "✕" was
   dropped because the bottom dock's camera toggle already covers it. (Oryn) */
.self-controls-pill .video-hide {
    display: inline-flex;
    width: 1.5em;
    height: 1.5em;
    background: rgba(0,0,0,0.6);
    border-radius: 50%;
    justify-content: center;
    align-items: center;
    color: #eaeaea;
    font-size: 0.9em;
    cursor: pointer;
    user-select: none;
    vertical-align: middle;
}
.self-controls-pill .video-hide:hover { opacity: .85; }

/* ==========================================================================
   Oryn — let the video fill the tile (no reserved black strip)
   Upstream reserves 20px under every .media for the old in-flow control bar.
   Oryn's controls are now an absolutely-positioned overlay, so that reserved
   strip just paints the black tile background and crops the bottom of the
   picture — it read as a dark name-bar at the bottom of grid tiles. Speaker
   view already zeroes it; do the same for every tile, desktop and mobile
   alike. The name label below stays readable via its text-shadow. (Oryn)
   ========================================================================== */
.media { padding-bottom: 0; }

/* ==========================================================================
   Oryn — combined people + chat panel
   The left panel is one unit: brand header on top, the participant list and
   the chat split the rest in half (participants above, chat below). A single
   header button toggles the whole panel; the old separate chat column and its
   drag-resizer are gone.
   ========================================================================== */
#left-sidebar {
    display: flex;
    flex-direction: column;
}
.users-header { flex: 0 0 auto; }

/* The panel header lane carries the room title + E2EE indicator (moved out of
   the top bar so the pinned toggle can't overlap them). It is already a flex
   row via #left-sidebar .galene-header; drop the old float-clearfix pseudo
   elements so they don't add phantom flex items, and let the title ellipsize. */
.users-header::before,
.users-header::after { content: none; display: none; }
.users-header { overflow: hidden; }
.users-header #title {
    float: none;
    margin: 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
    line-height: 1.3;
}

/* Top-bar header: holds the (fixed) toggle button + the E2EE lock/SAS. Flex so
   the indicator is vertically centred; on mobile the in-flow button and the
   indicator sit side by side here too. */
#header { display: flex; align-items: center; }

/* Top half: participant list */
#left-sidebar #users {
    flex: 1 1 50%;
    height: auto;
    min-height: 0;
    overflow-y: auto;
}

/* Bottom half: chat */
#left-sidebar #chat {
    flex: 1 1 50%;
    height: auto !important;      /* beat base #chat { height: 100% !important } */
    width: 100%;
    min-width: 0;
    border: none;
    display: flex;
    overflow: hidden;
    background: transparent;
}
#left-sidebar #chatbox {
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
}
#left-sidebar #box {
    flex: 1 1 auto;
    height: auto;
    min-height: 0;
    overflow-y: auto;
}
#left-sidebar .reply { flex: 0 0 auto; }

/* Toggle icon: a person silhouette with a small chat bubble tucked into the
   bottom-right corner. The bubble sits slightly clear of the silhouette, is
   tinted with the accent and carries a halo in the bar colour, so the two
   glyphs read as a person + chat rather than one merged blob. */
.panel-toggle-icon { position: relative; display: inline-block; line-height: 1; }
.panel-toggle-badge {
    position: absolute;
    right: -0.34em;
    bottom: -0.16em;
    top: auto;
    font-size: 0.5em;
    color: var(--accent);
    text-shadow:
        0 0 2px var(--surface), 0 0 2px var(--surface),
        0 0 3px var(--surface), 0 0 3px var(--surface);
}

/* Unobtrusive alert dot: unread chat or a new lobby knock while the panel is
   closed. Sits at the TOP-right (clear of the chat bubble) and glows softly. */
.panel-toggle-dot {
    display: none;
    position: absolute;
    right: -0.32em;
    top: -0.2em;
    bottom: auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 6px 1px var(--accent);
    animation: panel-dot-pulse 1.8s ease-in-out infinite;
}
#sidebarCollapse.panel-alert .panel-toggle-dot { display: block; }
@keyframes panel-dot-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.45; }
}

/* Draggable divider between the participant list and the chat. */
#panel-resizer {
    flex: 0 0 auto;
    height: 8px;
    position: relative;
    cursor: ns-resize;
    background: transparent;
}
#panel-resizer::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 3px;
    height: 1px;
    background: var(--divider);
    transition: background var(--t-fast) var(--ease);
}
#panel-resizer:hover::before,
#panel-resizer:active::before {
    background: var(--accent);
    height: 2px;
    top: 3px;
}

/* Desktop: the panel is a 320px column that pushes the video aside;
   collapsing it (.active) gives the video the full width. */
@media only screen and (min-width: 1025px) {
    #left-sidebar {
        min-width: 320px;
        max-width: 320px;
        /* sits above the E2EE lock (z:1041) so the visible panel physically
           covers the lock at the top-left — without this the lock paints on
           top of the room title that lives inside .users-header. */
        z-index: 1050;
    }
    #left-sidebar.active { min-width: 0; max-width: 0; }
    .full-width { width: calc(100vw - 320px); }
    .full-width-active { width: 100vw; }   /* wins over .full-width when collapsed */

    /* Pin the people+chat toggle. Opening the panel pushes the video column
       320px to the right, which used to drag this button along with it, so
       closing the panel meant chasing the button. Anchor it to the viewport
       instead — like the settings button, it now stays in one place whether
       the panel is open or shut. The high z-index keeps it clickable above
       the open panel; the .users-header strip below aligns to the same band. */
    #sidebarCollapse {
        position: fixed;
        top: 0;
        left: 0;
        height: 3.5rem;
        margin: 0;
        padding: 0 18px;
        display: flex;
        align-items: center;
        z-index: 1100;
    }
    /* the room title no longer needs to clear a pinned toggle (it is in the dock) */
    .users-header { padding-left: 16px; }

    /* (The E2EE lock/SAS now floats centred above the dock — see the dock
       section — so it no longer needs to clear a top-bar toggle here.) */
}

/* Mobile: keep the people+chat toggle pinned like the desktop one.
   The panel is an in-flow column that, when open, pushes the rest of the top bar
   320px to the right (off-screen, clipped by body{overflow-x:hidden}) — that is
   what clears the bar off the panel so the panel's own "Main" header reads.  The
   bug was that the toggle, being in that bar, slid away with it.  Pin the toggle
   so it stays at the top-left and, because the bar's stacking context (z 1039)
   sits above the in-flow panel (z 1002), it stays on top and tappable — the SAME
   button opens AND closes the panel, just like on desktop.  The pushed-away lock
   and call buttons are faded out so nothing peeks beside the panel. (Oryn) */
@media only screen and (max-width: 1024px) {
    #left-sidebar.active {
        min-width: 320px;
        max-width: 320px;
        /* overlays the video, sits above the E2EE lock (z:1041) so the panel
           physically covers the lock when open, no hide/show needed. */
        z-index: 1050;
    }

    /* Pin the toggle like the desktop one: it stays put and, sitting in the bar
       that paints above the panel, stays tappable over the open panel. */
    #sidebarCollapse {
        position: fixed;
        top: 0;
        left: 0;
        height: 3.5rem;
        margin: 0;
        padding: 0 16px;
        display: flex;
        align-items: center;
        z-index: 1103;
        transition: opacity var(--t-base) var(--ease),
                    transform var(--t-base) var(--ease);
    }
    /* toggle + lock moved to / above the dock; no top-bar padding needed */
    #header { padding-left: 0; }
    #left-sidebar .users-header { padding-left: 16px; }
    /* Immersive: the toggle sits inside .nav-menu, so it rides the dock's own
       hide (transform: translateY(160%) + opacity 0 on .nav-menu) and needs
       no rule of its own. */

    /* When the panel is open we are in "chat mode": fade out the lock and the
       call buttons that the panel pushes aside, so nothing peeks in the strip
       beside it.  The opacity transition matches the panel's slide, so they fade
       back in instead of flashing on close (the old phantom-flash failure). */
    .topnav .nav-menu,
    #header > #e2ee-indicator {
        transition: opacity var(--t-base) var(--ease);
    }
    #left-sidebar.active ~ .container .nav-menu,
    #left-sidebar.active ~ .container #e2ee-indicator {
        opacity: 0;
        pointer-events: none;
    }

    /* Retire the legacy floating chat bubble / "show video" pill on mobile: the
       combined panel is the chat now, and these were the "phantom" that flashed
       at the top-right for the panel's 0.3s slide-out when it closed. */
    .coln-right .collapse-video,
    .coln-right .show-video {
        display: none !important;
    }
}

/* ==========================================================================
   Oryn — end-to-end encryption: lock + emoji SAS in the top bar

   The 5 emoji are the Short Authentication String the two participants compare
   out loud; the whole indicator lives next to the room title and is hidden
   before joining (the top bar carries the .pre-join hide).
   ========================================================================== */
.e2ee-indicator {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-left: 0.25rem;
    padding: 0.05rem 0.55rem;
    border-radius: 999px;
    font-size: 0.95rem;
    cursor: default;
    vertical-align: middle;
}
/* Only show the pill background when the emoji SAS is present (established),
   so a lone red lock doesn't sit in an empty grey oval. */
.e2ee-indicator.e2ee-on  {
    color: var(--accent, #8b7cf6);
    background: rgba(255, 255, 255, 0.05);
}
.e2ee-indicator.e2ee-bad { color: #ef5350; }
.e2ee-sas {
    font-size: 1.05rem;
    letter-spacing: 0;
    white-space: nowrap;
}
@media only screen and (max-width: 480px) {
    .e2ee-sas { font-size: 0.95rem; }
}

/* Full-screen notice shown when the group requires end-to-end encryption but
   the call cannot be encrypted; local media is blocked while it is visible.
   Visibility is driven by the .invisible class (setVisibility); we show via
   :not(.invisible) so the .invisible rule (display:none) always wins when set. */
.e2ee-block-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    padding: 1.5rem;
    background: rgba(8, 10, 16, 0.82);
}
.e2ee-block-overlay:not(.invisible) {
    display: flex;
    align-items: center;
    justify-content: center;
}
.e2ee-block-card {
    max-width: 30rem;
    text-align: center;
    padding: 1.6rem 1.8rem;
    border-radius: 14px;
    background: var(--surface, #161922);
    border: 1px solid #ef5350;
    color: var(--text, #e8eaf0);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
.e2ee-block-card i {
    font-size: 2rem;
    color: #ef5350;
    margin-bottom: 0.6rem;
}
.e2ee-block-card p {
    margin: 0.4rem 0 0;
    line-height: 1.45;
}

/* Full-screen notice when the browser cannot do video calls (missing/broken
   WebRTC, e.g. Xiaomi Mi Browser).  Same visibility trick as the E2EE overlay. */
.browser-unsupported-overlay {
    position: fixed;
    inset: 0;
    z-index: 1001;
    padding: 1.5rem;
    background: rgba(8, 10, 16, 0.9);
}
.browser-unsupported-overlay:not(.invisible) {
    display: flex;
    align-items: center;
    justify-content: center;
}
.browser-unsupported-card {
    max-width: 30rem;
    text-align: center;
    padding: 1.6rem 1.8rem;
    border-radius: 14px;
    background: var(--surface, #161922);
    border: 1px solid var(--accent, #8b7cf6);
    color: var(--text, #e8eaf0);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
.browser-unsupported-card i {
    font-size: 2rem;
    color: #f5b942;
    margin-bottom: 0.6rem;
}
.browser-unsupported-card p { margin: 0.6rem 0 0; line-height: 1.45; }
.browser-unsupported-url {
    font-family: monospace;
    font-size: 0.9rem;
    word-break: break-all;
    opacity: 0.85;
    -webkit-user-select: all;
    user-select: all;
}

/* Oryn — "reconnecting" banner: a non-modal status pill pinned to the top while
   a dropped connection is being re-established (see scheduleReconnect).  Same
   visibility trick as the overlays: the base rule has no `display`, so the
   global `.invisible { display:none }` always wins when the class is set. */
.reconnect-banner {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1002;
    margin-top: 0.6rem;
    padding: 0.5rem 1rem;
    align-items: center;
    gap: 0.6rem;
    border-radius: 999px;
    background: var(--surface, #161922);
    border: 1px solid var(--accent, #5B8CFF);
    color: var(--text, #e8eaf0);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
    font-size: 0.9rem;
}
.reconnect-banner:not(.invisible) { display: flex; }
.reconnect-spinner {
    width: 1rem;
    height: 1rem;
    border: 2px solid rgba(255, 255, 255, 0.25);
    border-top-color: var(--accent, #5B8CFF);
    border-radius: 50%;
    animation: reconnect-spin 0.8s linear infinite;
}
@keyframes reconnect-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   Oryn — pre-join device check (login card)

   Two square icon toggles (camera / microphone), off by default. Turning one
   on reveals a live camera preview and/or a microphone level meter (a canvas
   drawn by precheckDrawMeter in galene.js), plus a device picker for each,
   so people can check their hardware before joining.
   ========================================================================== */
.precheck {
    margin: 14px 0 4px;
}
.precheck-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.precheck-hint {
    color: var(--text-2, #9AA4B2);
    font-size: 0.92rem;
}
.precheck-toggles {
    display: flex;
    gap: 10px;
}
.precheck-toggle {
    width: 44px;
    height: 44px;
    border-radius: var(--radius-sm, 10px);
    border: 1px solid var(--divider, rgba(255, 255, 255, 0.12));
    background: var(--surface-2, #161B22);
    color: var(--text-2, #9AA4B2);
    font-size: 1.05rem;
    cursor: pointer;
    transition: color var(--t-fast, 0.15s) var(--ease, ease),
                border-color var(--t-fast, 0.15s) var(--ease, ease),
                background var(--t-fast, 0.15s) var(--ease, ease);
}
.precheck-toggle:hover {
    border-color: var(--accent, #5B8CFF);
    color: var(--text, #E6EAF0);
}
.precheck-toggle.on {
    background: var(--accent-soft, rgba(91, 140, 255, 0.14));
    border-color: var(--accent, #5B8CFF);
    color: var(--accent, #5B8CFF);
}
.precheck-toggle:disabled {
    opacity: 0.6;
    cursor: default;
}
.precheck-preview {
    margin-top: 12px;
}
.precheck-video {
    display: block;
    width: 100%;
    max-height: 200px;
    border-radius: var(--radius-sm, 10px);
    background: #000;
    object-fit: cover;
    transform: scaleX(-1);   /* self-view convention: mirrored */
}
.precheck-meter {
    display: block;
    width: 100%;
    height: 36px;
    margin-top: 8px;
}
.precheck-error {
    margin: 8px 0 0;
    color: #ef5350;
    font-size: 0.9rem;
}
.precheck-devices {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 10px;
}
.precheck-devices select {
    width: 100%;
    max-width: none;
}
/* class selectors above would otherwise tie with .invisible (declared much
   earlier), so restate the hiding at higher specificity */
.precheck .invisible,
.apk-link.invisible {
    display: none;
}

/* "Download the Android app" link under the login form; only shown when the
   server actually serves an APK (probeAPK in galene.js). */
.apk-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 14px;
    padding: 9px 12px;
    border: 1px dashed var(--divider, rgba(255, 255, 255, 0.16));
    border-radius: var(--radius-sm, 10px);
    color: var(--text-2, #9AA4B2);
    font-size: 0.92rem;
    text-decoration: none;
    transition: color var(--t-fast, 0.15s) var(--ease, ease),
                border-color var(--t-fast, 0.15s) var(--ease, ease);
}
.apk-link:hover {
    color: var(--accent, #5B8CFF);
    border-color: var(--accent, #5B8CFF);
    text-decoration: none;
}
