/* dark-only theme, Watermelon accent (#00bbb4) — same tokens as the Equipment app */

/* ---------- Caratteri, serviti dal nostro dominio ----------
   Prima arrivavano da fonts.googleapis.com. Non scrivevano cookie, ma a ogni
   apertura l'indirizzo IP di chi apriva finiva a Google senza che nessuno
   avesse chiesto niente. Ora i file stanno in fonts/ qui accanto e non esce
   nessuna richiesta verso l'esterno.
   IBM Plex e' sotto Open Font License, che consente di ospitarlo in proprio.
   Due sottoinsiemi per peso: `latin` copre italiano e inglese, `latin-ext`
   le accentate delle altre lingue europee. L'unicode-range fa scaricare al
   browser solo quelli che gli servono: sono 10 file dichiarati, ma su una
   pagina italiana ne scendono uno o due. Toglierlo li farebbe scaricare
   tutti.
   Ogni app tiene la sua copia invece di puntare a una cartella comune:
   restano pacchetti indipendenti, come sono gia' i loro zip. */

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --bg: #0e0e10;
  --surface: #1a1a1d;
  --surface-2: #242428;
  --border: #303034;
  --text: #f0f0f2;
  --text-dim: #9a9aa0;
  --accent: #00bbb4;
  --accent-soft: rgba(0, 187, 180, 0.16);
  --accent-ink: #05201f;
  --green: #4cd080;
  --green-soft: rgba(0, 187, 180, 0.14);
  --amber: #e0b13b;
  --amber-soft: rgba(224, 177, 59, 0.16);
  --heart: #e0475b;
  --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 4px 16px rgba(0,0,0,0.25);
  --radius: 12px;
  /* tells every browser this page is dark-themed, so native controls it
     doesn't otherwise style (date picker, select dropdown list, scrollbars)
     render in dark colors instead of the OS/browser light default —
     standard, cross-browser fix (Chrome/Firefox/Safari), unlike the old
     WebKit-only ::-webkit-calendar-picker-indicator filter hack */
  color-scheme: dark;
}

* { box-sizing: border-box; }

/* generic hide switch — !important because plenty of components (e.g.
   .hdr-icon-btn's own `display: flex`) are equal-specificity single-class
   selectors defined later in the cascade, which would otherwise win and
   silently re-show the element */
.hidden { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* while the detail modal is open, scrolling inside it (or overscrolling
   past its top/bottom edge) must not also scroll the page underneath */
body.modal-open { overflow: hidden; }

/* La stessa larghezza del sito, ricavata dal suo codice e non a occhio.
   Il contenuto del sito sta in una griglia di 26 colonne larga 1440 con 11px
   di gap, e comincia dalla seconda colonna — sta scritto nel markup del
   footer condiviso: --d:1/2/2/26. Quindi:
     colonna = (1440 - 25*11) / 26 = 44,81
     rientro = 44,81 + 11          = 55,81   ->  colonna utile 1328,4
   Sotto i 1440 la griglia si stringe con la finestra e il rientro con lei,
   restando il 3,876% della sua larghezza: min() dice le due cose insieme.
   Misurato sul sito vivo a 1500px di finestra: contenuto da 86 a 1414. */
#app {
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 min(55.81px, 3.876vw) 60px;
}

/* Il footer condiviso deve stare sotto lo stesso rientro del contenuto, o si
   vede che non sono allineati. La variante --wide di footer.css nasce a 1200
   e qui la si porta ai valori qui sopra. Sta in questo foglio e non in
   footer.css apposta: quel file lo caricano anche le dieci pagine del sito,
   e cambiarlo vorrebbe dire ribumparle e ricaricarle tutte. Tenuto qui, i due
   numeri stanno accanto a quello di #app da cui devono non discostarsi.
   Il selettore comincia da body per una ragione precisa: in Production
   style.css e' caricato PRIMA di footer.css, quindi a parita' di specificita'
   perderebbe. */
body .site-footer--app.site-footer--wide {
  --fo-row-w: 1440px;
  --fo-row-pad: min(55.81px, 3.876vw);
}
/* page-load reveal (see the fuller comment near .apply-page below) —
   #content is never removed/reinserted, only its own innerHTML is
   swapped on every search/filter/tab change, so this only ever plays
   once on the real page load, not on every re-render */
#app.reveal-page > * {
  opacity: 0;
  animation: revealUp .3s cubic-bezier(.22, 1, .36, 1) both;
}
#app.reveal-page > *:nth-child(1) { animation-delay: 0ms; }
#app.reveal-page > *:nth-child(2) { animation-delay: 30ms; }
#app.reveal-page > *:nth-child(3) { animation-delay: 60ms; }
#app.reveal-page > *:nth-child(4) { animation-delay: 90ms; }
#app.reveal-page > *:nth-child(n+5) { animation-delay: 120ms; }
@media (prefers-reduced-motion: reduce) {
  #app.reveal-page > * { animation: none; opacity: 1; }
}

.sticky-top {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  padding-top: 16px;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-bottom: 16px;
}
.topbar-spacer { flex: 1; }

.brand-logo {
  width: 48px;
  height: 48px;
  border-radius: 11px;
  object-fit: cover;
  flex-shrink: 0;
  margin-right: 10px;
}
/* same as ODG's/Equipment's own .brand-col + .brand-title-list — logo
   stays alone in the compact topbar row, the app name sits on its own
   line below, at identical size/weight/spacing across all three apps */
.brand-col { display: flex; flex-direction: column; gap: 3px; min-width: 0; margin-bottom: 18px; }
.brand-title-list { font-size: 22px; font-weight: 700; color: var(--text); }

.hdr-icon-btn {
  border: none;
  background: none;
  color: var(--text);
  padding: 6px;
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hdr-icon-btn:hover { color: var(--accent); }
.hdr-icon-btn.active { color: var(--accent); }
.hdr-icon-btn .icon-close { display: none; }
.hdr-icon-btn.active .icon-search { display: none; }
.hdr-icon-btn.active .icon-close { display: block; }

#favToggle.active #favToggleIcon { fill: var(--heart); stroke: var(--heart); }

.tabs {
  display: flex;
  gap: 22px;
  overflow-x: auto;
  border-bottom: 1px solid var(--border);
  margin-bottom: 14px;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  white-space: nowrap;
  border: none;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--text-dim);
  padding: 0 0 10px;
  font-size: 15px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.tab:hover { color: var(--text); }
.tab.active {
  color: var(--text);
  font-weight: 700;
  border-bottom-color: var(--accent);
}

/* sits inline in the topbar, immediately left of the search toggle, so it
   never covers the other header icons (Filtri etc. stay clickable while
   the field is open) — capped width, it only ever holds short queries */
.searchrow {
  display: flex;
  align-items: center;
  min-width: 0;
  flex: 0 1 280px;
  margin-right: 4px;
}
.searchrow.hidden { display: none; }
.topbar-icons { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
/* la lente prima del + (Carlo, 07/09/2026): cercare e' il gesto di ogni
   giorno, aggiungere quello raro. order:-1 la porta in testa senza
   toccare il markup, e nei tab senza + non cambia niente. */
#searchToggle { order: -1; }
/* IL CUORE IN TESTATA NON SI VEDE PIU' (Carlo, 07/09/2026): la funzione
   «solo preferiti» ora vive come voce nella bacheca. Il bottone resta nel
   DOM - e' il motore del filtro (favOnly), su cui si appoggia la voce
   della bacheca - ma nascosto. Per riaverlo in testata: togliere questa
   riga. */
#favToggle { display: none; }
.searchrow input {
  width: 100%;
  min-width: 0;
  padding: 8px 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  outline: none;
}
.searchrow input:focus { border-color: var(--accent); }

/* --- filters panel: one column of checkboxes per taxonomy, wraps on mobile */
.filterspanel {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 28px;
  padding: 14px 0 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}
.filterspanel.hidden { display: none; }
.filter-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 130px;
}
.filter-group h4 {
  margin: 0 0 2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.filter-chk {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
}
.filter-chk input { accent-color: var(--accent); }
.filters-clear {
  border: none;
  background: none;
  color: var(--accent);
  font-size: 13px;
  cursor: pointer;
  padding: 4px 0;
  align-self: flex-start;
}
.filters-clear:hover { text-decoration: underline; }

/* --- shareable lists panel ("Bacheca") ---
   Styled to read as a distinct board, same recipe as ODG App's/Equipment
   App's own project-list rows (.odg-row / .list-row there): bordered,
   shadowed, surface-colored cards stacked with a gap, not a plain
   divider-separated list — the previous look was too subtle to register
   as "this is a list of lists." */
.listspanel {
  padding: 14px 0 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}
.listspanel.hidden { display: none; }
.lists-panel-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.lists-panel-head-title { display: flex; align-items: center; gap: 4px; }
.lists-panel-head-title .hdr-icon-btn { margin-left: -6px; }
.lists-panel-title { font-size: 22px; font-weight: 700; margin: 0; }
.list-rows { display: flex; flex-direction: column; gap: 8px; }
.list-row-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: border-color .12s;
}
.list-row-card:hover { border-color: var(--accent); }
.list-row-card.active { border-color: var(--accent); background: var(--accent-soft); }
.list-row-card-main { flex: 1; min-width: 0; }
.list-row-card-name { font-size: 15px; font-weight: 700; margin: 0; }
.list-row-card-name-input {
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  background: none;
  border: none;
  border-bottom: 1px solid var(--accent);
  padding: 0 0 2px;
  width: 100%;
  max-width: 260px;
}
.list-row-card-name-input:focus { outline: none; }
.list-row-card-sub { font-size: 13px; color: var(--text-dim); margin: 3px 0 0; }
.list-row-card-actions { display: flex; gap: 2px; flex-shrink: 0; }
.list-action-btn {
  border: none;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  padding: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.list-action-btn:hover { color: var(--accent); }
.list-action-btn-delete:hover { color: var(--heart); }
.list-empty { color: var(--text-dim); font-size: 13px; }

/* --- add-to-list control inside the detail modal --- */
.modal-addlist-newbtn {
  border: none;
  background: none;
  color: var(--accent);
  font-size: 12.5px;
  cursor: pointer;
}
.modal-addlist-newbtn:hover { text-decoration: underline; }

.resultsmeta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
  color: var(--text-dim);
  margin: 0 0 14px;
}
/* single flex child on the right of .resultsmeta, so the map toggle never
   shifts position depending on whether the grid-size slider is showing */
.resultsmeta-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.gridsize {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0 10px;
  background: var(--surface);
  color: var(--text-dim);
  box-sizing: border-box;
}
.gridsize input[type="range"] {
  width: 90px;
  accent-color: var(--accent);
  cursor: pointer;
}
.maptoggle {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0 10px;
  background: var(--surface);
  color: var(--text-dim);
  font-size: 12.5px;
  font-family: inherit;
  cursor: pointer;
  box-sizing: border-box;
}
.maptoggle:hover { border-color: var(--accent); color: var(--accent); }
.maptoggle.active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.location-map-view {
  height: calc(100vh - 220px);
  min-height: 360px;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
}
.map-infowin { display: flex; flex-direction: column; gap: 6px; min-width: 160px; }
.map-infowin img { width: 100%; height: 90px; object-fit: cover; border-radius: 6px; display: block; }
.map-infowin-title { font-size: 13px; font-weight: 700; color: #1a1a1a; margin: 0; }
.map-infowin-sub { font-size: 12px; color: #555; margin: 0; }
.map-infowin-btn {
  margin-top: 2px;
  border: none;
  border-radius: 6px;
  background: var(--accent);
  color: #05201f;
  font-weight: 700;
  font-size: 12px;
  font-family: inherit;
  padding: 6px 10px;
  cursor: pointer;
}

/* --- photo grid (casting) --- */
/* the zoom slider's own --card-min floor is quite low (60px) so it still
   has room to zoom out further, but cards must never actually get small
   enough to pack more than 6 per row on a wide desktop window — max()
   clamps the effective minmax floor to whichever is bigger: the slider's
   value, or "exactly 6 columns wide" for the current container width (5
   gaps of 12px between 6 cards). The narrow-screen media query below
   tightens this further, to a max of 3 per row on a phone. */
.grid-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(max(var(--card-min, 150px), calc((100% - 5 * 12px) / 6)), 1fr));
  gap: 12px;
}
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: transform .12s, border-color .12s;
}
.card:hover { border-color: var(--accent); }
.card-photo {
  width: 100%;
  aspect-ratio: 3/4;
  object-fit: cover;
  background: var(--surface-2);
  display: block;
}
.card-photo-empty {
  width: 100%;
  aspect-ratio: 3/4;
  background: var(--surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 28px;
  font-weight: 700;
}
.card-square .card-photo, .card-square .card-photo-empty { aspect-ratio: 1/1; }
.list-members-grid { grid-template-columns: repeat(auto-fill, minmax(max(var(--card-min, 162px), calc((100% - 5 * 12px) / 6)), 1fr)); }
.card-body { padding: 9px 10px 5px; display: flex; flex-direction: column; flex: 1; }
/* long names with no natural break point (e.g. a single long surname)
   would otherwise overflow the card's width and get clipped by .card's
   own overflow:hidden at small zoom levels — break mid-word instead */
.card-name { font-size: 13.5px; font-weight: 700; margin: 0 0 2px; line-height: 1.25; overflow-wrap: break-word; }
.card-sub { font-size: 11.5px; color: var(--text-dim); line-height: 1.4; font-weight: 500; }
.card-sub-spaced { margin-top: auto; padding-top: 6px; font-size: 11px; font-weight: 400; opacity: 0.78; }
.card-fav {
  position: absolute;
  top: 7px;
  right: 7px;
  border: none;
  background: rgba(0,0,0,0.45);
  border-radius: 50%;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  cursor: pointer;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.card-fav.active { color: var(--heart); }
.card-fav svg { fill: none; stroke: currentColor; }
.card-fav.active svg { fill: currentColor; }

/* same floating circular slot as .card-fav, used instead of it inside a
   Bacheca list's member grid — a stateless action (no .active fill), red on
   hover matching the destructive-red convention used everywhere else */
.card-remove-btn {
  position: absolute;
  top: 7px;
  right: 7px;
  border: none;
  background: rgba(0,0,0,0.45);
  border-radius: 50%;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  cursor: pointer;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.card-remove-btn:hover { color: var(--heart); }

/* client favorite/reject tri-state, mirrored from share.js/share.html so
   staff can see and override it from the Bacheca list-members popup without
   opening the client's own share link — sits top-left, .card-remove-btn
   (top-right) stays the only occupant of that corner */
.card-status-btns { position: absolute; top: 7px; left: 7px; display: flex; gap: 6px; z-index: 1; }
.status-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: none;
  background: rgba(0,0,0,0.45);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.status-btn svg { fill: none; stroke: currentColor; }
.status-btn.active svg { fill: currentColor; }
.status-favorite.active { background: var(--accent); color: #05201f; }
.status-reject.active { background: var(--heart); color: #fff; }
.card.status-favorite { border-color: var(--accent); }
.card.status-rejected { border-color: var(--heart); opacity: 0.6; }

.dup-tag {
  position: absolute;
  top: 7px;
  left: 7px;
  z-index: 1;
  background: rgba(0,0,0,0.6);
  color: var(--text);
  font-size: 10.5px;
  font-weight: 600;
  padding: 3px 7px;
  border-radius: 20px;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.dup-tag-inline {
  position: static;
  display: inline-block;
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: 2px 6px;
  font-size: 10px;
  vertical-align: middle;
}

/* --- list rows (location, recruitment) --- */
.list-rows { display: flex; flex-direction: column; gap: 8px; }
.list-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: border-color .12s;
}
.list-row:hover { border-color: var(--accent); }
.list-row-thumb {
  width: 52px;
  height: 52px;
  border-radius: 8px;
  object-fit: cover;
  background: var(--surface-2);
  flex-shrink: 0;
}
.list-row-thumb-empty {
  width: 52px;
  height: 52px;
  border-radius: 8px;
  background: var(--surface-2);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-weight: 700;
}
.list-row-main { flex: 1; min-width: 0; }
.list-row-name { font-size: 14.5px; font-weight: 700; margin: 0 0 2px; }
.list-row-sub { font-size: 12.5px; color: var(--text-dim); line-height: 1.25; font-weight: 500; }
.list-row-sub-spaced { margin-top: 2px; font-weight: 400; opacity: 0.78; }
.list-row-links { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.list-row-link-icon { display: flex; color: var(--text-dim); }
.list-row-link-icon:hover { color: var(--accent); }
.list-row-fav {
  border: none;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  padding: 6px;
}
.list-row-fav.active { color: var(--heart); }
.list-row-fav svg { fill: none; stroke: currentColor; }
.list-row-fav.active svg { fill: currentColor; }

/* client heart/reject tri-state + remove, for the Bacheca list-members
   popup's row view (recruitment) — same .status-btn look as the photo-card
   grid version, just laid out inline instead of floating over a photo */
.list-row.status-favorite { border-color: var(--accent); }
.list-row.status-rejected { border-color: var(--heart); opacity: 0.6; }
.list-row-status-btns { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.list-row-remove-btn {
  border: none;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  padding: 6px;
}
.list-row-remove-btn:hover { color: var(--heart); }

.empty-state {
  text-align: center;
  color: var(--text-dim);
  font-size: 14px;
  padding: 60px 20px;
}

.conn-banner {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--amber-soft);
  color: var(--amber);
  border: 1px solid var(--amber);
  border-radius: 10px;
  padding: 8px 14px;
  font-size: 12.5px;
  font-weight: 600;
  margin: 8px 0;
}
/* an error can be triggered by an action INSIDE the detail modal (e.g. a
   failed photo upload) — the banner has to outrank the modal (z-index 100)
   and lightbox (200), or it renders invisibly behind them */
#connBanner {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 300;
  max-width: calc(100vw - 32px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
}
.conn-banner.hidden { display: none; }

.toast-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 300;
  opacity: 0;
  pointer-events: none;
  cursor: pointer;
  transition: opacity 0.18s ease;
}
.toast-overlay.show { opacity: 1; pointer-events: auto; }
.toast-card {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 14px 28px;
  border-radius: 14px;
  font-size: 15px;
  font-weight: 600;
  box-shadow: var(--shadow);
}

/* --- login gate (identical pattern to Equipment app) --- */
.login-gate {
  position: fixed;
  inset: 0;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 500;
  padding: 24px;
}
.login-gate.hidden { display: none; }
.login-card {
  width: 100%;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
}
.login-logo {
  width: 112px;
  height: 112px;
  border-radius: 28px;
  object-fit: cover;
  margin-bottom: 6px;
}
.login-brand { font-size: 16px; font-weight: 700; color: var(--text); margin: 0 0 4px; }
.login-sub { font-size: 13.5px; color: var(--text-dim); margin: 0 0 4px; }
#loginStepEmail, #loginStepCode,
#otpStepEmail, #otpStepCode {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}
#loginStepEmail.hidden, #loginStepCode.hidden,
#otpStepEmail.hidden, #otpStepCode.hidden { display: none; }
.login-email-row {
  position: relative;
  width: 100%;
}
.login-email-row input { width: 100%; padding-right: 46px; }
.login-email-row .hdr-icon-btn {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
}
.login-gate input {
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 15px;
  outline: none;
  text-align: center;
  font-family: inherit;
}
.login-gate input:focus { border-color: var(--text-dim); }
/* Safari/Chrome autofill forces its own pale background + dark text,
   painting over the send button (fixed above with z-index) and breaking
   the dark theme — this repaints it as the app's own surface color instead */
.login-gate input:-webkit-autofill,
.login-gate input:-webkit-autofill:hover,
.login-gate input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
  transition: background-color 5000s ease-in-out 0s;
}
.login-error {
  color: var(--amber);
  font-size: 12.5px;
  min-height: 1em;
  margin: 0;
}

/* --- detail modal --- */
.modal {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
}
.modal.hidden { display: none; }
/* Il riquadro del modulo di inserimento: grande quasi quanto lo schermo,
   senza imbottitura, perche' dentro c'e' una pagina che ha gia' la sua.
   `min()` e non una misura fissa: su un portatile piccolo il riquadro non
   deve uscire dallo schermo, e su uno grande non deve diventare enorme. */
.modal-card-form { width: min(920px, 96vw); height: min(88vh, 1040px); padding: 0; overflow: hidden; }
.modal-card-form iframe { width: 100%; height: 100%; border: 0; display: block; border-radius: var(--radius); }
.modal-card {
  background: var(--bg);
  border-radius: 16px;
  max-width: 640px;
  width: 100%;
  max-height: 86vh;
  overflow-y: auto;
  padding: 24px;
  position: relative;
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
  /* only #detailModal's card actually drags (see modalCard's touch
     handlers in app.js), but this is harmless on every other .modal-card
     too: pan-y tells the browser vertical scroll is still native, so it
     doesn't fight our own horizontal-drag detection */
  touch-action: pan-y;
}
.modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  border: none;
  background: none;
  color: var(--text);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  z-index: 2;
}
.modal-close:hover { color: var(--accent); }
/* same spot/size as modal-close, just one slot to its left — same pattern
   as ODG's editModeToggle next to its own header icons */
.modal-edit-toggle {
  position: absolute;
  top: 14px;
  right: 50px;
  border: none;
  background: none;
  color: var(--text);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  z-index: 2;
}
.modal-edit-toggle:hover { color: var(--accent); }
.modal-edit-toggle.editing { color: var(--accent); }
/* pencil ⇄ checkmark swap while editing, same convention as ODG's own
   editModeToggle (.icon-pencil/.icon-check) */
.modal-edit-toggle .icon-check { display: none; }
.modal-edit-toggle.editing .icon-pencil { display: none; }
.modal-edit-toggle.editing .icon-check { display: block; }

/* same spot/size again, one more slot to the left — "add to a list", only
   shown on tabs with hasLists (Casting/Location) */
.modal-addlist-toggle {
  position: absolute;
  top: 14px;
  right: 86px;
  border: none;
  background: none;
  color: var(--text);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  z-index: 2;
}
.modal-addlist-toggle:hover { color: var(--accent); }
.modal-addlist-toggle.active { color: var(--accent); }
.modal-addlist-popover {
  position: absolute;
  top: 52px;
  right: 14px;
  z-index: 3;
  width: 230px;
  max-width: calc(100% - 28px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 12px;
}
.modal-addlist-popover.hidden { display: none; }
.modal-addlist-popover-title { font-size: 12px; font-weight: 700; color: var(--text-dim); margin: 0 0 8px; text-transform: uppercase; letter-spacing: .02em; }
.modal-addlist-options { display: flex; flex-direction: column; gap: 2px; max-height: 200px; overflow-y: auto; margin-bottom: 8px; }
.modal-addlist-option { display: flex; align-items: center; gap: 8px; padding: 6px 4px; font-size: 13.5px; cursor: pointer; border-radius: 6px; }
.modal-addlist-option:hover { background: var(--surface-2); }

/* --- edit mode: inline field inputs, replacing the plain modal-row values */
.modal-row-edit { flex-direction: column; align-items: stretch; gap: 6px; }
.modal-edit-input {
  width: 100%;
  padding: 7px 10px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  outline: none;
}
.modal-edit-input:focus { border-color: var(--accent); }
/* new-list prompt (replaces the old native prompt()) — plain label above
   each field, same modal-edit-input styling used everywhere else */
.modal-field-label { display: block; font-size: 12.5px; font-weight: 600; color: var(--text-dim); margin: 0 0 6px; }
.modal-field-label:not(:first-child) { margin-top: 14px; }
#newListModal .modal-save-btn { margin-top: 18px; }
textarea.modal-edit-input { resize: vertical; min-height: 60px; }
/* Il campo data su iOS ha una larghezza sua e sborda oltre gli altri
   (screenshot di Carlo, 06/09/2026) - stessa cura gia' data al modulo
   yoga: si spegne l'aspetto di sistema e lo si obbliga nel contenitore.
   `display: flex` perche' senza, con appearance spento, Safari centra
   il testo in verticale a modo suo e la data balla rispetto agli altri
   campi. */
input[type="date"].modal-edit-input {
  -webkit-appearance: none;
  appearance: none;
  display: flex;
  align-items: center;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}
.modal-edit-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.modal-edit-phone { display: flex; gap: 8px; }
.modal-edit-phone select { flex-shrink: 0; width: 120px; }
.modal-edit-multiselect { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.modal-edit-multiselect .apply-select-row { padding: 9px 12px; font-size: 13px; }
.modal-hero-title-edit { display: flex; gap: 8px; }
.modal-hero-title-edit input { font-size: 19px; font-weight: 700; padding: 4px 8px; }
.modal-card-narrow { max-width: 420px; }
/* list members popup — same 900px standard as the apply-*.html forms and
   share.html, wide enough for the photo-card grid instead of the default
   640px single-record width */
.modal-title { font-size: 17px; font-weight: 700; margin: 0 0 16px; }
.modal-save-btn {
  width: 100%;
  border: none;
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: 10px;
  padding: 12px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  margin-top: 4px;
}
.modal-danger-btn { background: var(--heart); color: #fff; }

.modal-hero {
  display: flex;
  gap: 16px;
  margin-bottom: 6px;
}
.modal-hero-photo {
  width: 110px;
  height: 110px;
  border-radius: 12px;
  object-fit: cover;
  background: var(--surface-2);
  flex-shrink: 0;
  cursor: zoom-in;
}
.modal-hero-photo-empty {
  width: 110px;
  height: 110px;
  border-radius: 12px;
  background: var(--surface-2);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 32px;
  font-weight: 700;
}
.modal-hero-info {
  flex: 1;
  min-width: 0;
  padding-top: 2px;
  display: flex;
  flex-direction: column;
}
/* padding-right reserves space for the addlist/edit/close buttons, which
   are position:absolute (top:14px, right:14-86px) and so don't push this
   flex row's content over on their own — without it, the two Nome/Cognome
   edit inputs stretch under those buttons on narrow (iPhone) widths */
.modal-hero-title-row { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; padding-right: 120px; }
.modal-hero-info h2 { margin: 0; font-size: 19px; }
.modal-hero-sub { margin: 0; font-size: 13px; color: var(--text-dim); line-height: 1.5; font-weight: 500; }
.modal-hero-sub-spaced { margin-top: 4px; font-weight: 400; opacity: 0.78; }
/* pushed to the bottom of the info column, which is as tall as the hero
   photo next to it — lines the date up with the photo's bottom edge */
.modal-hero-date { margin: 0; font-size: 11.5px; color: var(--text-dim); flex-shrink: 0; }
/* icon-only now, next to the name — used to be a labeled "Aggiungi ai
   preferiti" row of its own further down the hero column */
.modal-hero-fav {
  border: none;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
  flex-shrink: 0;
}
.modal-hero-fav.active { color: var(--heart); }
.modal-hero-fav svg { fill: none; stroke: currentColor; width: 18px; height: 18px; }
.modal-hero-fav.active svg { fill: currentColor; }

/* Location & Casting detail — big photo on top (prev/next + set-main/delete
   overlaid), filmstrip of small thumbnails below. Title now sits above this
   block full-width instead of squeezed beside a small square photo. */
.modal-hero-info-full { padding-top: 0; margin-bottom: 4px; }
.modal-gallery { margin: 14px 0; }
.modal-gallery-main {
  position: relative;
  width: 100%;
  height: 320px;
  border-radius: 12px;
  background: var(--surface-2);
  overflow: hidden;
}
/* position:relative e overflow:hidden servono allo scorrimento fra una foto
   e l'altra: durante il gesto qui dentro convivono due elementi in posizione
   assoluta, quello che esce e quello che entra, e cio' che esce dai bordi
   non deve vedersi. */
.modal-gallery-photo-slot { position: relative; overflow: hidden;
                            width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
.modal-gallery-photo {
  width: 100%;
  height: 100%;
  object-fit: contain;
  cursor: zoom-in;
}
.modal-gallery-empty {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 40px;
  font-weight: 700;
}
.modal-gallery-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  border: none;
  background: rgba(0,0,0,0.45);
  color: #fff;
  font-size: 22px;
  line-height: 1;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}
.modal-gallery-arrow:hover { background: rgba(0,0,0,0.65); }
.modal-gallery-prev { left: 10px; }
.modal-gallery-next { right: 10px; }
.modal-gallery-main-actions {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 6px;
  z-index: 2;
}
.modal-gallery-thumbs {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  overflow-x: auto;
  padding-bottom: 2px;
}
.modal-gallery-thumb {
  flex-shrink: 0;
  width: 64px;
  height: 64px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface-2);
  cursor: pointer;
}
.modal-gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.modal-gallery-thumb-broken { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: var(--text-dim); }
.modal-gallery-thumb.active { border-color: var(--accent); }
.modal-gallery-thumbs .modal-photo-add { width: 64px; height: 64px; flex-shrink: 0; }
.photo-action-btn {
  border: none;
  background: rgba(0,0,0,0.55);
  color: #fff;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.photo-action-btn:hover { color: var(--accent); }
.photo-action-btn-delete:hover { color: var(--heart); }

.modal-photo-add {
  width: 100%;
  height: 90px;
  border-radius: 8px;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.modal-photo-add:hover { border-color: var(--accent); color: var(--accent); }

.modal-section { margin: 16px 0; }
/* same recipe as the public forms' section headers (cardHeadHtml/
   .apply-card-head-title) — short accent underline, only as wide as the
   text — for visual consistency between the internal detail view and the
   apply-*.html forms the data actually comes from */
.modal-section h3 {
  display: inline-block;
  margin: 0 0 10px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  padding-bottom: 8px;
  border-bottom: 2px solid var(--accent);
}
/* videos live inside the same carousel as photos (modal-gallery) — main
   slot plays them full-size, thumbs show the raw <video> (browsers paint
   its first frame once metadata loads) with a play badge on top */
.modal-gallery-video { width: 100%; height: 100%; object-fit: contain; background: #000; }
.modal-gallery-thumb-video { position: relative; background: #000; }
.modal-gallery-thumb-video video { width: 100%; height: 100%; object-fit: cover; display: block; }
.modal-gallery-thumb-play {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #fff; background: rgba(0,0,0,0.25); pointer-events: none;
}
.modal-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.modal-row:last-child { border-bottom: none; }
/* ">" here matters: without it, this also matches nested spans inside a
   row's own value (e.g. the first/last Servizi chip, which is also a
   <span> and also a first/last-child of ITS OWN parent) */
.modal-row > span:first-child { color: var(--text-dim); flex-shrink: 0; }
.modal-row > span:last-child { text-align: right; }
.modal-row-link { color: var(--accent); text-decoration: none; }
.modal-row-link:hover { text-decoration: underline; }
/* Servizi (Location) — label on its own line above a wrapping row of
   amenity chips, instead of squeezed into the standard label/value columns */
.modal-row-stacked { flex-direction: column; align-items: flex-start; gap: 8px; }
/* ">" here matters: without it this also matches the last .modal-service-chip
   itself (also a <span>, also a last-child), stretching it to full width */
.modal-row-stacked > span:last-child { text-align: left; width: 100%; }
.modal-services { display: flex; flex-wrap: wrap; gap: 8px; }
.modal-service-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--text);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 5px 10px 5px 8px;
}
.modal-service-chip svg { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-dim); }


.modal-desc {
  white-space: pre-wrap;
  font-size: 13.5px;
  color: var(--text-dim);
  line-height: 1.55;
  margin: 0;
}
.modal-desc a { color: var(--accent); word-break: break-word; }
.modal-desc-empty { font-style: italic; opacity: 0.65; }
.modal-desc-edit {
  width: 100%;
  min-height: 90px;
  resize: vertical;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.55;
  outline: none;
}
.modal-desc-edit:focus { border-color: var(--accent); }

.modal-links { display: flex; flex-wrap: wrap; gap: 10px 16px; }
.modal-link {
  font-size: 12.5px;
  color: var(--accent);
  text-decoration: none;
}
.modal-link:hover { text-decoration: underline; }

.modal-notes textarea {
  width: 100%;
  min-height: 80px;
  resize: vertical;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 13.5px;
  outline: none;
}
.modal-notes textarea:focus { border-color: var(--accent); }
.modal-notes-status {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 4px;
  min-height: 1em;
}

.modal-danger-row {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.modal-danger-actions { display: flex; align-items: center; gap: 16px; }
.modal-danger {
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: 12.5px;
  cursor: pointer;
  padding: 4px 0;
  display: flex;
  align-items: center;
  gap: 6px;
}
.modal-danger:hover { color: var(--heart); }
.modal-restore {
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: 12.5px;
  cursor: pointer;
  padding: 4px 0;
  display: flex;
  align-items: center;
  gap: 6px;
}
.modal-restore:hover { color: var(--accent); }

.detail-nav-prev { left: 16px; }
.detail-nav-next { right: 16px; }

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 30px;
  cursor: zoom-out;
}
.lightbox.hidden { display: none; }
.lightbox img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.5);
}
.lightbox video {
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.5);
  background: #000;
  cursor: default;
}
.lightbox-nav {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  border: none;
  background: rgba(0,0,0,0.4);
  color: #fff;
  font-size: 28px;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  cursor: pointer;
  z-index: 210;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox-prev { left: 16px; }
.lightbox-next { right: 16px; }
.lightbox-nav:hover { color: var(--accent); }

@media (max-width: 640px) {
  /* Sotto questa larghezza il campo di ricerca va da solo su una riga
     sotto, ma SENZA flex-wrap sulla riga del titolo: col wrap, flexbox
     manda a capo PRIMA di restringere, e su Recruitment le otto icone
     scendevano sotto il titolo (screenshot di Carlo, 07/09/2026). La
     griglia invece dice le posizioni per nome: titolo che si accorcia
     coi puntini, icone fisse a destra, ricerca su riga piena sotto.
     L'id sul selettore della ricerca batte il margin-top di -1px
     dell'allineamento ottico, piu' in giu' nel foglio. */
  /* #stickyTop su OGNI riga: la regola base .riga-titolo{display:flex}
     sta piu' in basso nel foglio e a parita' di peso vinceva, lasciando
     la riga in flex e le icone sparpagliate (Carlo, 07/09/2026). Con l'id
     questa griglia vince sempre. Icone allineate in alto come il titolo. */
  #stickyTop .riga-titolo { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
  #stickyTop .riga-titolo .brand-col { grid-column: 1; }
  #stickyTop .riga-titolo .topbar-icons { grid-column: 2; margin-top: 0; }
  #stickyTop .riga-titolo-spazio { display: none; }
  #stickyTop .riga-titolo .searchrow { grid-column: 1 / -1; margin: 8px 0 0; }
  .modal-hero { flex-direction: column; }
  .modal-hero-photo, .modal-hero-photo-empty { width: 100%; height: 200px; }
  /* these float at a fixed 50% viewport height regardless of scroll
     position, so on a narrow screen they end up sitting right on top of
     the photo thumbnail filmstrip — swiping (see modalCard's touchstart/
     touchend handlers) already covers next/prev record here, so just drop
     the redundant floating buttons instead of fighting their position */
  .detail-nav-prev, .detail-nav-next { display: none; }
  .modal-gallery-main { height: 220px; }
  /* on a narrow (smartphone) screen the zoom slider can pack 3+ tiny cards
     per row — Casting's Ruolo line gets too cramped at that size, so it
     drops out here (the city line right below it stays) */
  .grid-cards[data-tab="casting"] .card-sub-primary { display: none; }
  /* same 4-per-row floor as the desktop rule (see .grid-cards above), just
     one column tighter — a phone-width screen is too narrow for 4 tiny
     cards to stay legible, so the cap drops to 3 here */
  .grid-cards, .list-members-grid {
    grid-template-columns: repeat(auto-fill, minmax(max(var(--card-min, 150px), calc((100% - 2 * 12px) / 3)), 1fr));
  }
}

/* --- public application forms (apply-*.html) --------------------------- */

.apply-page {
  max-width: 900px;
  margin: 0 auto;
  padding: 0 20px 80px;
}

/* Page-load reveal (opt-in via .reveal-page on .apply-page): direct
   children of the page, the gate's login-card, and the form fade in and
   rise slightly, staggered top to bottom — same idea as apple.com's
   marketing pages. Pure CSS: an element's animation resets automatically
   whenever it goes from display:none (.hidden) to visible, so this
   replays correctly the first time a gated section (login card,
   applyBody) appears, with no JS bookkeeping needed. */
@keyframes revealUp {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: translateY(0); }
}
.apply-page.reveal-page > *,
.apply-page.reveal-page .login-card > *,
.apply-page.reveal-page #applyBody > *,
.apply-page.reveal-page .apply-form > * {
  opacity: 0;
  animation: revealUp .3s cubic-bezier(.22, 1, .36, 1) both;
}
.apply-page.reveal-page > *:nth-child(1),
.apply-page.reveal-page .login-card > *:nth-child(1),
.apply-page.reveal-page #applyBody > *:nth-child(1),
.apply-page.reveal-page .apply-form > *:nth-child(1) { animation-delay: 0ms; }
.apply-page.reveal-page > *:nth-child(2),
.apply-page.reveal-page .login-card > *:nth-child(2),
.apply-page.reveal-page #applyBody > *:nth-child(2),
.apply-page.reveal-page .apply-form > *:nth-child(2) { animation-delay: 30ms; }
.apply-page.reveal-page > *:nth-child(3),
.apply-page.reveal-page .login-card > *:nth-child(3),
.apply-page.reveal-page #applyBody > *:nth-child(3),
.apply-page.reveal-page .apply-form > *:nth-child(3) { animation-delay: 60ms; }
.apply-page.reveal-page > *:nth-child(4),
.apply-page.reveal-page .login-card > *:nth-child(4),
.apply-page.reveal-page #applyBody > *:nth-child(4),
.apply-page.reveal-page .apply-form > *:nth-child(4) { animation-delay: 90ms; }
.apply-page.reveal-page > *:nth-child(5),
.apply-page.reveal-page .login-card > *:nth-child(5),
.apply-page.reveal-page #applyBody > *:nth-child(5),
.apply-page.reveal-page .apply-form > *:nth-child(5) { animation-delay: 120ms; }
.apply-page.reveal-page > *:nth-child(6),
.apply-page.reveal-page .login-card > *:nth-child(6),
.apply-page.reveal-page #applyBody > *:nth-child(6),
.apply-page.reveal-page .apply-form > *:nth-child(6) { animation-delay: 150ms; }
.apply-page.reveal-page > *:nth-child(7),
.apply-page.reveal-page .login-card > *:nth-child(7),
.apply-page.reveal-page #applyBody > *:nth-child(7),
.apply-page.reveal-page .apply-form > *:nth-child(7) { animation-delay: 180ms; }
.apply-page.reveal-page > *:nth-child(8),
.apply-page.reveal-page .login-card > *:nth-child(8),
.apply-page.reveal-page #applyBody > *:nth-child(8),
.apply-page.reveal-page .apply-form > *:nth-child(8) { animation-delay: 210ms; }
.apply-page.reveal-page > *:nth-child(n+9),
.apply-page.reveal-page .login-card > *:nth-child(n+9),
.apply-page.reveal-page #applyBody > *:nth-child(n+9),
.apply-page.reveal-page .apply-form > *:nth-child(n+9) { animation-delay: 240ms; }
@media (prefers-reduced-motion: reduce) {
  .apply-page.reveal-page > *,
  .apply-page.reveal-page .login-card > *,
  .apply-page.reveal-page #applyBody > *,
  .apply-page.reveal-page .apply-form > * { animation: none; opacity: 1; }
}

/* Le regole .app-copyright stavano qui: erano la riga di copyright che
   chiudeva la pagina prima che ci fosse il footer vero. Nessun HTML le
   scriveva piu' — verificato il 19/08/2026 su tutte e cinque le pagine
   pubblicate, zero occorrenze. Tolte. */
/* Only the logo row is sticky — same split as ODG/Equipment's own header:
   .apply-topbar (logo + any header icons) pins to the top of the viewport
   exactly like ODG's .topbar, while the title/subtitle below live in plain
   document flow and scroll away normally, not stuck alongside the logo. */
.apply-header { margin-bottom: 32px; }
/* Finche' la pagina chiede il codice via mail, il logo in alto non si vede
   (Carlo, 09/09/2026): il riquadro «Verifica la tua email» ha gia' il suo, e
   quello piccolo nell'angolo lo doppiava. Torna quando il cancello sparisce.
   :has() e' supportato da Safari 15.4 e Chrome 105 in poi; nei browser piu'
   vecchi il logo semplicemente resta, come prima. */
.apply-page:has(#otpGate:not(.hidden)) .apply-topbar { display: none; }
.apply-topbar {
  position: sticky;
  top: 0;
  z-index: 501;
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--bg);
  /* same padding formula as ODG's/Equipment's own .topbar */
  padding: calc(16px + env(safe-area-inset-top)) 0 16px;
}
.apply-topbar-spacer { flex: 1; }
.apply-logo { width: 48px; height: 48px; border-radius: 11px; object-fit: cover; flex-shrink: 0; }
.apply-title { font-size: 22px; font-weight: 700; margin: 16px 0 0; }
.apply-sub { font-size: 14px; color: var(--text-dim); margin: 10px 0 0; max-width: 480px; }

/* Recruitment-only manual IT/EN toggle — a normal flex child of
   .apply-topbar now (pushed to the right by .apply-topbar-spacer, same
   pattern as ODG's/Equipment's own header icons), not position:absolute —
   that's what kept it vertically off from the logo's own centering before.
   Bare-glyph look, same recipe as .hdr-icon-btn (Modifica, Cerca, etc.) —
   no border/background box, just a colored label+globe icon that tints on
   hover, not a separate pill widget. */
/* Cerchietto EN/IT come sul sito (Carlo, 10/09/2026): stessa forma della
   voce di lingua nel menu, al posto del vecchio mappamondo. */
.apply-lang-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  border: 2px solid currentColor; border-radius: 50%; background: none;
  color: var(--text);
  font-family: inherit; font-size: 12px; font-weight: 600; letter-spacing: 0.06em; line-height: 1;
  cursor: pointer; opacity: 0.85; transition: opacity 0.2s, color 0.2s;
}
.apply-lang-toggle:hover { opacity: 1; color: var(--accent); }

.otp-verified-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 24px;
}

.apply-form { display: flex; flex-direction: column; gap: 28px; }
/* Notion-callout section heads, same look as ODG's "Data e location" —
   bold title with a short accent underline (only as wide as the text
   itself), no icon, no card background/border/divider */
.apply-card-head { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
.apply-card-head-title { font-size: 15px; font-weight: 700; color: var(--text); padding-bottom: 8px; border-bottom: 2px solid var(--accent); }
/* bare glyph, no box/border/background — same "Nike-style" icon convention
   used for header icon buttons elsewhere in the app family */
.apply-card-head-icon { display: flex; flex-shrink: 0; color: var(--text-dim); margin-bottom: 8px; }
.apply-card-head-icon svg { width: 16px; height: 16px; }
.apply-row { display: flex; flex-direction: column; gap: 6px; }
.apply-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.apply-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
.apply-row-4 { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 14px; }
.apply-label { font-size: 13px; font-weight: 600; color: var(--text); }
.req { color: var(--heart); }
.apply-hint { font-size: 12px; color: var(--text-dim); margin: -2px 0 0; }
.apply-map { height: 480px; border-radius: 10px; overflow: hidden; border: 1px solid var(--border); }
.apply-form input[type="text"],
.apply-form input[type="email"],
.apply-form input[type="tel"],
.apply-form input[type="date"],
.apply-form input[type="number"],
.apply-form select,
.apply-form textarea {
  width: 100%;
  height: 42px;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
  outline: none;
  box-sizing: border-box;
}
/* iOS Safari renders type="date" with its own intrinsic control height that
   ignores the box's height/padding, making it taller than the other fields
   — appearance:none strips that native chrome so the box model above wins,
   same fix as the <select> chevron below */
.apply-form input[type="date"] {
  -webkit-appearance: none;
  appearance: none;
}
/* native <select> rendering doesn't reliably honor the same height/padding
   as a text input across browsers — appearance:none + an explicit height
   plus a drawn-on chevron makes it match pixel-for-pixel instead of
   depending on the OS/browser's own control metrics */
.apply-form select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239a9aa0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 16px;
  padding-right: 34px;
}
.apply-form input:focus, .apply-form select:focus, .apply-form textarea:focus { border-color: var(--accent); }
/* height is auto-grown by JS (autoResizeTextarea, same technique as ODG's
   Note field) as the user types — no manual resize handle needed */
.apply-form textarea { height: auto; min-height: 42px; padding-top: 11px; resize: none; overflow: hidden; }
.apply-phone-row { display: flex; gap: 8px; }
.apply-phone-row select { width: 120px; flex-shrink: 0; }
.apply-phone-row input { flex: 1; min-width: 0; }

/* social profile fields — a fixed, non-editable domain prefix + just the
   handle, instead of asking for a full URL: friendlier to type/paste on a
   phone, and guarantees the value we build and store is always a real,
   clickable link regardless of what the person actually types */
.apply-form .apply-url-row {
  display: flex;
  align-items: center;
  width: 100%;
  height: 42px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  overflow: hidden;
}
.apply-form .apply-url-row:focus-within { border-color: var(--accent); }
.apply-url-prefix { padding: 0 0 0 12px; color: var(--text-dim); font-size: 14px; white-space: nowrap; user-select: none; }
.apply-form .apply-url-row input[type="text"] {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: none;
  background: transparent;
  padding: 0 12px 0 2px;
}

/* Menu dei suggerimenti di Google (.pac-container): viene appeso al <body>
   con i colori chiari suoi, e va ridipinto per non sembrare un corpo
   estraneo nel tema scuro dell'app. Gli !important servono perche' Google
   scrive gli stili in linea.
   Per un periodo qui c'era un menu scritto da noi, quando i suggerimenti
   arrivavano da OpenStreetMap; e' tornato quello di Google insieme ai suoi
   dati, che in Italia sono gli unici ad avere i numeri civici. */
.pac-container {
  background: var(--surface-2) !important;
  border: 1px solid var(--border) !important;
  border-radius: 10px !important;
  margin-top: 4px;
  box-shadow: var(--shadow) !important;
  font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
}
.pac-container:after { display: none !important; } /* la barra col logo di Google */
.pac-item { border-color: var(--border) !important; padding: 8px 12px !important; font-size: 13.5px !important; color: var(--text-dim) !important; cursor: pointer; }
.pac-item:hover, .pac-item-selected { background: var(--surface) !important; }
.pac-item-query { color: var(--text) !important; font-size: 13.5px !important; }
.pac-matched { color: var(--accent) !important; font-weight: 600; }
.pac-icon { display: none !important; } /* lo spillo di Google: piu' pulito senza */

/* Riquadro che occupa il posto della mappa mentre lo script arriva, e in
   caso di errore. Stessa altezza della mappa, cosi' il modulo non sobbalza
   quando compare. */
.map-stato {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  text-align: center;
  background: var(--surface);
}
.map-stato__testo { margin: 0; max-width: 40ch; font-size: 13px; line-height: 1.45; color: var(--text-dim); }
.apply-radio {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
}
.apply-radio input { accent-color: var(--accent); width: 16px; height: 16px; margin-top: 2px; flex-shrink: 0; }
.apply-radio:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }

/* apply-location.html's "Che tipo di location è?" gate — full-width stacked
   rows rather than two side-by-side tiles, matching the row lists in ODG
   (.odg-row) and Equipment: icon on the left, bold title with a dim
   description under it, each row its own bordered card. */
.apply-typechoice-list { display: flex; flex-direction: column; gap: 10px; width: 100%; margin-top: 6px; }
.apply-typechoice {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .12s;
}
.apply-typechoice:hover { border-color: var(--accent); }
.apply-typechoice > svg { flex-shrink: 0; color: var(--text-dim); }
.apply-typechoice-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.apply-typechoice-title { font-size: 15px; font-weight: 700; }
.apply-typechoice-sub { font-size: 13px; color: var(--text-dim); line-height: 1.4; }
/* the type gate needs more room than the OTP gate's single email field */
.login-card-wide { max-width: 420px; }
/* vertical toggle list (Competenze) — same look as the Equipment App's
   equipment list: one continuous bordered block, thin dividers between
   rows, no visible checkbox, tap anywhere on the row to toggle it */
.apply-select-list {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.apply-select-row {
  display: block;
  padding: 13px 16px;
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  transition: background-color .12s;
}
.apply-select-row:last-child { border-bottom: none; }
/* opacity:0 (not display:none) keeps the checkbox "rendered" so clicking
   the label still forwards the click to it natively — display:none breaks
   that forwarding in some browsers */
.apply-select-row input:not([type="text"]) { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.apply-select-row:has(input:checked) { background: var(--accent-soft); }
@media (hover: hover) and (pointer: fine) {
  .apply-select-row:hover { background: var(--surface-2); }
  .apply-select-row:has(input:checked):hover { background: var(--accent-soft); filter: brightness(0.96); }
}
/* Servizi (Location) amenity icon, Airbnb-style — bare glyph, no
   box/border/background, same "Nike-style" convention as the card-head icon */
.apply-select-row-content { display: flex; align-items: center; gap: 10px; }
.apply-select-row-icon { display: flex; flex-shrink: 0; color: var(--text-dim); }
.apply-select-row-icon svg { width: 18px; height: 18px; }
.apply-select-row:has(input:checked) .apply-select-row-icon { color: var(--accent); }
/* Fallback for browsers without :has() (Safari <15.4, Firefox <121) — the
   real checkbox is opacity:0, so without this a selected row would look
   identical to an unselected one and the form becomes unusable. The sibling
   combinator has universal support, so tint the label itself as a backstop;
   where :has() works the rules above simply add the row background on top. */
.apply-select-row input:checked + .apply-select-row-content { color: var(--accent); font-weight: 600; }
.apply-select-row input:checked + .apply-select-row-content .apply-select-row-icon { color: var(--accent); }
/* Recruitment "Competenze" — Altro row: typing goes right in place of the
   label text (see setupSkillOtherInline in apply-recruitment.html), so the
   input has to look like plain row text, not a form field, both empty
   (placeholder matching the other rows' label color/weight, not a greyed-out
   placeholder default) and while checked/typed (inherits the accent color +
   bold the sibling rule above already applies to .apply-select-row-content) */
/* base rule — covers the backend edit modal (.modal-edit-multiselect), which
   has no competing input[type=text] rule so this alone is enough there. A
   dashed underline is the "this is editable, not just a label" affordance,
   solid+accent on focus — without it the row looks identical to a plain
   read-only option since there's no visible input chrome otherwise. */
/* font-weight fixed at 400 (not "inherit") — the checked-state rule above
   bolds .apply-select-row-content when its checkbox is checked, and typing
   here checks it, so without this override the text would go bold mid-type */
.apply-select-row-input { height: auto; border: none; border-bottom: 1px dashed var(--border); border-radius: 0; outline: none; background: transparent; font: inherit; font-weight: 400; color: inherit; padding: 0 0 2px; width: 100%; min-width: 0; }
.apply-select-row-input:focus { border-bottom-style: solid; border-bottom-color: var(--accent); }
.apply-select-row-input::placeholder { color: var(--text); opacity: 1; }
/* .apply-form input[type="text"] (above) sets height/padding/border/font-size
   for every text input on the page — same specificity, so this needs the
   extra ".apply-form" + type qualifier just to win the cascade tie via
   source order, keeping the row the same height as its plain-text siblings */
.apply-form input.apply-select-row-input {
  /* .apply-form input[type="text"] (above) sets a 10px border-radius on
     every text input — with only a border-bottom visible here, that radius
     curls its ends up into a rounded pill/bracket shape instead of a clean
     straight line, so it needs an explicit reset back to 0 */
  height: auto; border: none; border-bottom: 1px dashed var(--border); border-radius: 0; outline: none; background: transparent; font-family: inherit; font-size: 13.5px; font-weight: inherit; line-height: normal; color: inherit; padding: 0 0 2px; width: 100%; min-width: 0;
}
.apply-form input.apply-select-row-input:focus { border-bottom-style: solid; border-bottom-color: var(--accent); }
/* checkmark at the end of an "Altro"-style inline text row — backend
   (Competenze) uses it as an explicit confirm/save button, the public form
   as a "done" affordance that just blurs the field; same look either way */
.apply-select-row-confirm { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 22px; height: 22px; padding: 0; border: none; background: transparent; color: var(--text-dim); cursor: pointer; border-radius: 6px; }
.apply-select-row-confirm:hover { color: var(--accent); background: var(--surface-2); }
/* Servizi (Location) — same rows, laid out 2-up to fit a long amenities
   list without the page turning into one endless scroll */
.apply-select-list-2col { display: grid; grid-template-columns: 1fr 1fr; }
.apply-select-list-2col .apply-select-row:nth-child(odd) { border-right: 1px solid var(--border); }
@media (max-width: 480px) {
  .apply-select-list-2col { grid-template-columns: 1fr; }
  .apply-select-list-2col .apply-select-row:nth-child(odd) { border-right: none; }
}
/* "+" tile photo picker (Casting/Location) — same look as the internal
   app's own photo grid (.modal-photo-add) and ODG's storyboard tile */
.apply-photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: 8px;
}
.apply-photo-item { position: relative; }
.apply-photo-item img {
  width: 100%;
  height: 90px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  display: block;
}
.apply-photo-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.apply-photo-remove:hover { background: var(--heart); }
.apply-photo-add {
  width: 100%;
  height: 90px;
  border-radius: 8px;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.apply-photo-add:hover { border-color: var(--accent); color: var(--accent); }
/* CV/portfolio picker (Recruitment) — same "+" tile as photos, but once a
   file is chosen it becomes a row (no thumbnail possible for a PDF) */
.apply-file-chosen {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 90px;
  padding: 0 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
}
.apply-file-chosen-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 13px;
}
.apply-file-remove {
  border: none;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding: 4px;
}
.apply-file-remove:hover { color: var(--heart); }
.apply-privacy { display: flex; align-items: flex-start; gap: 10px; font-size: 13px; color: var(--text-dim); }
.apply-privacy input { accent-color: var(--accent); width: 16px; height: 16px; margin-top: 2px; flex-shrink: 0; }
.apply-privacy a { color: var(--accent); }
.apply-submit-error { color: var(--amber); font-size: 13px; text-align: center; min-height: 1em; margin: 0; }
.apply-success { text-align: center; padding: 60px 20px; display: flex; flex-direction: column; align-items: center; gap: 14px; }
.apply-success-icon { color: var(--accent); }
.apply-success h2 { margin: 0; font-size: 20px; }
.apply-success p { margin: 0; color: var(--text-dim); font-size: 14px; max-width: 380px; }

.apply-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translate(-50%, 12px);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 12px 18px;
  border-radius: 10px;
  font-size: 13.5px;
  box-shadow: var(--shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s, transform .15s;
  z-index: 300;
  max-width: calc(100% - 40px);
  text-align: center;
}
.apply-toast.visible { opacity: 1; transform: translate(-50%, 0); }
.apply-toast.apply-toast-error { border-color: var(--heart); color: var(--heart); }

@media (max-width: 560px) {
  .apply-row-2, .apply-row-3 { grid-template-columns: 1fr; }
  .apply-row-4 { grid-template-columns: 1fr 1fr; }
  /* iOS Safari auto-zooms the page on focus when an input's font-size is
     under 16px — bumping it to 16px on mobile stops the zoom-and-horizontal-
     scroll jump without changing the desktop size */
  .apply-form input[type="text"],
  .apply-form input[type="email"],
  .apply-form input[type="tel"],
  .apply-form input[type="date"],
  .apply-form input[type="number"],
  .apply-form select,
  .apply-form textarea,
  .apply-url-prefix {
    font-size: 16px;
  }
}


/* ===========================================================================
   Vista a tabella — la scheda Yoga
   ---------------------------------------------------------------------------
   Non e' una tabella nuova: e' quella di Billing, portata qui. Stesse classi
   (.tabella-wrap + table.dati), stesse misure, stessa intestazione che resta
   attaccata in alto mentre si scorre. Due app della stessa casa che mostrano
   un elenco a righe devono mostrarlo allo stesso modo.
   Le altre tre schede restano a schede/elenco: li' ogni voce ha una foto e un
   volto, qui sono 467 iscritti e la domanda e' "chi c'era", non "chi e'".
=========================================================================== */
.tabella-wrap {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}
/* NIENTE `overflow` ne' `max-height` sugli schermi larghi, e non e' una
   dimenticanza. Con il riquadro che scorreva per conto suo l'elenco stava
   dentro una finestrella alta quanto lo schermo; Carlo lo voleva come pagina
   lunga. Togliendo l'overflow il riquadro non e' piu' un contenitore di
   scorrimento, quindi **scorre la pagina** - e l'intestazione, che e'
   `position: sticky`, si attacca al bordo della FINESTRA invece che al bordo
   del riquadro: si scorrono 153 righe e i nomi delle colonne restano.
   Sotto una certa larghezza l'overflow orizzontale torna, perche' li' dieci
   colonne non ci stanno e senza si taglierebbero.

   LA SOGLIA ERA 1100px ED ERA TROPPO BASSA. Le dieci colonne, tutte a
   `white-space: nowrap`, ne chiedono circa 1330: fra 1100 e 1330 la tabella
   non aveva dove scorrere e usciva semplicemente dal riquadro, con l'ultima
   colonna tagliata a meta'. Non si vedeva su tutti gli schermi - a 1440px
   avanzava UN pixel - e bastava un browser che disegna il testo un filo piu'
   largo per perderlo: Carlo l'ha visto in Safari il 25/08/2026 su una
   finestra dove qui dentro andava bene. Un margine di un pixel non e' un
   margine. */
@media (max-width: 1330px) {
  .tabella-wrap { overflow-x: auto; }
}
table.dati { width: calc(100% - 1px); border-collapse: collapse; font-size: 14px; }
table.dati th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-2); color: var(--text-dim);
  font-size: 13px; font-weight: 700;
  text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.dati td {
  padding: 9px 12px; border-bottom: 1px solid var(--border);
  vertical-align: middle; white-space: nowrap;
}
table.dati tbody tr:last-child td { border-bottom: none; }
table.dati tbody tr { cursor: pointer; }
table.dati tbody tr:hover td { background: var(--surface-2); }
table.dati td.num, table.dati th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.dati td.vuoto { color: var(--text-dim); }
/* L'indirizzo e' la colonna piu' larga e la piu' variabile: da
   `ba@watermelon.it` a `maddalena.nocivelli@s4win.com` ballano 150px, e sono
   quelli che decidevano se la tabella ci stava o no. Cappata, il resto delle
   colonne ha misure stabili e la larghezza totale smette di dipendere da chi
   e' iscritto. Chi ha bisogno dell'indirizzo intero apre la scheda, dove non
   e' troncato - e comunque il taglio si vede, mentre una colonna che esce dal
   riquadro sembra un guasto. */
table.dati td[data-label="Email"] {
  max-width: 220px; overflow: hidden; text-overflow: ellipsis;
}
table.dati th.ordinabile { cursor: pointer; user-select: none; }
table.dati th.ordinabile:hover { color: var(--text); }
table.dati th.ordinata { color: var(--accent); }

/* La prima colonna resta ferma mentre si scorre di lato: con diciassette
   colonne si perde subito di vista di chi si sta leggendo la riga. */
table.dati th:first-child, table.dati td:first-child {
  position: sticky; left: 0; z-index: 2; background: var(--surface);
}
table.dati th:first-child { z-index: 3; background: var(--surface-2); }
table.dati tbody tr:hover td:first-child { background: var(--surface-2); }

/* Un pallino per edizione: pieno se la persona c'era, vuoto se no. Idea di
   Carlo il 24/08/2026 — "come le stelline di Lightroom". Si legge di colpo
   chi torna, senza confrontare elenchi di anni riga per riga. */
.pallini { display: inline-flex; gap: 4px; }
.pallino {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
  border: 1px solid var(--border); color: var(--text-dim);
  background: transparent;
}
.pallino.pieno { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* ---------- il riepilogo sopra la tabella Yoga ---------- */
.riepilogo { margin-bottom: 22px; }
/* Il titolo "Riepilogo di tutte le edizioni" e i suoi due bottoni non esistono
   piu': il comando e' passato nella riga dei risultati, accanto al tasto
   Mappa, e l'esportazione nella barra in alto. Le regole che li vestivano
   sono state tolte con loro - fra queste `.grafici-toggle`, che aveva un
   `min-width` per non far ballare il bottone quando la scritta cambiava da
   "Mostra" a "Nascondi": ora l'etichetta e' fissa e il problema non esiste. */
/* FLEX E NON GRID, ed e' il motivo per cui l'ultima riga non resta monca.
   Con `grid-template-columns: repeat(auto-fit, minmax(168px, 1fr))` le colonne
   sono le stesse su tutte le righe: stringendo la finestra i sei riquadri
   diventavano 4 + 2, e quei 2 restavano larghi un quarto ciascuno con meta'
   riga vuota alla loro destra. Il numero di colonne e' una proprieta' della
   griglia, non della singola riga, quindi la griglia non puo' fare altro.
   Con flex la riga e' l'unita': `flex-grow: 1` fa allargare le voci di OGNI
   riga fino a riempirla, ultima compresa. Le larghezze non sono piu' uguali
   fra una riga e l'altra - ed e' giusto cosi', il vuoto si vedeva, la
   differenza di larghezza no. */
.griglia-numeri { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.numero { flex: 1 1 168px; }

/* `flex-grow` da solo riempie la riga ma non decide DOVE spezzare: flex e'
   goloso, mette su una riga tutti quelli che ci stanno e manda a capo il
   resto. Con sei riquadri e una finestra che ne tiene cinque veniva 5 + 1, e
   quell'uno si allargava per tutta la riga: pieno, ma un riquadro largo un
   metro con dentro un numero solo.
   Queste soglie spezzano in parti uguali - 3 + 3, poi 2 + 2 + 2, poi uno per
   riga. Sono tarate sui SEI riquadri di oggi (a 1150px smettono di starci in
   fila) e sulla loro larghezza minima di 168px. Se un domani i riquadri
   diventassero cinque o sette, non si rompe niente: si torna al caso pieno-ma-
   sbilanciato di prima, che era comunque meglio del vuoto a destra. */
@media (max-width: 1150px) { .numero { flex-basis: calc(33.333% - 6px); } }
@media (max-width: 780px)  { .numero { flex-basis: calc(50% - 4px); } }
@media (max-width: 480px)  { .numero { flex-basis: 100%; } }
.numero { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 13px 14px; }
/* `min-width: 0` su tutti e due: senza, una voce lunga dentro il riquadro
   impedisce al riquadro di stringersi sotto la sua larghezza naturale, e la
   riga sborda invece di andare a capo. E' la regola meno intuitiva di flex. */
.numero, .grafico { min-width: 0; }
.numero .etichetta { font-size: 13px; font-weight: 700; color: var(--text-dim); margin-bottom: 6px; }
.numero .valore { font-size: 22px; font-weight: 700; letter-spacing: -.02em; }
.numero .nota { font-size: 13px; color: var(--text-dim); margin-top: 4px; }
.numero.forte { border-color: var(--accent); }
.numero.forte .valore { color: var(--accent); }

/* Stessa ragione dei riquadri qui sopra: con quattro grafici e una finestra
   che ne tiene tre, il quarto restava largo un terzo con due terzi di riga
   vuoti accanto. Ora si prende tutta la riga. */
.grafici { display: flex; flex-wrap: wrap; gap: 8px; }
.grafico { flex: 1 1 280px; }
/* Stessa cosa per i quattro grafici: sotto i 1260px non ci stanno in fila e
   senza queste soglie verrebbe 3 + 1, con l'ultimo grafico largo quanto la
   pagina. Cosi' invece 2 + 2. */
/* I grafici sono da tre a cinque, secondo quello che c'e' da mostrare: il
   grafico degli orari e quello dell'attesa compaiono solo se esistono orari
   veri. Con cinque e una finestra che ne tiene quattro tornava il 4 + 1, con
   l'ultimo largo quanto la pagina. Sotto i 1540px si passa a tre per riga
   (3 + 2), sotto i 1260 a due, sotto i 700 uno. */
/* QUANTI PER RIGA LO DECIDE IL NUMERO DI GRAFICI, non la larghezza.
   Prima era una soglia in pixel, e andava indovinata: i grafici sono da tre a
   cinque secondo quello che c'e' da mostrare, quindi la larghezza in cui "ci
   stanno tutti" cambia con loro. A ogni tentativo restava una finestra in cui
   veniva 4 + 1, con l'ultimo grafico largo quanto la pagina.
   `data-n` porta il conto nel markup e le righe si dividono in parti uguali:
   quattro fanno 2 + 2, cinque fanno 3 + 2, tre stanno in fila. Le soglie qui
   sotto restano per gli schermi stretti, dove comanda lo spazio e non il
   numero - e vincono perche' vengono dopo, a parita' di specificita'. */
.grafici[data-n="4"] .grafico { flex-basis: calc(50% - 4px); }
.grafici[data-n="5"] .grafico { flex-basis: calc(33.333% - 6px); }
@media (max-width: 1260px) { .grafici[data-n] .grafico { flex-basis: calc(50% - 4px); } }
@media (max-width: 700px)  { .grafici[data-n] .grafico { flex-basis: 100%; } }
.grafico {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px 16px;
}
.grafico h4 { margin: 0 0 14px; font-size: 13px; font-weight: 700; color: var(--text-dim); }
.grafico-nota { margin: 12px 0 0; font-size: 12px; color: var(--text-dim); line-height: 1.45; }

/* istogramma: dove le categorie hanno un ordine (anni, fasce d'eta') */
.istogramma { display: flex; align-items: flex-end; gap: 10px; }
.istogramma .colonna { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; text-align: center; }
.istogramma .numero-sopra { font-size: 13px; font-weight: 700; margin-bottom: 4px; }
.istogramma .barra { background: var(--accent); border-radius: 4px 4px 0 0; min-height: 2px; flex: none; }
.istogramma .pila { display: flex; flex-direction: column-reverse; border-radius: 4px 4px 0 0; overflow: hidden; min-height: 2px; flex: none; }
.istogramma .parte { width: 100%; }
/* Il cartellino che segue il mouse sui grafici. `pointer-events: none` e'
   essenziale: senza, il cartellino finisce sotto il puntatore, il `mouseout`
   scatta sulla barra e il cartellino sparisce - e riappare, e sparisce. */
.tip-grafico {
  position: fixed; z-index: 9999; pointer-events: none;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 5px 9px; font-size: 12px; font-weight: 600;
  white-space: nowrap; box-shadow: 0 4px 14px rgba(0,0,0,.35);
}
.tip-grafico.hidden { display: none; }
/* La parte sotto il puntatore si schiarisce: dice quale delle fasce impilate
   sta descrivendo il cartellino, che su una colonna con cinque fasce non e'
   ovvio. */
.istogramma .parte:hover { filter: brightness(1.35); }
.istogramma .sotto { font-size: 12px; color: var(--text-dim); margin-top: 6px; line-height: 1.3; }
.istogramma .perc { font-size: 11px; }
/* Ventiquattro colonne invece di tre o cinque: piu' strette, senza numero
   sopra, e sotto solo un'etichetta ogni sei ore. */
.istogramma-ore { gap: 2px; }
.istogramma-ore .colonna { min-width: 0; }
.istogramma-ore .barra { border-radius: 2px 2px 0 0; }
/* L'ora sotto la colonna si scrive solo ogni sei (0, 6, 12, 18), ma la
   fascia dell'etichetta deve esserci lo stesso su TUTTE. Le colonne sono
   allineate in basso (`align-items: flex-end`): una colonna senza etichetta e'
   alta solo quanto la sua barra, quindi la barra le arriva fino in fondo,
   mentre in quelle etichettate resta sollevata dell'altezza della scritta.
   Il risultato era un istogramma con la base a zig-zag. Con un'altezza minima
   la fascia c'e' sempre, anche vuota, e le basi tornano su una riga sola. */
/* Tutte e ventiquattro le ore, non una ogni sei: piccole e centrate ci
   stanno. `-1px` di lettere e nessuna interruzione di riga, se no "10" va a
   capo dentro una colonna larga otto pixel. */
.istogramma-ore .sotto {
  font-size: 10px; min-height: 14px; letter-spacing: -.5px; white-space: nowrap;
}
/* Le ore pari un filo piu' chiare. Con ventiquattro colonne attaccate e
   ventiquattro numeri sotto, senza un'alternanza si perde la corrispondenza
   fra il numero e la sua barra: e' l'unico scopo di questa differenza, non
   e' una categoria. */
.istogramma-ore .colonna:nth-child(even) .barra { opacity: .62; }

/* Il conteggio sopra la barra, che compare passandoci sopra. Il `title` del
   browser fa la stessa cosa ma dopo un secondo abbondante, e a quel punto si
   e' gia' spostato il mouse. `visibility` e non `display`: lo spazio resta
   occupato sempre, ed e' anche quello che tiene le basi degli istogrammi
   allineate fra un grafico e l'altro. */
.istogramma-ore .numero-sopra {
  visibility: hidden; font-size: 11px; letter-spacing: -.5px; white-space: nowrap;
}
.istogramma-ore .colonna:hover .numero-sopra { visibility: visible; color: var(--accent); }
.istogramma-ore .colonna:hover .barra { opacity: 1; background: var(--accent); }

/* torta: dove sono parti di un tutto e le fette sono poche */
.torta-riga { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.torta { width: 108px; height: 108px; border-radius: 50%; flex: none; }
.legenda { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.legenda li { display: flex; align-items: center; gap: 7px; margin: 5px 0; min-width: 0; }
.legenda .pastiglia { width: 11px; height: 11px; border-radius: 3px; flex: none; }
.legenda .perc { color: var(--text-dim); }
/* Le voci vanno a capo invece di stringersi: con quattro voci, di cui una
   lunga come «Remoto o solo donazione», la riga sola le comprimeva fino a
   spingere il testo fuori dal riquadro. Ogni voce resta su una riga sua e
   sono le VOCI ad andare a capo, non le parole dentro. */
/* La legenda in fila sotto il grafico. Quando le voci vanno a capo - cinque
   fasce non ci stanno su una riga - lo stacco verticale era di 18px, e non
   perche' qualcuno l'avesse deciso: 8px di `gap` piu' i 5px di margine sopra
   e sotto che ogni voce eredita da `.legenda li`, pensati per la legenda
   incolonnata. Qui il margine si azzera e restano 6px. */
.legenda-riga { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 12px; }
.legenda-riga li { white-space: nowrap; margin: 0; }

/* ===========================================================================
   La tabella sul telefono: due righe per persona, non una scheda
   ---------------------------------------------------------------------------
   Il primo tentativo faceva una scheda con tutti e dieci i campi etichettati.
   Carlo: «le schede sono troppo ingombranti» - e aveva ragione, per scorrere
   153 persone servivano dieci schermate. Qui si mostra solo quello che serve a
   RICONOSCERE una persona in un elenco: nome, come partecipa, anno. Tutto il
   resto e' a un dito di distanza, nella finestra che si apre toccando la riga.
   Non e' nascondere dati: e' scegliere cosa mettere nell'indice e cosa nella
   pagina. Su schermo largo le colonne restano tutte e dieci.
=========================================================================== */
@media (max-width: 760px) {
  .tabella-wrap { border: none; background: transparent; overflow-x: visible; }
  table.dati thead { display: none; }
  table.dati, table.dati tbody { display: block; width: auto; }

  /* Tutto su UNA riga: nome a sinistra, come partecipa e anno a destra.
     Quattro colonne dichiarate, e la seconda (il nome) e' l'unica elastica -
     e' lei che spinge le altre due contro il bordo destro. Con flex la
     posizione dipendeva da quanto era lungo il nome. */
  table.dati tbody tr {
    display: grid; grid-template-columns: auto 1fr auto auto;
    align-items: baseline;
    padding: 10px 2px; border-bottom: 1px solid var(--border);
    column-gap: 8px;
  }
  table.dati td {
    display: block; padding: 0; border: none; white-space: normal;
    position: static;
  }
  table.dati td::before { content: none; }   /* niente etichette: le dice il posto */

  /* `grid-row: 1` su tutte e quattro, e non e' ridondante: nel DOM «come
     partecipa» viene DOPO l'anno, e la disposizione automatica non torna
     indietro a riempire una colonna gia' superata - la mandava a capo, e la
     riga veniva alta 58px invece di 40. */
  /* SI SCEGLIE PER NOME DI COLONNA, NON PIU' PER POSIZIONE (06/09/2026).
     La versione per posizione e' saltata due volte: il 25/08 sparendo
     "Quante", e oggi con la colonna "#" aggiunta in testa - tutto e'
     scalato di uno e la vista stretta mostrava il numero e la tipologia
     al posto del nome e della partecipazione (screenshot di Carlo).
     Ogni cella porta il nome della sua colonna in `data-label` (lo
     scrive renderResults apposta per questa vista): agganciarsi a quello
     regge qualunque riordino, e una colonna nuova nasce nascosta invece
     di spostare le altre. Il "#" qui non si mostra: e' Carlo che l'ha
     chiesto, in stretto la riga e' gia' piena. */
  table.dati td { display: none; }
  table.dati td[data-label="Cognome"] { display: block; grid-row: 1; grid-column: 1; font-size: 15px; font-weight: 700; }
  table.dati td[data-label="Nome"] { display: block; grid-row: 1; grid-column: 2; font-size: 15px; font-weight: 700; }
  table.dati td[data-label="Come partecipa"] { display: block; grid-row: 1; grid-column: 3; color: var(--text-dim); font-size: 13px; text-align: right; }
  table.dati td[data-label="Edizione"] { display: block; grid-row: 1; grid-column: 4; color: var(--text-dim); font-size: 13px; text-align: right; }

  /* una cella vuota non deve lasciare il suo trattino in mezzo alla riga */
  table.dati td[data-label="Come partecipa"].vuoto { display: none; }

  /* La prima colonna qui non deve restare ferma: quella regola serve in vista
     larga, dove si scorre di lato fra diciassette colonne, e per farlo si
     porta dietro uno sfondo OPACO. Su schermo stretto non si scorre di lato
     - `overflow-x: visible` - quindi quello sfondo non tiene ferma nessuna
     colonna: dipinge soltanto un rettangolo sopra la riga, e si vedeva
     perche' copriva l'evidenziazione proprio sul nome. */
  table.dati td:first-child { position: static; background: transparent; }

  /* L'evidenziazione va sulla RIGA, non sulle celle. In vista larga le celle
     sono attaccate e il risultato e' una fascia unica; qui la riga e' una
     griglia con 8px di spazio fra le colonne, e lo stesso stile dipingeva
     quattro rettangoli staccati con dei buchi in mezzo. */
  table.dati tbody tr:hover { background: var(--surface-2); }
  table.dati tbody tr:hover td,
  table.dati tbody tr:hover td:first-child { background: transparent; }

  /* Il dito non ha il passaggio del mouse: senza questo, su iPhone la riga
     si accende solo DOPO il tocco e resta accesa finche' non se ne tocca
     un'altra. Cosi' invece risponde mentre si preme, come un bottone. */
  table.dati tbody tr:active { background: var(--surface-2); }
}


/* --- il titolo che cambia sezione ----------------------------------------
   Sostituisce la barra a parte che avevo messo il 26/08/2026: due file di
   schede una sopra l'altra non dicevano quale comandasse. Cambiare sezione e'
   un livello sopra al cambiare vista, e sta nel titolo. */
.brand-switch {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.brand-switch-caret { opacity: .45; transition: transform .15s, opacity .15s; }
.brand-switch:hover .brand-switch-caret { opacity: .9; }
.brand-switch[aria-expanded="true"] .brand-switch-caret { transform: rotate(180deg); opacity: .9; }
.brand-col { position: relative; }
.brand-menu {
  position: absolute; z-index: 60; top: 100%; left: 0; margin-top: 4px;
  min-width: 190px; padding: 5px;
  background: var(--surface-2, #1a1a1d); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 12px 34px rgba(0,0,0,.38);
  display: flex; flex-direction: column;
}
.brand-menu.hidden { display: none; }
.brand-menu a {
  padding: 9px 11px; border-radius: 7px; text-decoration: none;
  color: var(--text); font-size: 15px; font-weight: 500;
}
.brand-menu a:hover { background: var(--surface-3, rgba(255,255,255,.06)); }
.brand-menu a.qui { color: var(--accent); }

/* Equipment e ODG nella fila delle schede sono collegamenti, non pulsanti:
   stesso aspetto, ma <a> non eredita il font del bottone. */
a.tab { text-decoration: none; display: inline-flex; align-items: center; }

/* Il titolo sotto il menu: dice in che sezione sei. Stesso peso del nome
   della lista in Equipment e del giorno in ODG - sono la stessa cosa, cioe'
   il nome di quello che stai guardando. */
#sezioneTitolo { display: inline-block; }
.brand-col { padding: 14px 0 6px; }

/* --- la riga del titolo e dei comandi ------------------------------------
   Titolo a sinistra, comandi a destra, sotto la barra di navigazione. Ricerca,
   filtri, preferiti, aggiungi: valgono per la sezione aperta, non per
   l'applicazione, e in alto a destra sembravano globali (Carlo, 26/08/2026).
   Su schermo stretto i comandi restano sulla riga del titolo: sono icone, ci
   stanno; e' il titolo che si accorcia. */
.riga-titolo {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 0 8px;
}
.riga-titolo .brand-col { padding: 0; min-width: 0; }
.riga-titolo .brand-title-list { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.riga-titolo-spazio { flex: 1; }

/* I comandi si allineano alla PRIMA RIGA del titolo, non al centro del blocco.
   In ODG sotto il titolo ci sono cliente e "aggiornato": centrandoli, le icone
   scendevano a meta' di tre righe e sembravano appese al nulla (Carlo,
   26/08/2026). Il titolo e' alto 29px e un pulsante 31: un pixel di scarto
   li mette sulla stessa linea ottica. */
.riga-titolo { align-items: flex-start; }
.riga-titolo .searchrow,
.riga-titolo .topbar-icons { margin-top: -1px; }

/* ============================================================
   MENU DELLE SEZIONI NELLA RIGA DEL LOGO
   Equipment, ODG, Casting, Location, Recruitment, Yoga stanno in alto a
   destra, sulla stessa riga del logo, e sotto una certa larghezza si
   chiudono nel burger — come su watermelon.it (Carlo, 26/08/2026).
   E' sempre la STESSA <nav>: sopra la soglia e' una riga, sotto e' un
   pannello in colonna. Niente elenco duplicato da tenere allineato a mano.
   La riga che chiudeva il menu ora chiude la topbar: sta sotto al bordo
   dell'intestazione appiccicata, ed e' quella che separa dal contenuto.
   ============================================================ */
.topbar {
  /* qui, e SOLO qui, la topbar non e' sticky: a incollarsi in alto e' il suo
     contenitore .sticky-top. Senza questo il pannello del burger si
     ancorerebbe a un antenato piu' lontano e cadrebbe fuori squadra. */
  position: relative;
  border-bottom: 1px solid var(--border);
}

.topbar .tabs {
  margin-left: auto;    /* e' questo che lo manda a destra */
  margin-bottom: 0;
  border-bottom: none;
  position: static;     /* dentro la topbar non deve appiccicarsi per conto suo */
  overflow: visible;    /* servirebbe a nascondere il pannello del burger */
  padding-top: 0;
  align-items: center;
}
.topbar .tab { padding-bottom: 6px; }

.nav-burger {
  display: none;        /* compare solo stretto, vedi il @media in fondo */
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 32px;
  height: 32px;
  margin-left: auto;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  flex-shrink: 0;
  position: relative;
}
/* bersaglio da 44px, che e' quello che un dito colpisce davvero, senza
   cambiare il disegno: lo pseudo-elemento e' fuori flusso e non si vede */
.nav-burger::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}
.nav-burger span {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: var(--text);
  transition: transform .25s ease, opacity .25s ease;
}
.nav-burger.aperto span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-burger.aperto span:nth-child(2) { opacity: 0; }
.nav-burger.aperto span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 820px) {
  .nav-burger { display: flex; }
  .topbar .tabs {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    flex-direction: column;
    gap: 0;
    min-width: 190px;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--bg);
    box-shadow: 0 12px 32px rgba(0, 0, 0, .32);
    /* 40 -> 70 (06/09/2026): la barra del titolo e' diventata appiccicosa
       con z-index 60 e sfondo pieno, e copriva la CIMA della tendina -
       proprio le voci Equipment e ODG, le prime due. Il menu aperto deve
       stare sopra a tutto quel che scorre: barra (60) e filtri (61). */
    z-index: 70;
  }
  .topbar.menu-aperto .tabs { display: flex; }
  .topbar .tab {
    width: 100%;
    text-align: left;
    padding: 11px 12px;
    border-bottom: none;
  }
  .topbar .tab.active { color: var(--accent); }
}


/* ---------- l'interruttore delle iscrizioni Yoga ---------- */
/* Sta in cima alla scheda e non dentro i grafici: chiudere le iscrizioni e'
   la cosa piu' urgente che si fa da qui, e non puo' dipendere dall'aver
   aperto un pannello. Verde quando sono aperte, spento quando sono chiuse:
   lo stato si legge prima di leggere le parole. */
.yoga-iscrizioni {
  display: flex;
  align-items: center;
  /* Piu' compatta in verticale (Carlo, 06/09/2026): meta' dei
     respiri di prima, ora che vive dentro il riepilogo. */
  gap: 6px 12px;
  flex-wrap: wrap;
  padding: 7px 12px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.yoga-iscrizioni.sono-aperte {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.yoga-iscrizioni-stato { flex: 1; min-width: 0; font-size: 15px; color: var(--text-dim); }
.yoga-iscrizioni-stato strong { color: var(--text); }
.yoga-iscrizioni.sono-aperte .yoga-iscrizioni-stato strong { color: var(--accent); }
.yoga-iscrizioni-btn {
  border: 1px solid var(--border);
  background: none;
  color: var(--text);
  border-radius: 9px;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  flex-shrink: 0;
}
.yoga-iscrizioni-btn:hover { border-color: var(--text-dim); }
/* CHIUDERE E' L'AZIONE GROSSA, e si veste di rosso (Carlo, 07/09/2026):
   stesso rosso della pastiglia "No" della donazione, cosi' i segnali di
   pericolo dell'app parlano una lingua sola. Solo lo stato "Chiudi":
   "Apri le iscrizioni" resta neutro. */
.yoga-iscrizioni-btn.yoga-btn-chiudi {
  border-color: rgba(224, 82, 75, 0.55);
  color: var(--danger, #ff7a72);
}
.yoga-iscrizioni-btn.yoga-btn-chiudi:hover {
  border-color: var(--danger, #ff7a72);
  background: rgba(224, 82, 75, 0.14);
}
.yoga-iscrizioni-btn:disabled { opacity: .55; cursor: default; }

/* IL LINK DEL MODULO. Va su una riga sua sotto l'interruttore: e' la cosa che
   si copia e si manda a Fondazione, e messo in fila con "Apri/Chiudi"
   sparirebbe fra due pulsanti che fanno tutt'altro.
   `flex-basis: 100%` la fa andare a capo dentro lo stesso riquadro invece che
   in un riquadro suo: apertura e link sono la stessa faccenda. */
.yoga-link {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  border-top: 1px solid var(--border);
  padding-top: 5px;
  font-size: 13px;
  color: var(--text-dim);
}
/* Il <code> con l'URL in chiaro non esiste piu' (06/09/2026): i bottoni
   portano l'indirizzo in data-copia-testo e la riga contiene solo loro. */
.yoga-link .yoga-iscrizioni-btn { padding: 3px 9px; font-size: 12.5px; }

/* ============================================================
   LA BARRA DEL TITOLO E' APPICCICOSA e il pannello dei filtri le
   galleggia sotto (Carlo, 06/09/2026): aperto da fondo pagina,
   il pannello e' comunque davanti agli occhi, sopra il contenuto,
   e si scorre l'elenco con i filtri aperti. Si chiude con un clic
   fuori o con Esc - i gestori stanno in app.js.
   ============================================================ */
.riga-titolo {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--bg);
}
.riga-titolo .filterspanel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  /* 6 -> 2 -> -6px: anche a 2 il riquadro del riepilogo spuntava
     ancora da dietro l'angolo del pannello (Carlo, 06/09/2026, secondo
     screenshot). A -6 il pannello monta di qualche pixel sulla barra e
     copre per intero quel che gli sta sotto: la barra e' sua madre
     (sticky, z-index piu' basso del pannello), quindi niente si perde. */
  margin: -6px 0 0;
  padding: 16px 20px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 14px 44px rgba(0, 0, 0, 0.45);
  z-index: 61;
}

/* IL SEMAFORO DELLA DONAZIONE nell'elenco Yoga, sui toni dello stato
   fatture di Billing: verde confermata, rosso no. E' un bottone vero:
   il clic cambia lo stato sul database senza aprire la scheda. */
.dona-pill {
  border: none;
  border-radius: 999px;
  padding: 3px 12px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
/* Verde WATERMELON, non il verde dei soldi: e' l'accento delle app
   (Carlo, 06/09/2026). */
.dona-si { background: rgba(0, 187, 180, 0.16); color: var(--accent, #00bbb4); }
.dona-no { background: rgba(224, 82, 75, 0.16);  color: var(--danger, #ff7a72); }
.dona-pill:disabled { opacity: 0.5; cursor: default; }

/* IL MENU VOLANTE della donazione, preso di peso da Billing: vive
   attaccato a <body>, quindi il corpo del testo se lo dichiara da solo. */
.menu-volante {
  font-size: 14px;
  position: absolute; z-index: 80; min-width: 120px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 11px; box-shadow: 0 14px 44px rgba(0, 0, 0, 0.45); padding: 5px;
}
.voce-stato {
  display: flex; align-items: center; gap: 10px; width: 100%;
  text-align: left; background: none; border: none;
  padding: 5px 6px; cursor: pointer; border-radius: 8px;
  font: inherit; color: var(--text);
}
.voce-stato:hover { background: var(--surface-2); }
/* Le due pastiglie nel menu hanno la STESSA larghezza, fissa: senza,
   quella senza spunta si allargava a riempire la riga e le due voci
   sembravano di due menu diversi (Carlo, 06/09/2026). */
.voce-stato .dona-pill { flex: 0 0 auto; min-width: 54px; text-align: center; }
.voce-attuale { margin-left: auto; color: var(--text-dim); }

/* La freccia dell'ordinamento: posto fisso in ogni intestazione, cosi'
   ordinare non allarga mai le colonne. Spenta = invisibile ma ingombrante. */
.freccia-ordine { display: inline-block; width: 0.95em; text-align: right; }
.freccia-ordine.spenta { visibility: hidden; }
