/* Kiss Empire — webcam performer studio + viewer. */
.ke-cam-studio, .ke-cam-view { max-width: 820px; margin: 0 auto; color: #e8e2f2; }
.ke-cam-stage { position: relative; width: 100%; aspect-ratio: 16/9; background: #000; border-radius: 10px; overflow: hidden; }
.ke-cam-stage video { width: 100%; height: 100%; object-fit: contain; background: #000; display: block; }
/* Safari/WebKit disegna un pulsante play centrale sui video fermi anche senza
   l'attributo controls: nell'anteprima del performer (.ke-cam-self) non ha alcun
   senso — non deve avviare niente, è la sua stessa webcam — e sullo stream dello
   spettatore ci pensa già il playgate custom. Lo togliamo su entrambi. */
/* Safari (desktop) continua a disegnare i suoi comandi play/pausa sopra i video
   grandi anche senza l'attributo controls, e i pseudo-elementi non bastano a
   toglierli. Copriamo il video con uno schermo trasparente: il puntatore non lo
   raggiunge mai, quindi Safari non ha motivo di mostrare alcunché. Sta sotto ai
   nostri comandi (z-index 6-7) e sotto al playgate (4), che restano cliccabili. */
.ke-cam-stage::after { content: ''; position: absolute; inset: 0; z-index: 3; }
.ke-cam-stage video { pointer-events: none; }
.ke-cam-stage video::-webkit-media-controls,
.ke-cam-stage video::-webkit-media-controls-start-playback-button,
.ke-cam-stage video::-webkit-media-controls-play-button,
.ke-cam-stage video::-webkit-media-controls-overlay-play-button,
.ke-cam-stage video::-webkit-media-controls-overlay-enclosure,
.ke-cam-stage video::-webkit-media-controls-enclosure,
.ke-cam-stage video::-webkit-media-controls-panel { display: none !important; opacity: 0 !important; -webkit-appearance: none; appearance: none; pointer-events: none; }
/* One-tap "start" overlay (desktop only): macOS Chrome/Safari leave a WebRTC <video>
   black until a genuine user interaction, so we ask for one click — that click is
   what makes the browser paint the first frame. Native <video>, full quality. The
   overlay is OPAQUE so if the stream ever paints on its own underneath, you don't
   see the video running behind the "start" prompt. */
.ke-cam-playgate { position: absolute; inset: 0; z-index: 4; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; width: 100%; height: 100%; border: 0; cursor: pointer; background: #0c0a11; color: #fff; font-size: 15px; font-weight: 600; }
.ke-cam-playgate-ic { display: flex; align-items: center; justify-content: center; width: 72px; height: 72px; border-radius: 50%; background: var(--ke-accent,#e50914); box-shadow: 0 8px 24px rgba(229,9,20,.45); transition: transform .12s ease; }
/* White play triangle drawn with borders (no emoji glyph to render inconsistently). */
.ke-cam-playgate-ic::before { content: ''; width: 0; height: 0; border-style: solid; border-width: 13px 0 13px 22px; border-color: transparent transparent transparent #fff; margin-left: 6px; }
.ke-cam-playgate:hover .ke-cam-playgate-ic { transform: scale(1.06); }
.ke-cam-playgate-tx { opacity: .92; }
/* Status badges (top-left of the video). Icon + text so they're readable regardless
   of colour (colour-blind friendly); colour is only a secondary cue. */
.ke-cam-flags { position: absolute; top: 10px; inset-inline-start: 10px; z-index: 6; display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-start; max-width: 80%; }
.ke-cam-badge { background: #e50914; color: #fff; font-weight: 700; font-size: 12px; padding: 3px 9px; border-radius: 4px; letter-spacing: .04em; white-space: nowrap; }
.ke-cam-live-flag { background: #e50914; }
.ke-cam-mode-flag.ke-cam-mode-o2o { background: #6b4fbf; }
.ke-cam-mode-flag.ke-cam-mode-group { background: #2f7fd1; }
.ke-cam-mode-flag.ke-cam-mode-public { background: #4a5568; }
.ke-cam-wait { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #b9a7e6; font-size: 14px; text-align: center; padding: 20px; }
.ke-cam-bar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 12px 2px; }
.ke-cam-viewers, .ke-cam-bal { color: #8a7ca8; font-size: 13px; }
.ke-cam-btn { background: var(--ke-accent, #e50914); color: #fff; border: 0; border-radius: 7px; padding: 9px 16px; cursor: pointer; font-size: 14px; font-weight: 600; }
.ke-cam-btn:hover { background: var(--ke-accent-2, #ff2d3d); }
/* Secondary/decline button (e.g. "Rifiuta" next to "Accetta"). */
.ke-cam-btn--muted { background: #3a2f4a; }
.ke-cam-btn--muted:hover { background: #4a3d5e; }
.ke-cam-go { min-width: 130px; }
.ke-cam-tipbox { display: inline-flex; align-items: center; gap: 6px; margin-inline-start: auto; }
.ke-cam-tip-amt { width: 5em; padding: 7px; border-radius: 6px; border: 1px solid #3a2f4a; background: #221b2c; color: #fff; font-size: 16px; }
.ke-cam-tips { min-height: 24px; display: flex; flex-direction: column; gap: 4px; margin: 6px 0; }
.ke-cam-tip-msg { align-self: flex-start; background: rgba(229, 9, 20, .2); color: #cdc3e0; border-radius: 999px; padding: 3px 12px; font-size: 13px; animation: kecamin .3s ease; }
@keyframes kecamin { from { opacity: 0; transform: translateY(6px); } }
.ke-cam-share { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; font-size: 13px; color: #8a7ca8; }
.ke-cam-share-url { background: #1b1526; border: 1px solid #3a2f4a; border-radius: 6px; padding: 5px 9px; color: #cdc3e0; font-size: 12px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ke-cam-copy-link { padding: 4px 12px; }
.ke-cam-copy-link:hover { border-color: #6b5b8f; color: #fff; }
/* "Abbandona la stanza" — nella stanza il tema nasconde header e footer a ogni
   breakpoint (body.ke-cam-immersive), quindi questo è l'UNICO modo per tornare
   indietro: va visto al primo colpo d'occhio. Accento sul bordo + fondo tenue, pieno
   al passaggio del mouse. Sta accanto al titolo su desktop (.ke-cam-exit-title) e
   accanto al nome nella barra video su mobile (.ke-cam-exit-mini). */
/* Doppia classe (.ke-cam-modbtn.ke-cam-exit-*): i pulsanti nascono come .ke-cam-modbtn,
   che è definita più sotto in questo file — a pari specificità vincerebbe lei e
   l'evidenziazione andrebbe persa. */
.ke-cam-perfhead { display: inline-flex; align-items: center; gap: 8px; }
.ke-cam-modbtn.ke-cam-exit-mini, .ke-cam-modbtn.ke-cam-exit-title, .ke-cam-modbtn.ke-cam-exit-studio {
	padding: 7px 16px; font-size: 13px; text-decoration: none; line-height: 1.4; white-space: nowrap;
	font-weight: 700; color: #fff;
	border: 1px solid var(--ke-accent, #e50914);
	background: rgba(229, 9, 20, .14);
}
.ke-cam-modbtn.ke-cam-exit-mini:hover, .ke-cam-modbtn.ke-cam-exit-title:hover, .ke-cam-modbtn.ke-cam-exit-studio:hover,
.ke-cam-modbtn.ke-cam-exit-mini:focus-visible, .ke-cam-modbtn.ke-cam-exit-title:focus-visible, .ke-cam-modbtn.ke-cam-exit-studio:focus-visible {
	background: var(--ke-accent, #e50914); border-color: var(--ke-accent, #e50914); color: #fff;
}
.ke-room-titlebar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
/* Push the exit button to the right edge, away from the title. */
.ke-cam-exit-title { margin-inline-start: auto; }
/* Exit link inside the offline / busy notices — centered on its own line. Only on
   mobile, where the immersive title bar (with its exit button) is hidden; on desktop
   the title-bar button is enough, so this would just duplicate it. */
.ke-cam-exit-notice { display: block; width: fit-content; margin: 14px auto 0; }
@media (min-width: 900px) { .ke-cam-exit-notice { display: none; } }
/* Desktop: the title bar carries the exit button, so drop the duplicate name+exit in
   the video bar. */
@media (min-width: 900px) { .ke-cam-bar .ke-cam-perfhead { display: none; } }
/* Mobile: no big title (immersive), so the video bar carries the performer name and
   the exit button sits at the right edge of the screen. */
@media (max-width: 899px) {
	body.ke-cam-immersive .ke-room-titlebar { display: none; }
	.ke-cam-perfhead { display: flex; flex: 1 1 100%; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
}
.ke-cam-copy-msg { color: #5fd08a; font-weight: 700; }
.ke-cam-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.ke-cam-card { display: flex; align-items: center; gap: 8px; background: #221b2c; border: 1px solid #3a2f4a; border-radius: 8px; padding: 14px; color: #e8e2f2; text-decoration: none; font-weight: 600; }
.ke-cam-card:hover { border-color: var(--ke-accent, #e50914); }
.ke-cam-live-dot { width: 9px; height: 9px; border-radius: 50%; background: #e50914; box-shadow: 0 0 6px #e50914; }
.ke-cam-empty { color: #8a7ca8; text-align: center; padding: 30px; }
.ke-cam-form { max-width: 420px; }
.ke-cam-form input[type=text], .ke-cam-form input[type=email], .ke-cam-form input[type=password], .ke-cam-form input[type=tel], .ke-cam-form input[type=number], .ke-cam-form input[type=search], .ke-cam-form input[type=url] { width: 100%; height: 40px; padding: 0 11px; line-height: 38px; font-size: 14px; font-family: inherit; margin: 0; border-radius: 6px; border: 1px solid #3a2f4a; background: #221b2c; color: #fff; box-sizing: border-box; }
/* Consensi del modulo (maggiore eta', regole di moderazione): stessa misura e
   stesso rosso del consenso che si spunta per firmare il contratto
   (`.ke-sign-check` in Support/Contract.php) e degli altri moduli
   d'iscrizione (`.ke-consent` in studio.css — la regola e' ripetuta qui
   perche' questa pagina carica webcam.css e non studio.css). Senza, il
   quadratino resta quello nativo del browser: azzurro e di un'altra misura. */
.ke-consent { display: flex; align-items: flex-start; gap: 10px; line-height: 1.45; cursor: pointer; }
.ke-consent input[type=checkbox],
.ke-cam-form input[type=checkbox] { width: 20px; height: 20px; margin: 1px 0 0; flex: 0 0 auto; vertical-align: -4px; accent-color: var(--ke-accent, #e50914); cursor: pointer; }

.ke-cam-note { padding: 12px 14px; border-radius: 8px; background: #221b2c; color: #cdc3e0; margin: 10px 0; }
.ke-cam-note--ok { border-inline-start: 3px solid #5fd08a; }
.ke-cam-note--wait { border-inline-start: 3px solid #e6a417; }
.ke-cam-note--err { border-inline-start: 3px solid #e50914; }

/* performer fiscal + payout profile */
.ke-cam-fiscal { margin-top: 26px; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 12px; padding: 20px; }
.ke-cam-fiscal h3 { margin: 0 0 12px; font-size: 17px; color: #e8e2f2; }
.ke-cam-fiscal select, .ke-cam-fiscal input[type=number] { width: 100%; height: 40px; padding: 0 11px; line-height: 38px; font-size: 14px; font-family: inherit; margin: 0; border-radius: 6px; border: 1px solid #3a2f4a; background: #221b2c; color: #fff; box-sizing: border-box; }
/* Select alla stessa altezza degli input + freccia SVG (no icona nativa). */
.ke-cam-fiscal select { appearance: none; -webkit-appearance: none; -moz-appearance: none; padding-inline-end: 32px; cursor: pointer; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23e8e2f2' stroke-width='1.6' d='M2 4.5l4 4 4-4'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 11px center; background-size: 12px; }
.ke-cam-fiscal label { display: block; font-weight: 600; font-size: 13px; color: #e8e2f2; margin-bottom: 4px; }
/* ⚠️ Un campo spento deve restare LEGGIBILE: col lucchetto chiuso i dati
   fiscali si vedono ma non si toccano, e vederli e' il punto. Senza uno stile
   proprio le tendine disabilitate si sfasciano (la freccia del browser si
   ripete) e il testo sbiadisce fino a sparire. */
fieldset[disabled] select,
fieldset[disabled] input,
fieldset[disabled] textarea {
	background-image: none !important;
	color: #cfc9db !important;
	-webkit-text-fill-color: #cfc9db;
	opacity: 1;
	cursor: not-allowed;
}
fieldset[disabled] button { opacity: .5; cursor: not-allowed; }

.ke-cam-fiscal-note { display: block; margin-top: 6px; color: #8a7ca8; font-size: 12px; line-height: 1.5; }

/* performer earnings */
.ke-cam-earnings { margin-top: 26px; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 12px; padding: 20px; }
.ke-cam-earnings h3 { margin: 0 0 12px; font-size: 17px; color: #e8e2f2; }
.ke-cam-earnrow { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; }
.ke-cam-earn { background: #221b2c; border: 1px solid #3a2f4a; border-radius: 10px; padding: 12px 14px; }
.ke-cam-earn .k { display: block; color: #8a7ca8; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.ke-cam-earn .v { font-size: 22px; font-weight: 800; color: #e8e2f2; }
.ke-cam-earn .v small { font-size: 12px; color: #8a7ca8; }

/* realtime token counter in the broadcast bar */
.ke-cam-toklive { color: #8a7ca8; font-size: 13px; margin-inline-start: auto; }
.ke-cam-toklive b { color: #5fd08a; font-size: 15px; }
.ke-fx-wht-val { display: inline-block; font-size: 16px; font-weight: 800; color: #e8e2f2; padding: 6px 0; }

/* unmute overlay (autoplay starts muted by browser policy) */
.ke-cam-stage { position: relative; }
/* Performer audio/video toggles overlaid on the video (top-right). */
.ke-cam-avctl { position: absolute; top: 10px; inset-inline-end: 10px; z-index: 7; display: flex; gap: 8px; }
.ke-cam-av { width: 38px; height: 38px; border: 0; border-radius: 50%; background: rgba(20, 16, 26, .72); color: #fff; font-size: 17px; cursor: pointer; display: flex; align-items: center; justify-content: center; line-height: 1; }
.ke-cam-av:hover { background: rgba(20, 16, 26, .92); }
.ke-cam-av.is-off { background: var(--ke-accent, #e50914); }
/* Viewer sound toggle (bottom-right corner of the video). */
.ke-cam-sound { position: absolute; inset-inline-end: 12px; bottom: 12px; z-index: 7; width: 40px; height: 40px; border: 0; border-radius: 50%; background: rgba(20, 16, 26, .72); color: #fff; font-size: 18px; cursor: pointer; display: flex; align-items: center; justify-content: center; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, .45); }
.ke-cam-sound:hover { background: rgba(20, 16, 26, .92); }

/* 1:1 private show */
.ke-cam-o2o-box { margin-top: 18px; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 12px; padding: 18px; display: flex; flex-direction: column; }
.ke-cam-o2o-box .ke-cam-o2o-ask { margin-top: auto; align-self: flex-start; }
.ke-cam-o2o-box h4 { margin: 0 0 6px; color: #e8e2f2; font-size: 16px; }
.ke-cam-o2o-rate { color: #8a7ca8; margin: 0 0 10px; }
.ke-cam-o2o-box select { padding: 8px; border-radius: 6px; border: 1px solid #3a2f4a; background: #221b2c; color: #fff; }
.ke-cam-o2o-req { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; background: rgba(229, 9, 20, .14); border: 1px solid #e50914; border-radius: 10px; padding: 10px 14px; color: #e8e2f2; }
.ke-cam-o2o-req > span { flex: 1 1 200px; min-width: 0; }
.ke-cam-o2o-live { background: rgba(95, 208, 138, .16); color: #5fd08a; }

/* moderation list (broadcaster) */
.ke-cam-viewerlist { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.ke-cam-viewer-row { display: flex; align-items: center; gap: 8px; background: #221b2c; border: 1px solid #3a2f4a; border-radius: 8px; padding: 6px 12px; color: #e8e2f2; font-size: 13px; }
.ke-cam-viewer-row span { margin-inline-end: auto; }
.ke-cam-modbtn { background: transparent; border: 1px solid #3a2f4a; color: #cdc3e0; border-radius: 6px; padding: 3px 10px; font-size: 12px; cursor: pointer; }
.ke-cam-mod-kick { border-color: #e6a417; color: #e6a417; }
.ke-cam-mod-kick:hover { background: #e6a417; color: #14101a; }
.ke-cam-mod-ban { border-color: #e5556b; color: #e5556b; }
.ke-cam-mod-ban:hover { background: #e5556b; color: #fff; }
.ke-cam-mod-report { border-color: #ff2d3d; color: #ff2d3d; }
.ke-cam-mod-report:hover { background: #ff2d3d; color: #fff; }

/* room costs line */
.ke-cam-costs { margin: 10px 0; padding: 10px 14px; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 10px; color: #cdc3e0; font-size: 14px; }
.ke-cam-costs a { color: var(--ke-accent, #e50914); font-weight: 600; }
.ke-cam-recharge { color: var(--ke-accent, #e50914); font-weight: 600; margin-inline-start: 6px; }

/* token history */
.ke-cam-histtbl { width: 100%; border-collapse: collapse; }
.ke-cam-histtbl th { text-align: start; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: #8a7ca8; padding: 8px 10px; border-bottom: 1px solid #3a2f4a; }
.ke-cam-histtbl td { padding: 8px 10px; border-bottom: 1px solid #221b2c; color: #e8e2f2; font-size: 14px; }
.ke-cam-histtbl .n { text-align: end; font-variant-numeric: tabular-nums; color: #5fd08a; font-weight: 700; }
.ke-cam-earnnote { color: #8a7ca8; font-size: 13px; margin: 10px 0 0; }

/* Dati performer: responsive columns (3 large / 2 normal / 1 mobile via auto-fit) */
.ke-perf-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 20px; align-items: start; margin-top: 26px; }
.ke-perf-cols .ke-cam-fiscal { margin-top: 0; }

/* Dati performer layout: il PROFILO FISCALE occupa l'intera prima riga; metodo di
   pagamento + i due show (gruppo, 1:1) stanno su TRE colonne nella seconda riga.
   I wrapper (.ke-perf-fiscal/.ke-perf-rooms/.ke-cam-fiscal-wrap) e il form fiscale
   sono display:contents, così le singole card diventano celle della stessa griglia. */
.ke-perf-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: start; margin-top: 26px; }
.ke-perf-fiscal, .ke-perf-rooms, .ke-perf-fiscal .ke-cam-fiscal-wrap, .ke-perf-grid .ke-cam-form--fiscal { display: contents; }
.ke-perf-grid .ke-cam-fiscal { margin: 0; }
.ke-perf-grid .ke-cam-form { max-width: none; width: 100%; }
/* Profilo fiscale (o la nota "liquidato tramite studio") a tutta larghezza. */
.ke-perf-grid .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type,
.ke-perf-fiscal > .ke-cam-fiscal { grid-column: 1 / -1; }
/* Nella card larga i campi del profilo si distribuiscono su più colonne; titolo e
   note restano a tutta larghezza. */
.ke-perf-grid .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 0 20px; align-items: start; }
.ke-perf-grid .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type > h3,
.ke-perf-grid .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type > .ke-cam-note { grid-column: 1 / -1; }
.ke-perf-grid .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type > p { margin: 14px 0 0; }
@media (max-width: 1000px) {
	.ke-perf-grid { grid-template-columns: 1fr; }
}

/* Onboarding/wizard: il Profilo fiscale e il Metodo di pagamento occupano l'INTERA
   colonna (come nella pagina studio), con i campi su piu' colonne responsive.
   Senza questo, .ke-cam-form (max-width:420px) li lascia stretti nel wizard. */
.ke-onboarding .ke-cam-form { max-width: none; width: 100%; }
.ke-onboarding .ke-cam-fiscal-wrap { width: 100%; }
.ke-onboarding .ke-cam-form--fiscal > .ke-cam-fiscal {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 2px 20px;
	align-items: start;
}
.ke-onboarding .ke-cam-form--fiscal > .ke-cam-fiscal > h3,
.ke-onboarding .ke-cam-form--fiscal > .ke-cam-fiscal > .ke-cam-note,
.ke-onboarding .ke-cam-form--fiscal > .ke-cam-fiscal > p:last-child {
	grid-column: 1 / -1;
}
/* ⚠️ I GRUPPI OCCUPANO TUTTA LA RIGA, e le colonne le fanno LORO al loro
   interno (`.ke-firma-griglia`). Dal 25/08 i campi non sono piu' figli diretti
   di questa griglia ma stanno dentro i riquadri «Chi sei / Nascita /
   Indirizzo / Dati fiscali»: senza questa riga ogni riquadro diventerebbe UNA
   CELLA della griglia esterna, e da li' in giu' il modulo si scompagina. Il
   collaudo se n'e' accorto prima che lo vedesse Sergio. */
.ke-onboarding .ke-cam-form--fiscal > .ke-cam-fiscal > fieldset.ke-firma-gruppo {
	grid-column: 1 / -1;
	margin-inline: 0;
}
.ke-onboarding .ke-cam-form--fiscal > .ke-cam-fiscal > p { margin: 12px 0 0; }
@media (max-width: 640px) {
	.ke-onboarding .ke-cam-form--fiscal > .ke-cam-fiscal { grid-template-columns: 1fr; }
}

/* Broadcast earnings pills: tips vs private-room earnings (today). */
.ke-cam-earnbar { display: flex; gap: 12px; flex-wrap: wrap; margin: 10px 0 4px; }
.ke-cam-earnpill { background: #1b1526; border: 1px solid #3a2f4a; border-radius: 999px; padding: 6px 14px; font-size: 13px; color: #cdc3e0; }
.ke-cam-earnpill .k { color: #8a7ca8; margin-inline-end: 4px; }
.ke-cam-earnpill b { color: #fff; }

/* Group-show toggle (broadcast) + opt-in invite (viewer). */
.ke-cam-group-toggle.ke-cam-group-on { background: var(--ke-accent, #e50914); color: #fff; }
.ke-cam--groupinvite { display: flex; align-items: center; justify-content: center; min-height: 220px; background: #140f1e; border: 1px solid #3a2f4a; border-radius: 12px; text-align: center; padding: 24px; }
.ke-cam-groupinvite-box { max-width: 460px; }
.ke-cam-groupinvite-box h3 { color: #e8e2f2; margin: 0 0 8px; }
.ke-cam-groupinvite-box p { color: #cdc3e0; margin: 0 0 14px; }
.ke-cam--groupinvite .ke-cam-recharge { display: inline-block; margin-inline-start: 10px; color: var(--ke-accent, #e50914); }

/* waiting overlay must never block the native video controls / play button */
.ke-cam-wait { pointer-events: none; position: absolute; top: 14%; left: 0; right: 0; text-align: center; color: #8a7ca8; }

/* session earnings log (broadcast page) */
.ke-cam-sesslog { margin-top: 14px; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 10px; padding: 12px 16px; }
.ke-cam-sesslog h4 { margin: 0 0 8px; color: #e8e2f2; font-size: 14px; }
.ke-cam-sesslog-list { list-style: none; margin: 0; padding: 0; height: 220px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.ke-cam-sesslog-list li { color: #cdc3e0; font-size: 13px; }
.ke-cam-sesslog-empty { color: #8a7ca8; }

/* Banned-users list (performer studio): un-ban each with a button. */
.ke-cam-banned { margin-top: 14px; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 10px; padding: 12px 16px; }
.ke-cam-banned h4 { margin: 0 0 8px; color: #e8e2f2; font-size: 14px; }
.ke-cam-banned-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; height: 220px; overflow-y: auto; }
.ke-cam-banned-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: #cdc3e0; font-size: 13px; }
.ke-cam-banned-item .ke-cam-btn { padding: 5px 12px; font-size: 13px; }
.ke-cam-banned-empty { color: #8a7ca8; font-size: 13px; }

/* one-click quick top-up */
.ke-quick-topup { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-inline-start: 10px; }
.ke-quick-label { color: #8a7ca8; font-size: 13px; }
.ke-quick-btn { background: transparent; border: 1px solid var(--ke-accent, #e50914); color: var(--ke-accent, #e50914); border-radius: 999px; padding: 3px 12px; font-size: 12px; font-weight: 700; cursor: pointer; }
.ke-quick-btn:hover { background: var(--ke-accent, #e50914); color: #fff; }
.ke-quick-btn small { font-weight: 500; }
.ke-quick-msg { font-size: 12px; color: #8a7ca8; transition: color .2s; }
.ke-quick-msg--ok { color: #5fd08a; font-weight: 700; }
.ke-quick-msg--err { color: #ff6b6b; font-weight: 600; }
/* Il collegamento che dice DOVE risolvere: sta dentro un messaggio d'errore, e
   deve leggersi come una via d'uscita, non come altro rosso. Area di tocco
   generosa: chi lo preme sta guardando uno spettacolo a pagamento, col pollice. */
.ke-quick-fix { display: inline-block; margin-left: 6px; padding: 3px 8px; border-radius: 6px;
	background: rgba(255,255,255,.12); color: #ece9f1; font-weight: 700; text-decoration: none; white-space: nowrap; }
.ke-quick-fix:hover, .ke-quick-fix:focus-visible { background: rgba(255,255,255,.22); color: #fff; }
.ke-quick-fix:focus-visible { outline: 2px solid #e50914; outline-offset: 2px; }
/* Quello che compare PRIMA di premere, quando già si sa che mancano i dati. */
/* La pagina di chi è sospeso. Sobria di proposito: è una brutta notizia, non
   un allarme — un riquadro rosso lampeggiante fa pensare a un guasto, e qui non
   c'è nessun guasto da riparare. Testo leggibile e una via per chiedere. */
.ke-sospeso {
	max-width: 620px;
	margin: 32px auto;
	padding: 24px 26px;
	border-radius: 14px;
	background: #17111f;
	border: 1px solid #3a2f4a;
	border-left: 4px solid #d19b00;
	color: #ece9f1;
	line-height: 1.65;
}
.ke-sospeso-tit { margin: 0 0 6px; font-size: 20px; color: #fff; }
.ke-sospeso-quando { margin: 0 0 14px; color: #9b93a8; font-size: 13px; }
.ke-sospeso-motivo { background: rgba(209,155,0,.12); padding: 10px 12px; border-radius: 8px; margin: 0 0 14px; }
.ke-sospeso .ke-cam-btn { display: inline-block; text-decoration: none; margin-top: 6px; }

.ke-quick-fix--prima { margin-left: 0; background: rgba(229,9,20,.18); color: #ffd9dc; }
.ke-quick-fix--prima:hover, .ke-quick-fix--prima:focus-visible { background: rgba(229,9,20,.30); color: #fff; }
.ke-pack-vault { display: block; font-size: 12px; color: #8a7ca8; margin: 8px 0; }

/* Post-1:1 intermission (broadcast page): performer is hidden from the public
   until they press "Torna disponibile". */
.ke-cam-pausebox { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 14px 0; padding: 14px 18px; background: rgba(229, 9, 20, .10); border: 1px solid rgba(229, 9, 20, .4); border-radius: 12px; }
.ke-cam-pausebox-label { color: #f0d9dc; font-size: 14px; flex: 1 1 260px; }
.ke-cam-pausebox .ke-cam-resume { background: var(--ke-accent, #e50914); color: #fff; border: 0; }

/* air between stacked cards inside the fiscal wrap */
.ke-cam-fiscal-wrap .ke-cam-fiscal { margin-bottom: 20px; }
.ke-cam-fiscal-wrap form > p:last-child { margin-top: 0; }

/* room chat */
.ke-cam-chat { margin: 16px 0; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 12px; padding: 14px 16px; }
.ke-cam-chat-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; }
.ke-cam-chat-title { margin: 0; font-size: 14px; color: #e8e2f2; }
.ke-cam-chat-order { flex: none; background: transparent; border: 1px solid #3a2f4a; border-radius: 6px; color: #b9a7e6; font-size: 12px; padding: 4px 9px; cursor: pointer; white-space: nowrap; }
.ke-cam-chat-order:hover { border-color: #4a3d5e; color: #fff; }
.ke-cam-chat-log { height: 240px; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; padding-inline-end: 4px; }
/* Messaggio su due righe: sopra bandiera + nome (+ provenienza della traduzione),
   sotto il testo, rientrato fino all'altezza del nome — così la colonna dei testi è
   allineata e la lettura scorre, invece di avere nome e testo appiccicati. */
.ke-cam-chat-msg { font-size: 14px; color: #cdc3e0; line-height: 1.45; word-break: break-word; margin-bottom: 7px; }
.ke-cam-msg-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 5px; }
.ke-cam-chat-name { font-weight: 700; color: #b9a7e6; }
.ke-cam-chat-flag { font-weight: 400; font-size: 1.05em; line-height: 1; }
/* Il rientro è la larghezza della bandiera + il suo spazio: i testi restano in colonna
   anche per chi non ha bandiera (nessun paese noto). */
/* Il messaggio in corsivo, il nome in grassetto: a colpo d'occhio si distingue chi
   parla da ciò che dice, e la riga di provenienza resta un terzo livello discreto.
   Il tema imposta font-synthesis:none su :root — con un carattere privo di corsivo e
   grassetto veri il browser non li disegna affatto (era il motivo per cui la
   distinzione non si vedeva). Qui, solo nella chat, lasciamo che li sintetizzi. */
.ke-cam-chat-msg, .ke-cam-chat-msg * { font-synthesis: style weight; -webkit-font-synthesis: style weight; }
.ke-cam-chat-text { padding-inline-start: 1.45em; font-style: italic; }
/* The performer (room owner) is always red; your own name is cyan — but only when
   you're NOT the performer. On the performer's own studio their messages are both
   mine and perf, so is-perf wins → red, exactly as before. Everyone else: default. */
/* Your own name: warm amber + a "(tu)" tag so it's distinguishable WITHOUT relying on
   colour (colour-blind friendly). The performer stays red. */
.ke-cam-chat-msg.is-mine:not(.is-perf) .ke-cam-chat-name { color: #e0a53a; }
.ke-cam-chat-msg.is-mine:not(.is-perf) .ke-cam-chat-name::after { content: ' (tu)'; font-weight: 400; font-size: .82em; opacity: .85; }
.ke-cam-chat-msg.is-perf .ke-cam-chat-name { color: var(--ke-accent, #e50914); }
/* La moderazione, quando parla scoperta: verde e con una barretta a lato, così si
   distingue da un utente qualunque anche a colpo d'occhio e anche senza colore. */
.ke-cam-chat-msg.is-mod { border-inline-start: 3px solid #3ba55d; padding-inline-start: 8px; }
.ke-cam-chat-msg.is-mod .ke-cam-chat-name { color: #3ba55d; font-weight: 700; }
.ke-cam-chat-form { display: flex; gap: 8px; }
/* font-size 16px: iOS Safari auto-zooms into any focused input below 16px. */
.ke-cam-chat-input { flex: 1; min-width: 0; padding: 9px 12px; border-radius: 8px; border: 1px solid #3a2f4a; background: #221b2c; color: #fff; box-sizing: border-box; font-size: 16px; }
.ke-cam-chat-empty { color: #8a7ca8; font-size: 13px; }

/* Room layout (viewer): a grid so we can reorder for portrait vs landscape.
   Desktop / phone-landscape: video + rest on the left, chat spanning on the right. */
.ke-cam-room {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 340px;
	grid-template-areas: "video chat" "rest chat";
	gap: 16px 20px;
	align-items: start;
	max-width: 1180px;
	margin: 0 auto;
}
.ke-cam-room > .ke-cam-view { grid-area: video; max-width: none; margin: 0; }
.ke-cam-room > .ke-cam-room-side { grid-area: chat; align-self: stretch; display: flex; min-width: 0; min-height: 0; }
.ke-cam-room > .ke-cam-room-rest { grid-area: rest; min-width: 0; display: flex; flex-wrap: wrap; gap: 12px; align-items: stretch; }
/* Most rows span full width; the two action cards (1:1 request + group reservation)
   sit side by side, wrapping to one column when there isn't room. */
.ke-cam-room > .ke-cam-room-rest > * { flex: 1 1 100%; min-width: 0; margin-top: 0; }
.ke-cam-room > .ke-cam-room-rest > .ke-cam-o2o-box,
.ke-cam-room > .ke-cam-room-rest > .ke-cam-group-resv { flex: 1 1 calc(50% - 6px); min-width: 240px; }
.ke-cam-room-side .ke-cam-chat { margin: 0; flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* flex-basis 0 (not auto): the chat's height is dictated by the video column, and
   the log fills what's left — otherwise the log's content grows the grid row and the
   chat ends up taller than the video. */
.ke-cam-room-side .ke-cam-chat-log { height: auto; flex: 1 1 0; min-height: 0; }
/* Exit-to-archive button (mobile immersive rooms hide the site header/menu). */
.ke-cam-exit { display: inline-block; margin-top: 14px; color: #b9a7e6; font-weight: 700; text-decoration: none; }
.ke-cam-exit:hover { color: #fff; }

/* Performer studio: title + today's earnings on top; below, video with the chat
   beside it (chat matches the video height) and the online users list (kick/ban/
   report) right under the chat; the tips history + share link fill the rest. */
.ke-cam-studio {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 340px;
	grid-template-areas: "head head" "video chat" "rest users";
	gap: 16px 20px;
	align-items: start;
	max-width: 1180px;
	margin: 0 auto;
}
.ke-cam-studio-head { grid-area: head; display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 4px; }
.ke-cam-studio-title { margin: 0; font-size: clamp(24px, 3vw, 38px); font-weight: 800; }
.ke-cam-studio .ke-cam-earnbar { margin: 0; flex-wrap: wrap; }
/* The studio renders its own title row (above) with the earnings pills, so hide the
   theme's duplicate page title. Duplicated from the theme CSS here because THIS sheet
   is always freshly loaded, so the fix lands even if the theme CSS is browser-cached. */
body.ke-cam-studio-page .ke-single-title { display: none; }
body.ke-cam-studio-page .ke-single-content { padding-top: 0; }
.ke-cam-studio > .ke-cam-livecol { grid-area: video; min-width: 0; }
.ke-cam-studio > .ke-cam-chat { grid-area: chat; align-self: stretch; margin: 0; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.ke-cam-studio > .ke-cam-chat .ke-cam-chat-log { height: auto; flex: 1 1 0; min-height: 0; }
.ke-cam-studio > .ke-cam-viewerlist { grid-area: users; min-width: 0; }
.ke-cam-studio > .ke-cam-rest { grid-area: rest; min-width: 0; }
/* Mance ricevute + Utenti bannati side by side (share link full-width below) so the
   page doesn't get taller. Collapses to one column on narrow / fullscreen. */
.ke-cam-studio > .ke-cam-rest { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
.ke-cam-studio > .ke-cam-rest > .ke-cam-share { grid-column: 1 / -1; }
.ke-cam-studio > .ke-cam-rest > .ke-cam-sesslog, .ke-cam-studio > .ke-cam-rest > .ke-cam-banned { margin-top: 0; }

/* Fullscreen button + fullscreen room */
.ke-cam-fs { margin-inline-start: auto; padding: 8px 12px; display: inline-flex; align-items: center; }
.ke-cam-fs svg { display: block; }
/* Fullscreen: the video fills the height on the left with the chat full-height on
   the right; the costs/tip row tucks under the video. No page scroll, nothing cut. */
.ke-cam-room:-webkit-full-screen { display: grid; width: 100%; height: 100%; max-width: none; margin: 0; padding: 10px; gap: 10px; background: #0c0a11; grid-template-columns: minmax(0, 1fr) 340px; grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "video chat" "rest chat"; }
.ke-cam-room:fullscreen { display: grid; width: 100%; height: 100%; max-width: none; margin: 0; padding: 10px; gap: 10px; background: #0c0a11; grid-template-columns: minmax(0, 1fr) 340px; grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "video chat" "rest chat"; }
.ke-cam-room:fullscreen > .ke-cam-view { min-height: 0; height: 100%; display: flex; flex-direction: column; }
.ke-cam-room:fullscreen .ke-cam-stage { flex: 1 1 auto; min-height: 0; max-height: none; aspect-ratio: auto; border-radius: 0; }
.ke-cam-room:fullscreen .ke-cam-stage video { height: 100%; max-height: none; }
.ke-cam-room:fullscreen > .ke-cam-room-side { align-self: stretch; }
.ke-cam-room:fullscreen > .ke-cam-room-rest { padding: 4px 12px; }
/* Studio fullscreen: focus on the video + chat (hide the title/earnings, users list
   and the tips history/share row). The go-live/mute controls stay in the video bar. */
/* Studio fullscreen: video on the left at full height; on the right the chat takes
   the top ~half, and below it the online users (kick/ban/report) and the tips-received
   history — so the performer keeps everyone, invites and tips in view. (Invites + live
   tips also appear under the video, in the tips feed.) */
.ke-cam-studio:-webkit-full-screen { display: grid; width: 100%; height: 100%; max-width: none; margin: 0; padding: 10px; gap: 10px; background: #0c0a11; grid-template-columns: minmax(0, 1fr) 360px; grid-template-rows: auto 30vh minmax(0, 1fr) 26vh; grid-template-areas: "video head" "video chat" "video users" "video rest"; }
.ke-cam-studio:fullscreen { display: grid; width: 100%; height: 100%; max-width: none; margin: 0; padding: 10px; gap: 10px; background: #0c0a11; grid-template-columns: minmax(0, 1fr) 360px; grid-template-rows: auto 30vh minmax(0, 1fr) 26vh; grid-template-areas: "video head" "video chat" "video users" "video rest"; }
/* Head above the chat: keep the two earnings pills (title hidden), abbreviated to
   icon + number so they fit on one line (full label on hover via title). */
.ke-cam-studio:-webkit-full-screen > .ke-cam-studio-head,
.ke-cam-studio:fullscreen > .ke-cam-studio-head { grid-area: head; align-self: stretch; margin: 0; padding: 8px 10px 2px; justify-content: center; }
.ke-cam-studio:-webkit-full-screen .ke-cam-studio-title,
.ke-cam-studio:fullscreen .ke-cam-studio-title { display: none; }
.ke-cam-studio:-webkit-full-screen .ke-cam-earnbar,
.ke-cam-studio:fullscreen .ke-cam-earnbar { flex-wrap: nowrap; gap: 8px; justify-content: center; }
.ke-cam-studio:-webkit-full-screen .ke-cam-earnpill .k,
.ke-cam-studio:fullscreen .ke-cam-earnpill .k,
.ke-cam-studio:-webkit-full-screen .ke-cam-earnpill .ke-earn-unit,
.ke-cam-studio:fullscreen .ke-cam-earnpill .ke-earn-unit { display: none; }
.ke-cam-studio:fullscreen > .ke-cam-livecol,
.ke-cam-studio:-webkit-full-screen > .ke-cam-livecol { grid-area: video; min-height: 0; height: 100%; display: flex; flex-direction: column; }
.ke-cam-studio:fullscreen .ke-cam-stage,
.ke-cam-studio:-webkit-full-screen .ke-cam-stage { flex: 1 1 auto; min-height: 0; max-height: none; aspect-ratio: auto; border-radius: 0; }
.ke-cam-studio:fullscreen .ke-cam-stage video,
.ke-cam-studio:-webkit-full-screen .ke-cam-stage video { height: 100%; max-height: none; }
.ke-cam-studio:fullscreen > .ke-cam-chat,
.ke-cam-studio:-webkit-full-screen > .ke-cam-chat { grid-area: chat; align-self: stretch; min-height: 0; margin: 0; }
.ke-cam-studio:fullscreen > .ke-cam-viewerlist,
.ke-cam-studio:-webkit-full-screen > .ke-cam-viewerlist { grid-area: users; align-self: stretch; min-height: 0; overflow-y: auto; margin: 0; padding: 6px 10px; }
.ke-cam-studio:fullscreen > .ke-cam-rest,
.ke-cam-studio:-webkit-full-screen > .ke-cam-rest { grid-area: rest; align-self: stretch; min-height: 0; overflow: hidden; display: grid; grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; padding: 4px 10px 8px; }
/* The two boxes fill the row so their lists are visible (not collapsed to the title). */
.ke-cam-studio:fullscreen > .ke-cam-rest > .ke-cam-sesslog,
.ke-cam-studio:fullscreen > .ke-cam-rest > .ke-cam-banned,
.ke-cam-studio:-webkit-full-screen > .ke-cam-rest > .ke-cam-sesslog,
.ke-cam-studio:-webkit-full-screen > .ke-cam-rest > .ke-cam-banned { min-height: 0; height: 100%; overflow: hidden; }
/* Bottom cards fill their fixed row and scroll inside (no column growth); the room
   link isn't needed while broadcasting fullscreen. */
.ke-cam-studio:fullscreen > .ke-cam-rest > .ke-cam-share,
.ke-cam-studio:-webkit-full-screen > .ke-cam-rest > .ke-cam-share { display: none; }
.ke-cam-studio:fullscreen .ke-cam-sesslog, .ke-cam-studio:fullscreen .ke-cam-banned,
.ke-cam-studio:-webkit-full-screen .ke-cam-sesslog, .ke-cam-studio:-webkit-full-screen .ke-cam-banned { margin: 0; display: flex; flex-direction: column; min-height: 0; }
.ke-cam-studio:fullscreen .ke-cam-sesslog-list, .ke-cam-studio:fullscreen .ke-cam-banned-list,
.ke-cam-studio:-webkit-full-screen .ke-cam-sesslog-list, .ke-cam-studio:-webkit-full-screen .ke-cam-banned-list { height: auto; flex: 1 1 0; min-height: 0; }

/* group-show reservation (viewer): same card shape as the 1:1 box so they match. */
.ke-cam-group-resv { display: flex; flex-direction: column; background: #1b1526; border: 1px solid #6b5b8f; border-radius: 12px; padding: 18px; color: #e8e2f2; margin-top: 18px; }
.ke-cam-group-resv h4 { margin: 0 0 6px; color: #e8e2f2; font-size: 16px; }
.ke-cam-group-resv p { color: #8a7ca8; margin: 0 0 10px; }
.ke-cam-group-resv .ke-cam-resv-btn { margin-top: auto; align-self: flex-start; }
.ke-cam-group-resv .ke-cam-resv-count { color: #fff; font-weight: 700; }
.ke-cam-group-resv[data-reserved="1"] .ke-cam-resv-btn { background: #234c30; }
/* reservation indicator in the performer's bar (pushed to the right) */
.ke-cam-resv-info { display: inline-flex; align-items: center; gap: 8px; margin-inline-start: auto; color: #cdc3e0; font-size: 13px; }
.ke-cam-resv-info b { color: #fff; }

/* In-page confirm dialog (kept inside the studio so it never exits fullscreen). */
.ke-cam-confirm { position: fixed; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center; background: rgba(10, 8, 14, .72); }
.ke-cam-confirm-box { background: #1b1526; border: 1px solid #3a2f4a; border-radius: 12px; padding: 20px 22px; max-width: 380px; text-align: center; box-shadow: 0 12px 40px rgba(0, 0, 0, .5); }
.ke-cam-confirm-box p { margin: 0 0 16px; color: #e8e2f2; }
/* Stessa regola del consenso cookie: prima si va a capo, poi si comprime. Senza,
   in 336px utili i due pulsanti si schiacciavano e il testo andava su due righe
   dentro il pulsante. */
.ke-cam-confirm-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
/* Ban/report reason: preset tag chips + an optional short note (16px avoids iOS zoom). */
.ke-cam-reason-tags { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin: 0 0 12px; }
.ke-cam-reason-tag { background: transparent; border: 1px solid #3a2f4a; color: #cdc3e0; border-radius: 999px; padding: 5px 12px; font-size: 13px; cursor: pointer; }
.ke-cam-reason-tag:hover { border-color: #6b5b8f; color: #fff; }
.ke-cam-reason-tag.is-on { background: var(--ke-accent, #e50914); border-color: var(--ke-accent, #e50914); color: #fff; }
.ke-cam-reason-note { width: 100%; box-sizing: border-box; margin: 0 0 14px; padding: 8px 10px; border-radius: 6px; border: 1px solid #3a2f4a; background: #14101a; color: #e8e2f2; font-size: 16px; }
.ke-cam-ban-why { cursor: help; }
.ke-cam-banned-item[title] { cursor: help; }
/* What the admin decided on a reported user (shown in the performer's ban list). */
.ke-cam-ban-admin { display: inline-block; margin-inline-start: 6px; font-size: 11px; font-weight: 700; color: #e0a53a; }
/* Unpaid-fine (debt) banner shown to the user in the room. */
.ke-cam-debt { margin: 0 0 12px; }
.ke-cam-debt a { color: #fff; text-decoration: underline; font-weight: 700; }

/* Kick/ban "you're out" overlay with a cheeky animation. */
.ke-cam-eject { position: fixed; inset: 0; z-index: 10000; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 22px; background: #0c0a11; color: #fff; text-align: center; padding: 24px; }
.ke-cam-eject-msg { margin: 0; font-size: clamp(16px, 2.4vw, 22px); font-weight: 700; max-width: 520px; opacity: 0; animation: ke-eject-msg-in .5s ease-out 1.4s forwards; }
@keyframes ke-eject-msg-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.ke-eject-scene { position: relative; width: 260px; height: 160px; font-size: 64px; }
.ke-eject-scene > span { position: absolute; }
/* KICK: a boot swings in from the left, the victim flies off to the right, stars pop. */
.ke-eject-kick .ke-eject-victim { left: 42%; top: 44px; animation: ke-kick-fly 1.1s ease-in .35s forwards; }
.ke-eject-kick .ke-eject-boot { left: -34%; top: 50px; animation: ke-kick-boot .5s ease-in forwards; }
.ke-eject-kick .ke-eject-boom { left: 38%; top: 30px; opacity: 0; animation: ke-kick-boom .5s ease-out .35s; }
@keyframes ke-kick-boot { 0% { left: -34%; } 70% { left: 18%; } 100% { left: 10%; } }
@keyframes ke-kick-fly { 0% { transform: translateX(0) rotate(0); } 100% { transform: translateX(240px) rotate(90deg); opacity: 0; } }
@keyframes ke-kick-boom { 0% { opacity: 0; transform: scale(.4); } 40% { opacity: 1; transform: scale(1.3); } 100% { opacity: 0; transform: scale(1.6); } }
/* BAN: the captain salutes as the ship tilts and goes down into the rising sea. */
.ke-eject-ban .ke-eject-sea { left: 0; right: 0; bottom: -6px; text-align: center; letter-spacing: -10px; animation: ke-ban-sea 1.8s ease-in-out infinite; }
.ke-eject-ban .ke-eject-boat { left: 42%; top: 34px; animation: ke-ban-sink 2.4s ease-in forwards; }
.ke-eject-ban .ke-eject-sailor { left: 47%; top: 12px; font-size: 34px; animation: ke-ban-sink 2.4s ease-in .1s forwards; }
.ke-eject-ban .ke-eject-flag { left: 55%; top: 4px; font-size: 30px; animation: ke-ban-sink 2.4s ease-in forwards; }
@keyframes ke-ban-sink { 0% { transform: translateY(0) rotate(0); } 40% { transform: translateY(6px) rotate(-12deg); } 100% { transform: translateY(96px) rotate(-26deg); opacity: .15; } }
@keyframes ke-ban-sea { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }

/* Viewer notice when the performer temporarily mutes / blacks out the video. */
/* ⚠️ IL CARTELLO DELLA PAUSA, E I DUE CHE DEVE COPRIRE.
   Durante la pausa dello show privato i due avvisi di sempre — «video oscurato»,
   «audio muto» — sono verissimi e rispondono alla domanda sbagliata: chi ha un
   contatore davanti vuole sapere se sta pagando. Si nascondono e al loro posto va
   quello che parla di soldi. In giallo, non in rosso: e' una sospensione, non un
   guasto, e il rosso qui dentro vuol dire «qualcosa non va». */
.ke-cam-pausenote {
	position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 7;
	background: rgba(12, 10, 17, .9); color: #f2d98c; border: 1px solid #e6a417;
	border-radius: 12px; padding: 12px 20px; font-size: 15px; font-weight: 600;
	text-align: center; width: max-content; max-width: 88%; pointer-events: none;
}
.ke-cam--live.is-o2o-paused .ke-cam-avnote { display: none; }
.ke-cam-avnote { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 6; display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none; width: max-content; max-width: 88%; }
.ke-cam-avnote span { background: rgba(12, 10, 17, .82); color: #fff; border: 1px solid rgba(255, 255, 255, .18); border-radius: 999px; padding: 8px 16px; font-size: 14px; font-weight: 600; text-align: center; }

/* 1:1 talkback: viewer "Parla" button (idle = discreet outline; on = accent) + the
   performer's "viewer mic connected" badge. */
/* Viewer talkback mic: same round overlay control as the performer (.ke-cam-av /
   .is-off). The .ke-cam-talkctl wrapper reuses .ke-cam-avctl (top-right). */
.ke-cam-talkctl { pointer-events: auto; }
.ke-cam-talkback-badge { margin: 8px 0; }

/* group-member bar: rate + leave button, wraps cleanly on phones */
.ke-cam-group-member { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ke-cam-group-member .ke-cam-btn { margin-inline-start: auto; }

/* mobile: room controls stack instead of overflowing */
@media (max-width: 780px) {
	.ke-cam-view, .ke-cam-studio { max-width: 100%; }
	.ke-cam-group-member .ke-cam-btn { margin-inline-start: 0; width: 100%; }
	.ke-cam-o2o-endbtn { width: 100%; margin-top: 8px; }
	/* Cap the stage height so it can't push the tip/1:1 controls off-screen on
	   phones (iOS Safari can over-size a 16/9 video with an attached stream). */
	.ke-cam-stage { max-height: 60vh; aspect-ratio: auto; min-height: 210px; }
	.ke-cam-stage video { height: auto; max-height: 60vh; }
	.ke-cam-bar { flex-wrap: wrap; gap: 10px; }
	.ke-cam-tipbox { margin-inline-start: 0; width: 100%; justify-content: space-between; flex-wrap: wrap; }
	.ke-cam-toklive { margin-inline-start: 0; width: 100%; }
	.ke-cam-o2o-box .ke-cam-btn { width: 100%; }
	.ke-cam-costs { font-size: 13px; line-height: 1.7; }
	.ke-quick-topup { margin-inline-start: 0; }
	.ke-cam-viewer-row { flex-wrap: wrap; }
}

/* Phone/tablet PORTRAIT: single column, ordered video → chat → the rest (studio:
   title → video → chat → users → rest). The theme hides the site header/footer here
   (body.ke-cam-immersive) for a clean full-screen room. */
@media (max-width: 899px) and (orientation: portrait) {
	.ke-cam-room {
		grid-template-columns: 1fr;
		grid-template-areas: "video" "chat" "rest";
		gap: 12px;
	}
	.ke-cam-studio {
		grid-template-columns: 1fr;
		grid-template-areas: "head" "video" "chat" "users" "rest";
		gap: 12px;
	}
	/* Fixed chat height so it can't stretch off-screen; the log scrolls inside. */
	.ke-cam-room > .ke-cam-room-side,
	.ke-cam-studio > .ke-cam-chat { align-self: start; }
	.ke-cam-room-side .ke-cam-chat-log,
	.ke-cam-studio > .ke-cam-chat .ke-cam-chat-log { flex: none; min-height: 0; height: 240px; }
	/* Tips + banned back to one column on a narrow phone (too tight side by side). */
	.ke-cam-studio > .ke-cam-rest { grid-template-columns: 1fr; }
}
/* Phone/tablet LANDSCAPE: video + chat on top (chat = video height), and the info
   cards full-width below in two columns to keep the page short. */
@media (max-width: 899px) and (orientation: landscape) {
	.ke-cam-room { grid-template-columns: minmax(0, 1fr) 42%; grid-template-areas: "video chat" "rest rest"; }
	.ke-cam-studio { grid-template-columns: minmax(0, 1fr) 42%; }
}
/* Save vertical space on phones (both orientations): the performer name is already
   shown in the bar under the video. */
@media (max-width: 899px) {
	body.ke-cam-immersive .ke-single-title { display: none; }
}

/* Traduzione messaggi chat (bottone "Traduci" + output "Tradotto da"). */
.ke-cam-chat-tr { display: inline; margin-inline-start: 4px; padding: 0; border: 0; background: none; color: var(--ke-accent, #e50914); font-size: 11px; cursor: pointer; opacity: 0.85; }
.ke-cam-chat-tr:hover { opacity: 1; text-decoration: underline; }
.ke-cam-chat-trout { display: block; margin-top: 2px; font-size: 13px; color: #cfd0da; }
/* Provenienza: NON corsiva, ora che il corsivo distingue il testo del messaggio. */
.ke-cam-chat-trby { font-style: normal; font-size: 11px; color: #8a8a97; letter-spacing: .02em; }

/* --- Stealth moderator view (?ke_mod=1) ---------------------------------- */
/* Banner prepended on the room page for a webcam manager. */
.ke-mod-banner { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 14px; padding: 10px 14px; border: 1px solid #6b4fbf; border-inline-start: 4px solid #6b4fbf; border-radius: 10px; background: rgba(107,79,191,.14); color: #e7e0f5; font-size: 14px; }
.ke-mod-banner a { color: #c9b8ff; font-weight: 600; }
.ke-mod-badge { display: inline-block; padding: 2px 10px; border-radius: 999px; background: #6b4fbf; color: #fff; font-size: 12px; font-weight: 700; letter-spacing: .03em; }

.ke-cam-mod { display: block; }
.ke-cam-mod-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 8px; }
.ke-cam-mod-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 999px; background: #6b4fbf; color: #fff; font-weight: 700; font-size: 13px; }
.ke-cam-mod-title { font-size: 17px; color: #f2ecff; }
.ke-cam-mod-state { color: #fff; background: #4a5568; }
.ke-cam-mod-state.ke-cam-mode-group { background: #2f7fd1; }
.ke-cam-mod-state.ke-cam-mode-o2o { background: #6b4fbf; }
.ke-cam-mod-state.ke-cam-mode-paused { background: #b8862f; }
.ke-cam-mod-links { margin-inline-start: auto; display: inline-flex; gap: 8px; }
.ke-cam-mod-note { margin: 0 0 14px; color: #b7abcf; font-size: 13px; }
.ke-cam-mod-body { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(240px, 1fr); gap: 16px; align-items: start; }
.ke-cam-mod-side { display: flex; flex-direction: column; gap: 16px; }
.ke-cam-mod-viewers { border: 1px solid #2b2338; border-radius: 12px; padding: 12px 14px; background: rgba(30,24,42,.5); }
.ke-cam-mod-viewers h4 { margin: 0 0 10px; font-size: 14px; color: #d7cdea; }
.ke-cam-mod-empty { margin: 0; color: #8a7fa0; font-size: 13px; }
.ke-cam-mod-chat { margin-top: 16px; }
.ke-cam-chat-ro { margin: 0; padding: 8px 12px; color: #9c92b3; font-size: 12px; font-style: italic; border-top: 1px solid #2b2338; }
@media (max-width: 860px) { .ke-cam-mod-body { grid-template-columns: 1fr; } }

/* Avviso anti-recapiti nella chat + clausole di moderazione nel form performer. */
.ke-cam-chat-warn { margin: 0 0 8px; padding: 8px 11px; border-radius: 8px; font-size: 12.5px; line-height: 1.45; color: #ffd9c2; background: #3a1f18; border: 1px solid #7a3a24; }
.ke-cam-terms { font-size: 12.5px; line-height: 1.5; }
.ke-cam-terms strong { display: block; margin-bottom: 6px; color: #e8e2f2; }
.ke-cam-terms ul { margin: 0; padding-inline-start: 18px; }
.ke-cam-terms li { margin: 4px 0; }

/* Form di registrazione performer: card centrata orizzontalmente nella pagina. */
.ke-cam-form--center { margin-left: auto; margin-right: auto; margin-top: 30px; max-width: 460px; }

/* Contratto performer da sottoscrivere (gate go-live). */
.ke-contract-gate { max-width: 720px; margin: 24px auto; }
.ke-contract-doc { background: #1b1526; border: 1px solid #3a2f4a; border-radius: 12px; padding: 22px 24px; margin: 16px auto; color: #cdc3e0; }
.ke-contract-doc h3 { margin: 0 0 4px; color: #e8e2f2; }
.ke-contract-ver { margin: 0 0 14px; color: #8a7ca8; font-size: 12px; }
.ke-contract-clauses { margin: 12px 0; padding-inline-start: 20px; }
.ke-contract-clauses li { margin: 8px 0; line-height: 1.5; }

/* Onboarding performer (pagina profilo con checklist). */
.ke-onboarding { max-width: 760px; margin: 20px auto; }
.ke-onboarding-checklist { list-style: none; margin: 16px 0; padding: 14px 18px; background: #1b1526; border: 1px solid #3a2f4a; border-radius: 12px; }
.ke-onboarding-checklist li { display: flex; align-items: center; gap: 8px; padding: 6px 0; color: #cdc3e0; font-size: 14px; }
.ke-onboarding-checklist li.is-done { color: #8fe0ad; }
.ke-onboarding-checklist .ke-ob-mark { font-weight: 700; width: 18px; text-align: center; }
.ke-onboarding .ke-ob-step, .ke-onboarding .ke-ob-submit { margin-top: 18px; }
.ke-perf-cats { border: 1px solid #3a2f4a; border-radius: 8px; padding: 10px 12px; margin: 8px 0; }
.ke-perf-cats legend { padding: 0 6px; color: #e8e2f2; font-size: 13px; }
.ke-perf-cat { display: inline-flex; align-items: center; gap: 5px; margin: 4px 0; margin-inline-end: 12px; font-size: 13px; color: #cdc3e0; }

/* ---- Sezioni performer dentro la dashboard a colonna (.ke-account-main) ----
   Le sezioni ora vivono nella colonna principale del menu laterale: i box
   riempiono la larghezza, non più le larghezze del vecchio layout a griglia
   (fiscale mezza colonna / stanze impilate). */
.ke-account-main .ke-cam-form { max-width: none; width: 100%; }
.ke-account-main .ke-cam-earnings,
.ke-account-main .ke-cam-fiscal { margin-top: 0; }

/* Dati fiscali: piena larghezza, campi su più colonne (niente mezza colonna). */
.ke-account-main .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 0 20px;
	align-items: start;
}
.ke-account-main .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type > h3,
.ke-account-main .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type > .ke-cam-note,
.ke-account-main .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type > p:last-child { grid-column: 1 / -1; }
.ke-account-main .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type > p { margin: 12px 0 0; }

/* Impostazioni show: le due card (gruppo + 1:1) affiancate invece che impilate. */
.ke-account-main .ke-perf-rooms {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
	gap: 20px;
	align-items: start;
}
.ke-account-main .ke-perf-rooms > .ke-cam-fiscal { margin-top: 0; }

@media (max-width: 760px) {
	.ke-account-main .ke-cam-form--fiscal > .ke-cam-fiscal:first-of-type,
	.ke-account-main .ke-perf-rooms { grid-template-columns: 1fr; }
}

/* --- Layout adattivo: usa tutta la finestra ------------------------------- *
   Studio e stanza girano senza header/footer, quindi possono comportarsi come
   un'applicazione invece che come una pagina: il video prende l'altezza
   disponibile e la colonna laterale (chat + utenti) gli sta accanto a piena
   altezza, su qualunque monitor. Le condizioni sono due:
   - larghezza >= 900px: sotto, il layout resta impilato (mobile/tablet stretto);
   - altezza >= 620px: su finestre basse lo scorrimento verticale è più leggibile
     di un video schiacciato.
   `:not(:fullscreen)` lascia intatto il layout del fullscreen API, che ha regole
   proprie. L'altezza tiene conto della barra amministrazione di WordPress.       */
body.admin-bar { --ke-adminbar: 32px; }
@media screen and (max-width: 782px) { body.admin-bar { --ke-adminbar: 46px; } }

@media (min-width: 900px) {
	.ke-cam-studio:not(:fullscreen), .ke-cam-view:not(:fullscreen) { max-width: none; margin: 0; }
	.ke-cam-room:not(:fullscreen) { max-width: none; margin: 0; }
}

@media (min-width: 900px) and (min-height: 620px) {
	/* --- L'interfaccia intera sta nella finestra ---------------------------- *
	   Non solo il video: testata, video, chat, elenchi e card devono essere tutti
	   visibili insieme, senza scorrimento su schermi normali e senza vuoti su
	   monitor grandi. Il contenitore prende l'altezza della finestra e la
	   distribuisce: righe fisse per testata e code, il video si prende ciò che
	   resta. Ogni cella ha min-height:0 (senza, una griglia non lascia mai
	   rimpicciolire i figli sotto il loro contenuto) e i riquadri che possono
	   eccedere scorrono al proprio interno invece di allungare la pagina.       */

	/* --- Studio performer --- */
	.ke-cam-studio:not(:fullscreen) {
		height: calc(100dvh - var(--ke-adminbar, 0px) - 58px);
		grid-template-columns: minmax(0, 1fr) clamp(300px, 22vw, 440px);
		grid-template-rows: auto minmax(0, 1fr) minmax(0, 0.42fr);
		align-items: stretch;
		overflow: hidden;
	}
	.ke-cam-studio:not(:fullscreen) > .ke-cam-livecol { display: flex; flex-direction: column; min-height: 0; }
	.ke-cam-studio:not(:fullscreen) > .ke-cam-livecol > .ke-cam-stage {
		flex: 1 1 0; min-height: 180px; height: auto; aspect-ratio: auto; max-height: none;
	}
	.ke-cam-studio:not(:fullscreen) > .ke-cam-chat { min-height: 0; }
	.ke-cam-studio:not(:fullscreen) > .ke-cam-viewerlist { min-height: 0; overflow-y: auto; margin: 0; }
	.ke-cam-studio:not(:fullscreen) > .ke-cam-rest { min-height: 0; overflow-y: auto; }
	/* Le liste dentro le card scorrono da sole, così le card non si allungano. */
	.ke-cam-studio:not(:fullscreen) > .ke-cam-rest .ke-cam-sesslog-list,
	.ke-cam-studio:not(:fullscreen) > .ke-cam-rest .ke-cam-banned-list { max-height: none; }

	/* --- Stanza (spettatore) --- */
	.ke-cam-room:not(:fullscreen) {
		height: calc(100dvh - var(--ke-adminbar, 0px) - 132px);
		grid-template-columns: minmax(0, 1fr) clamp(300px, 22vw, 440px);
		grid-template-rows: minmax(0, 1fr) minmax(0, 0.42fr);
		align-items: stretch;
		overflow: hidden;
	}
	.ke-cam-room:not(:fullscreen) > .ke-cam-view { display: flex; flex-direction: column; min-height: 0; }
	.ke-cam-room:not(:fullscreen) > .ke-cam-view > .ke-cam-stage {
		flex: 1 1 0; min-height: 180px; height: auto; aspect-ratio: auto; max-height: none;
	}
	.ke-cam-room:not(:fullscreen) > .ke-cam-room-side { min-height: 0; }
	.ke-cam-room:not(:fullscreen) > .ke-cam-room-rest { min-height: 0; overflow-y: auto; }
}

/* Nota di conformità 2257: nella stanza/studio il footer del sito è nascosto, quindi
   la nota vive qui. Pulsante ben visibile (non un rimando in punta di piedi) che apre
   un <dialog> nativo, sempre consultabile. */
.ke-cam-2257-btn {
	padding: 7px 14px; font-size: 12px; font-weight: 700; letter-spacing: .03em;
	color: #f2ecff; background: #2b2338; border: 1px solid #6b5b8f; border-radius: 6px;
	cursor: pointer; white-space: nowrap;
}
.ke-cam-2257-btn:hover, .ke-cam-2257-btn:focus-visible { background: #3a2f4a; border-color: #9b86d6; color: #fff; }
.ke-2257-dlg {
	max-width: 620px; width: calc(100% - 32px); border: 1px solid #3a2f4a; border-radius: 12px;
	background: #1b1526; color: #e8e2f2; padding: 22px 24px; box-shadow: 0 18px 50px rgba(0,0,0,.6);
}
.ke-2257-dlg::backdrop { background: rgba(0,0,0,.6); }
.ke-2257-title { margin: 0 0 12px; font-size: 18px; color: #fff; }
.ke-2257-body { line-height: 1.6; font-size: 14px; color: #cdc3e0; max-height: 60vh; overflow-y: auto; }
.ke-2257-body p { margin: 0 0 10px; }
.ke-2257-dlg form { margin: 16px 0 0; text-align: end; }
/* Specchio anteprima: acceso di default (ci si vede come allo specchio); da spento
   il pulsante è smorzato, così si capisce a colpo d'occhio in che modalità si è. */
.ke-cam-av-flip.is-off { opacity: .55; }
/* Avviso mostrato solo quando l'anteprima di chi trasmette resta davvero in pausa. */
.ke-cam-selfhint { margin: 6px 0 0; padding: 7px 12px; border: 1px solid #6b5b8f; border-radius: 8px; background: rgba(107,79,191,.14); color: #e7e0f5; font-size: 13px; }
/* Anteprima su canvas (Safari): il <video> resta in riproduzione ma invisibile — e con
   lui spariscono i comandi che Safari gli disegna sopra — mentre il canvas mostra gli
   stessi fotogrammi, alla stessa risoluzione. */
.ke-cam-stage .ke-cam-self.is-hidden-src { opacity: 0; }
.ke-cam-selfcanvas { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; z-index: 2; background: #000; }
/* Impostazioni show: i due riquadri stanno in un unico form, con il pulsante di
   salvataggio unico sotto entrambi. */
.ke-perf-showsave { margin: 14px 0 0; }


/* ------------------------------------------------------------------------
   LINGUE DESTRA-SINISTRA (arabo, urdu)
   ------------------------------------------------------------------------
   Qui sotto SOLO cio' che non si puo' dire con le proprieta' logiche: sfumature
   direzionali, ombre, trasformazioni, posizioni di sfondo. Tutto il resto e' gia'
   scritto in proprieta' logiche piu' su e si specchia da solo.

   Regola: se una cosa si puo' esprimere con margin-inline-start / inset-inline-end
   e simili, VA SCRITTA LI', non qui. Questo blocco deve restare corto.
   ------------------------------------------------------------------------ */
/* background-position non ha equivalente logica: senza override la freccia resta a destra sopra il testo */
[dir="rtl"] .ke-cam-fiscal select { background-position: left 11px center; }
/* scenetta animata coerente (left + @keyframes su left + translateX): va specchiata IN BLOCCO, mai proprieta' per proprieta' */
[dir="rtl"] .ke-eject-scene { transform: scaleX(-1); }

/* Pagamenti della performer: la stessa riga di nota dei guadagni, piu' la
   variante che avvisa. Il giallo serve a distinguere «aspetta la soglia» da
   «aspetta TE»: sono due attese diverse e una sola delle due la puo' sbloccare
   lei. */
.ke-cam-payouts { margin-top: 18px; }
.ke-cam-earnnote--warn { color: #f0c04a; }
.ke-tab--payouts { width: 100%; margin-top: 10px; border-collapse: collapse; }
.ke-tab--payouts th, .ke-tab--payouts td { padding: 6px 8px; text-align: left; border-bottom: 1px solid rgba(255,255,255,.08); font-size: 13px; }
.ke-tab--payouts th { color: var(--ke-muted, #b6adc7); font-weight: 600; }

/* ⚠️ `hidden` DEVE VINCERE SUL `display:` QUI SOPRA.
   L'attributo `hidden` vale quanto `display: none`, ma una regola di classe
   con `display:` ha la stessa specificita' e, venendo dopo, vince: l'elemento
   resta visibile anche quando il codice lo dichiara nascosto. E' successo sul
   riquadro «Correggi e ricandida» del portale inserzionisti, dove il pulsante
   sembrava non fare niente perche' il riquadro era gia' aperto. */
.ke-cam-avctl[hidden] { display: none; }
.ke-cam-playgate-ic[hidden] { display: none; }
.ke-cam-resv-info[hidden] { display: none; }
