/* OPERA v2 — App Rilievo — style.css v0.12.0 Touch-first per iPad in cantiere. Bottoni grandi, contrasto alto, zero fronzoli. */ * { box-sizing: border-box; margin: 0; padding: 0; } :root { --bg: #f5f5f5; --surface: #ffffff; --text: #1a1a1a; --text-light: #666; --primary: #2563eb; --primary-hover: #1d4ed8; --danger: #dc2626; --success: #16a34a; --warn: #f59e0b; --border: #e0e0e0; --radius: 8px; --touch-min: 48px; } html { font-size: 16px; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); min-height: 100dvh; -webkit-tap-highlight-color: transparent; overflow-x: hidden; } /* ─── VISTE ─── */ .view { display: none; padding: 0; } .view:not([hidden]) { display: block; } /* ─── BANNER ─── */ .banner { position: sticky; top: 0; z-index: 100; padding: 10px 16px; text-align: center; font-weight: 600; font-size: 0.9rem; } .banner-warn { background: var(--warn); color: #000; } .banner-info { background: var(--primary); color: #fff; } /* ─── TOPBAR ─── */ .topbar { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 50; } .topbar h2 { font-size: 1.2rem; flex: 1; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .topbar-actions { display: flex; gap: 8px; } /* ─── BOTTONI ─── */ .btn { display: inline-flex; align-items: center; justify-content: center; min-height: var(--touch-min); padding: 0 20px; border: none; border-radius: var(--radius); font-size: 1rem; font-weight: 600; cursor: pointer; transition: background 0.15s; white-space: nowrap; } .btn-primary { background: var(--primary); color: #fff; } .btn-primary:active { background: var(--primary-hover); } .btn-ghost { background: transparent; color: var(--primary); } .btn-ghost:active { background: rgba(37,99,235,0.1); } /* v1.8.3 (C2) — Bottone discreto "link" per il jump rapido alle Caratteristiche muro globali dalla vista misure. Look testuale (no border, no background) con icona + sottolineatura su hover, così non "ruba" attenzione ai bottoni primari Salva/Indietro della topbar. */ .btn-link-muro { background: transparent; border: none; color: var(--primary, #2563eb); cursor: pointer; font-size: 0.85rem; padding: 4px 8px; text-decoration: none; transition: text-decoration 0.15s; } .btn-link-muro:hover { text-decoration: underline; } .btn-link-muro:active { color: var(--primary-hover, #1d4ed8); } .btn-secondary { background: #14b8a6; color: #fff; } .btn-secondary:active { background: #0d9488; } .btn-danger { background: var(--danger); color: #fff; } .btn-block { width: 100%; } /* ─── LOGIN ─── */ .login-box { max-width: 360px; margin: 80px auto; padding: 32px 24px; background: var(--surface); border-radius: 12px; text-align: center; } .login-box h1 { font-size: 2rem; letter-spacing: 4px; margin-bottom: 4px; } .login-sub { color: var(--text-light); margin-bottom: 24px; } .login-box input { width: 100%; padding: 14px; margin-bottom: 12px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 1rem; } /* ─── ERRORI ─── */ .errore { color: var(--danger); font-size: 0.9rem; margin-top: 8px; } /* ─── LISTA PROGETTI ─── */ .lista-progetti { padding: 8px; } .placeholder { text-align: center; color: var(--text-light); padding: 40px; } .progetto-card { display: flex; align-items: center; justify-content: space-between; padding: 16px; margin-bottom: 8px; background: var(--surface); border-radius: var(--radius); border-left: 4px solid var(--primary); cursor: pointer; min-height: 64px; } .progetto-card:active { background: #f0f0f0; } .progetto-card .pc-nome { font-weight: 600; font-size: 1.05rem; } .progetto-card .pc-meta { color: var(--text-light); font-size: 0.85rem; } .progetto-card .pc-stato { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 0.8rem; font-weight: 600; } .stato-preventivo { background: #dbeafe; color: #1e40af; } .stato-inviato { background: #fef3c7; color: #92400e; } .stato-confermato { background: #d1fae5; color: #065f46; } .stato-installato { background: #e5e7eb; color: #374151; } .stato-sopralluogo_da_fissare { background: #fce7f3; color: #9d174d; } /* v0.79.0 — nuovi stati handoff rilievo→ufficio */ .stato-rilievo_in_corso { background: #cffafe; color: #155e75; } .stato-rilievo_da_smistare { background: #fed7aa; color: #9a3412; } .stato-in_lavorazione_ufficio { background: #ddd6fe; color: #5b21b6; } /* v0.95.0 — banner stato ufficio nella vista lista progetti (Open vede quanti suoi rilievi sono pendenti) */ .banner-stato-ufficio { background: #fff7ed; border: 1px solid #fed7aa; border-left: 4px solid #f97316; border-radius: 6px; padding: 10px 14px; margin: 0 12px 12px 12px; font-size: 0.9rem; display: flex; align-items: center; gap: 10px; color: #9a3412; } .banner-stato-ufficio .bsu-icon { font-size: 1.1rem; } .banner-stato-ufficio strong { color: #c2410c; } /* v0.85.0 — promemoria richiesta all'ufficio (mostrato a Open quando rivede un suo rilievo inviato) */ .progetto-handoff-promemoria { background: #fff7ed; border: 1px solid #fed7aa; border-left: 4px solid #f97316; border-radius: 6px; padding: 10px 14px; margin-bottom: 12px; font-size: 0.9rem; } .progetto-handoff-promemoria .hp-header { font-weight: 600; color: #9a3412; margin-bottom: 4px; } .progetto-handoff-promemoria .hp-azione { color: #c2410c; font-weight: 500; margin-bottom: 4px; } .progetto-handoff-promemoria .hp-note { font-size: 0.85rem; color: #6b7280; font-style: italic; margin: 4px 0; } .progetto-handoff-promemoria .hp-status { font-size: 0.85rem; color: #5b21b6; font-weight: 600; margin-top: 4px; } /* ─── HANDOFF MODAL (v0.79.0) ─── */ .modal-hint { font-size: 0.9rem; color: #64748b; margin: 0 0 16px 0; } .handoff-azioni { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; } .handoff-radio { display: flex; align-items: flex-start; gap: 12px; padding: 12px; border: 1px solid #e5e7eb; border-radius: 8px; cursor: pointer; transition: background 0.1s, border-color 0.1s; } .handoff-radio:hover { background: #f9fafb; border-color: #cbd5e1; } .handoff-radio:has(input:checked) { background: #eff6ff; border-color: #3b82f6; } .handoff-radio input { margin-top: 2px; flex-shrink: 0; } .handoff-radio span { flex: 1; font-size: 0.95rem; line-height: 1.4; } .handoff-radio small { color: #64748b; font-weight: normal; } .handoff-note { display: block; margin-bottom: 16px; } .handoff-note span { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 6px; } .handoff-note textarea { width: 100%; padding: 8px; border: 1px solid #cbd5e1; border-radius: 6px; font-family: inherit; font-size: 0.95rem; resize: vertical; } /* ─── MODAL ─── */ .modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); display: flex; align-items: center; justify-content: center; z-index: 200; } .modal-overlay[hidden] { display: none; } .modal { background: var(--surface); padding: 24px; border-radius: 12px; width: 90%; max-width: 400px; } .modal h3 { margin-bottom: 16px; } .modal label { display: block; margin-bottom: 12px; font-weight: 600; font-size: 0.9rem; } .modal select, .modal input[type="text"] { width: 100%; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 1rem; margin-top: 4px; } .modal-actions { display: flex; gap: 8px; margin-top: 16px; justify-content: flex-end; } .checkbox-group { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; } .checkbox-group label { display: flex; align-items: center; gap: 4px; font-weight: 400; font-size: 0.9rem; background: var(--bg); padding: 6px 10px; border-radius: 6px; } /* ─── PROGETTO ─── */ .progetto-info { padding: 12px 16px; background: var(--surface); border-bottom: 1px solid var(--border); font-size: 0.9rem; color: var(--text-light); } .progetto-toolbar { display: flex; gap: 8px; padding: 8px 12px; background: var(--surface); border-bottom: 1px solid var(--border); } .btn-small { min-height: 40px; padding: 0 14px; font-size: 0.9rem; font-weight: 600; } /* ─── MURO (check/hint) ─── */ .muro-check { margin-top: 10px; padding: 8px 10px; border-radius: 6px; font-size: 0.85rem; font-weight: 600; } .muro-check.ok { background: #d1fae5; color: #065f46; } .muro-check.warn { background: #fef3c7; color: #92400e; } .muro-hint { margin-top: 6px; font-size: 0.8rem; color: var(--text-light); font-style: italic; } .lista-posizioni { padding: 8px; } .posizione-card { display: flex; align-items: center; padding: 16px; margin-bottom: 8px; background: var(--surface); border-radius: var(--radius); cursor: pointer; min-height: 64px; gap: 12px; } .posizione-card:active { background: #f0f0f0; } .pos-numero { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: var(--primary); color: #fff; border-radius: 50%; font-weight: 700; font-size: 0.9rem; flex-shrink: 0; } .pos-info { flex: 1; } .pos-info .pos-ambiente { font-weight: 600; } .pos-info .pos-tipo { color: var(--text-light); font-size: 0.85rem; } .pos-info .pos-prodotti { font-size: 0.8rem; color: var(--text-light); margin-top: 2px; } .pos-misure-badge { font-size: 0.8rem; padding: 3px 8px; border-radius: 10px; font-weight: 600; } .badge-completo { background: #d1fae5; color: #065f46; } .badge-incompleto { background: #fef3c7; color: #92400e; } /* ─── STATO POSIZIONE (icona ok/warn/err) ─── */ .pos-stato-icon { font-size: 1.2rem; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; cursor: pointer; border-radius: 50%; transition: background 0.15s; } .pos-stato-icon:active { background: rgba(0,0,0,0.08); } .pos-stato-icon.stato-ok { color: #16a34a; } .pos-stato-icon.stato-warn { color: #d97706; } .pos-stato-icon.stato-err { color: #dc2626; } /* v1.4.0 — Bottone elimina posizione (rosso, in basso a destra della card) */ .pos-elimina-btn { background: none; border: none; font-size: 1.1rem; padding: 8px; margin-left: 4px; cursor: pointer; opacity: 0.4; border-radius: 4px; flex-shrink: 0; transition: opacity 0.15s, background 0.15s; } .pos-elimina-btn:hover { opacity: 1; background: #fef2f2; } .pos-elimina-btn:active { opacity: 1; background: #fee2e2; } /* ─── CONTATORE STATO PROGETTO ─── */ .progetto-stato { display: flex; gap: 10px; align-items: center; font-size: 0.85rem; margin-left: auto; } .progetto-stato span { padding: 4px 10px; border-radius: 12px; font-weight: 600; cursor: pointer; min-height: 28px; display: inline-flex; align-items: center; } .progetto-stato .ps-ok { background: #d1fae5; color: #065f46; cursor: default; } .progetto-stato .ps-warn { background: #fef3c7; color: #92400e; } .progetto-stato .ps-err { background: #fee2e2; color: #991b1b; } .progetto-stato .ps-warn:active, .progetto-stato .ps-err:active { opacity: 0.7; } /* ─── CHECK INLINE (warning/error sotto gruppo campi) ─── */ .check-inline { margin: 10px 0 0; padding: 10px 12px; border-radius: 6px; font-size: 0.88rem; font-weight: 600; line-height: 1.5; } .check-inline.ok { background: #d1fae5; color: #065f46; } .check-inline.warn { background: #fef3c7; color: #92400e; } .check-inline.err { background: #fee2e2; color: #991b1b; } .check-inline div { margin: 2px 0; } /* ─── BOTTONE SALVA DISABILITATO (errori bloccanti) ─── */ .btn.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; background: var(--primary); } /* ─── MODALE PROBLEMI ─── */ #modal-problemi-body { max-height: 60vh; overflow-y: auto; font-size: 0.9rem; } #modal-problemi-body .problemi-sezione { margin-bottom: 14px; } #modal-problemi-body h5 { font-size: 0.9rem; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; } #modal-problemi-body ul { list-style: none; padding: 0; } #modal-problemi-body li { padding: 8px 10px; margin-bottom: 4px; border-radius: 6px; line-height: 1.4; } #modal-problemi-body li.err { background: #fee2e2; color: #991b1b; } #modal-problemi-body li.warn { background: #fef3c7; color: #92400e; } /* ─── MISURE ─── */ .misure-grid { padding: 12px 16px; } .misure-gruppo { background: var(--surface); border-radius: var(--radius); padding: 14px; margin-bottom: 10px; } .misure-gruppo h4 { font-size: 0.85rem; color: var(--text-light); margin-bottom: 10px; text-transform: uppercase; letter-spacing: 0.5px; } .misure-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } /* v1.8.0 — variante 4 colonne per layout compatto (LF/HF/TMV/HMT su 1 riga). */ .misure-row.compatta { grid-template-columns: repeat(4, 1fr); } .misure-row label { display: flex; align-items: center; gap: 6px; font-weight: 600; font-size: 0.95rem; } /* v1.8.0 fix — l'attributo HTML hidden deve vincere su display:flex */ .misure-row label[hidden] { display: none; } /* v1.8.0 — label/input full-width per campi singoli su tutta la riga. */ .misure-row label.full { grid-column: 1 / -1; flex-direction: column; align-items: stretch; gap: 4px; } .misure-row input.full { width: 100%; padding: 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 0.95rem; } .misure-row input[type="number"] { flex: 1; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 1.1rem; text-align: right; min-width: 0; } .misure-row select { padding: 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 1rem; } .misure-grid textarea { width: 100%; padding: 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 0.95rem; resize: vertical; } /* v1.8.2 (C1) — Subtitle "📦 prodotti attivi" sotto il titolo posizione. Mostra a colpo d'occhio quali prodotti contiene la posizione. */ .misure-prodotti-attivi { padding: 8px 16px 4px; font-size: 0.9rem; color: var(--text-light); display: flex; align-items: center; gap: 8px; } .misure-prodotti-attivi .mpa-icona { font-size: 1rem; } .misure-prodotti-attivi .mpa-prodotto { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.85rem; font-weight: 600; margin-right: 6px; color: white; } .misure-prodotti-attivi .mpa-prodotto.bp-infisso { background: var(--primary, #2563eb); } .misure-prodotti-attivi .mpa-prodotto.bp-tapparella { background: var(--warn, #f59e0b); } .misure-prodotti-attivi .mpa-prodotto.bp-zanzariera { background: var(--success, #16a34a); } .misure-prodotti-attivi .mpa-prodotto.bp-cassonetto { background: #475569; } .misure-prodotti-attivi .mpa-prodotto.bp-persiana { background: #92400e; } .misure-prodotti-attivi .mpa-prodotto.bp-portoncino { background: #7c3aed; } /* v1.8.2 (C1) — Header colorato distintivo per ogni blocco prodotto. Sostituisce il piccolo

grigio: banner pieno colore con emoji+nome per separare visivamente Infisso/Tapparella/Zanzariera durante lo scroll. */ .blocco-prodotto-header { margin: -14px -14px 12px -14px; /* sborda nei padding del .misure-gruppo */ padding: 10px 14px; border-radius: var(--radius) var(--radius) 0 0; font-size: 0.95rem; font-weight: 700; letter-spacing: 0.5px; color: white; display: flex; align-items: center; gap: 8px; } .blocco-prodotto.bp-infisso .blocco-prodotto-header { background: var(--primary, #2563eb); } .blocco-prodotto.bp-tapparella .blocco-prodotto-header { background: var(--warn, #f59e0b); } .blocco-prodotto.bp-zanzariera .blocco-prodotto-header { background: var(--success, #16a34a); } .blocco-prodotto.bp-cassonetto .blocco-prodotto-header { background: #475569; } .blocco-prodotto.bp-persiana .blocco-prodotto-header { background: #92400e; } .blocco-prodotto.bp-portoncino .blocco-prodotto-header { background: #7c3aed; } /* Bordo lateralel sinistro persistente come "ancora" del prodotto durante lo scroll */ .blocco-prodotto.bp-infisso { border-left: 4px solid var(--primary, #2563eb); } .blocco-prodotto.bp-tapparella { border-left: 4px solid var(--warn, #f59e0b); } .blocco-prodotto.bp-zanzariera { border-left: 4px solid var(--success, #16a34a); } /* v1.8.0 — Sub-gruppo "Apertura per anta" dentro blocco infisso. */ .misure-sub-gruppo { margin-top: 10px; padding: 10px; background: #fafafa; border-radius: var(--radius); border: 1px solid var(--border); } .ante-titolo { font-size: 0.8rem; color: var(--text-light); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; } .ante-riga { display: grid; grid-template-columns: 80px 1fr; gap: 10px; align-items: center; margin-bottom: 6px; } /* v1.8.0 fix — l'attributo HTML hidden deve vincere su display:grid */ .ante-riga[hidden] { display: none; } .ante-label { font-weight: 600; font-size: 0.95rem; color: var(--text); } .ante-riga select { padding: 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 0.95rem; width: 100%; } .ante-note-wrap { margin-top: 8px; } .ante-note-wrap label { display: flex; flex-direction: column; gap: 4px; font-weight: 600; font-size: 0.9rem; } /* v1.8.0 — Flash visivo su bottone (es. "Inserisci posizione" dopo "Inizia rilievo"). */ .flash-evidenza { animation: flashEvidenza 1.8s ease-out; box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.7); } @keyframes flashEvidenza { 0% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.7); transform: scale(1); } 20% { box-shadow: 0 0 0 12px rgba(37, 99, 235, 0); transform: scale(1.05); } 40% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.7); transform: scale(1); } 60% { box-shadow: 0 0 0 12px rgba(37, 99, 235, 0); transform: scale(1.05); } 100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0); transform: scale(1); } } /* ─── RESPONSIVE ─── */ /* v1.8.2 — Tablet (iPad portrait ~768px, landscape ~1024px): la griglia 4-colonne delle misure compatte diventa 2 colonne — restano leggibili senza scroll orizzontale. Su smartphone diventa 1 colonna. */ @media (max-width: 1024px) { .misure-row.compatta { grid-template-columns: repeat(2, 1fr); } /* Sub-righe ante: il select prende tutta la larghezza disponibile */ .ante-riga { grid-template-columns: 70px 1fr; } } @media (max-width: 600px) { .misure-row { grid-template-columns: 1fr; } .misure-row.compatta { grid-template-columns: 1fr 1fr; } .topbar h2 { font-size: 1rem; } .blocco-prodotto-header { font-size: 0.85rem; padding: 8px 10px; } } @media (max-width: 480px) { /* Smartphone piccoli: 1 colonna ovunque */ .misure-row.compatta { grid-template-columns: 1fr; } } /* ═══════════════════════════════════════════════════════════════ */ /* NUOVO PROGETTO Odoo-first (v1.1.0) */ /* ═══════════════════════════════════════════════════════════════ */ .modal-nuovo-progetto { max-width: 520px; width: 92%; } .np-ricerca { margin-bottom: 16px; } .np-ricerca label { display: block; margin-bottom: 6px; font-weight: 600; color: var(--text); } .np-ricerca-row { display: flex; gap: 8px; margin-bottom: 4px; } .np-ricerca-row input { flex: 1; padding: 12px; font-size: 1rem; border: 2px solid var(--border, #d1d5db); border-radius: 6px; } .np-ricerca-row input:focus { border-color: var(--primary, #2563eb); outline: none; } .np-ricerca-row .btn { padding: 12px 16px; white-space: nowrap; } .np-hint { margin: 0; font-size: 0.85rem; color: var(--text-muted, #6b7280); } /* v1.3.0 — feedback validazione live */ .np-hint-warn { color: #92400e; font-weight: 500; } .np-hint-ok { color: #166534; font-weight: 500; } .np-label { margin: 12px 0 8px; font-weight: 600; font-size: 0.95rem; } .np-risultati { margin-top: 12px; } .np-risultati-lista { display: flex; flex-direction: column; gap: 8px; max-height: 320px; overflow-y: auto; } .np-cliente-card { border: 1px solid var(--border, #d1d5db); border-radius: 6px; padding: 12px; cursor: pointer; transition: border-color 0.15s, background 0.15s; background: #fff; } .np-cliente-card:hover, .np-cliente-card:active { border-color: var(--primary, #2563eb); background: #eff6ff; } .np-cliente-nome { font-weight: 600; font-size: 1rem; margin-bottom: 4px; } .np-cliente-meta { display: flex; flex-wrap: wrap; gap: 8px 14px; font-size: 0.85rem; color: var(--text-muted, #6b7280); margin-bottom: 4px; } .np-cliente-id { font-size: 0.75rem; color: #9ca3af; font-family: monospace; } .np-fallback { margin-top: 12px; } .np-fallback hr { border: none; border-top: 1px dashed var(--border, #d1d5db); margin: 16px 0; } .btn-warn { background: #f97316; color: white; border: 1px solid #f97316; } .btn-warn:hover { background: #ea580c; border-color: #ea580c; } .btn-warn:disabled { opacity: 0.6; cursor: not-allowed; }