This commit is contained in:
javad committed 2026-09-10 11:34:19 +03:30
commit fa9d154db9
260 files changed
+17643

No files matched your search

+1
View File
@@ -0,0 +1 @@
:root{font-family:Tahoma,Arial,sans-serif;color:#172033;background:#f4f7fb;line-height:1.7;--brand:#075985;--accent:#0ea5e9}*{box-sizing:border-box}body{margin:0}.top{height:68px;background:#fff;border-bottom:1px solid #e2e8f0;display:flex;align-items:center;justify-content:space-between;padding:0 max(20px,calc((100% - 1200px)/2));position:sticky;top:0;z-index:5}.brand{font-weight:800;color:var(--brand);font-size:1.15rem}.top nav{display:flex;gap:18px}.container{max-width:1200px;margin:30px auto;padding:0 18px}a{color:#0369a1;text-decoration:none}h1,h2,h3{line-height:1.35}.card{background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:22px;box-shadow:0 4px 18px #0f172a0a}.auth{max-width:470px;margin:8vh auto}.form-card{max-width:760px;margin:auto}.muted{color:#64748b}.page-head{display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:22px}.button,button{display:inline-block;background:var(--brand);color:#fff;border:0;border-radius:10px;padding:10px 18px;font:inherit;cursor:pointer}button:disabled{opacity:.45;cursor:not-allowed}label{font-weight:700;display:block;margin-bottom:5px}input,textarea,select{width:100%;border:1px solid #cbd5e1;border-radius:9px;padding:10px 12px;font:inherit;background:#fff}textarea{min-height:120px}.errorlist{color:#b91c1c}.flash{padding:12px;border-radius:9px;background:#dbeafe;margin-bottom:15px}.flash.error{background:#fee2e2}.ticket-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px}.ticket{display:flex;flex-direction:column;gap:7px;color:inherit}.ticket h2{font-size:1.05rem;margin:0}.badge{background:#e0f2fe;color:#075985;border-radius:999px;padding:3px 10px;display:inline-block;font-size:.82rem}.priority-urgent{background:#fee2e2;color:#991b1b}.priority-important{background:#fef3c7;color:#92400e}.empty{text-align:center;padding:70px 20px;background:#fff;border-radius:16px}.staff-list{display:grid;gap:10px}.staff-list .ticket{flex-direction:row;align-items:center;justify-content:space-between}.search{display:flex;gap:8px;max-width:600px}.staff-layout{display:grid;grid-template-columns:230px minmax(0,1fr) 230px;gap:16px;align-items:start}.conversation{display:grid;gap:12px;max-height:62vh;overflow:auto}.message{background:#f1f5f9;border-radius:14px;padding:12px 16px;max-width:82%}.message.mine{background:#e0f2fe;margin-right:auto}.message.note{background:#fff7ed;border:1px dashed #fb923c;max-width:100%}.message header{display:flex;justify-content:space-between;gap:15px;font-size:.82rem}.message p{white-space:normal}.attachment{display:block;padding:6px;background:#ffffffaa;border-radius:6px;margin-top:6px}.composer{margin-top:14px}.mode{display:flex;gap:8px}.mode button{background:#e2e8f0;color:#334155}.mode button.active{background:var(--brand);color:#fff}.mode button.note-button{background:#c2410c}.voice{display:flex;align-items:center;gap:8px;margin:10px 0}dl{display:grid;grid-template-columns:auto 1fr;gap:7px}dd{margin:0;font-weight:bold}details{margin-top:15px}summary{cursor:pointer;font-weight:bold}@media(max-width:850px){.staff-layout{grid-template-columns:1fr}.page-head{align-items:stretch;flex-direction:column}.search{flex-direction:column}.staff-list .ticket{align-items:flex-start;flex-direction:column}.message{max-width:94%}.top{padding:0 15px}}
+2
View File
@@ -0,0 +1,2 @@
.dispatch-metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.7rem}.dispatch-metrics article{display:grid;gap:.25rem;border:1px solid #dce7ef;border-radius:1rem;background:#fff;padding:.9rem 1rem;box-shadow:0 12px 30px -28px #08376b}.dispatch-metrics small{color:#718698;font-size:.62rem}.dispatch-metrics b{color:#123e62;font-size:1.25rem}.dispatch-filter{display:grid;gap:.65rem;border-bottom:1px solid #e3ebf1;background:#f8fbfd;padding:.8rem}.dispatch-filter>div{display:grid;grid-template-columns:1fr 1fr;gap:.5rem}.dispatch-filter label{display:grid;gap:.25rem;color:#536d81;font-size:.58rem;font-weight:900}.dispatch-filter input,.dispatch-filter select{width:100%;min-height:2.35rem;border:1px solid #cbd9e5;border-radius:.6rem;background:#fff;padding:.45rem .55rem;color:#173f60;font-size:.62rem}.dispatch-filter footer{display:flex;align-items:center;gap:.5rem}.dispatch-filter button{min-height:2.35rem;flex:1;border:0;border-radius:.6rem;background:#0875aa;color:#fff;font-size:.62rem;font-weight:900}.dispatch-filter footer a{color:#647b8d;font-size:.58rem;font-weight:900}.dispatch-results{display:grid;max-height:34rem;overflow:auto}.operations-pagination{display:flex;align-items:center;justify-content:space-between;border-top:1px solid #e5edf3;padding:.7rem .8rem;color:#667e91;font-size:.6rem}.operations-pagination a{border-radius:.55rem;background:#e8f4fb;padding:.4rem .65rem;color:#0873a9;font-weight:900}
@media(max-width:700px){.dispatch-metrics{display:flex;overflow-x:auto}.dispatch-metrics article{min-width:8.5rem}}
+11
View File
@@ -0,0 +1,11 @@
.dashboard{display:grid;grid-template-columns:260px minmax(0,1fr);gap:16px}.filters{position:sticky;top:88px}.tabs{display:grid;gap:6px;margin-bottom:18px}.tabs a{padding:7px;border-radius:8px}.tabs a:hover{background:#e0f2fe}.filter-form{display:grid;gap:10px}.check{display:flex;align-items:center;gap:8px}.check input{width:auto}.metrics{display:flex;flex-wrap:wrap;gap:8px}.metrics span{background:#fff;border:1px solid #e2e8f0;border-radius:9px;padding:5px 10px}.danger,.overdue{color:#b91c1c}.danger-button{background:#b91c1c;padding:6px 10px}.grant,.message-actions,.history-item{display:flex;gap:8px;align-items:center;justify-content:space-between;margin-top:8px}.history-item{align-items:flex-start;flex-direction:column;border-top:1px solid #e2e8f0;padding-top:8px}.message-actions{justify-content:flex-end;font-size:.85rem}.message-actions details{margin:0}button:focus,input:focus,textarea:focus,select:focus,a:focus{outline:3px solid #7dd3fc;outline-offset:2px}@media(max-width:850px){.dashboard{grid-template-columns:1fr}.filters{position:static}}
/* Organizational operations pages */
.operations-toolbar{display:grid;grid-template-columns:minmax(220px,2fr) repeat(2,minmax(150px,1fr)) auto;gap:.75rem;padding:1rem;border-bottom:1px solid var(--line,#e5e7eb)}
.operations-toolbar input,.operations-toolbar select{min-height:44px;border:1px solid #d9e1e8;border-radius:10px;background:#fff;padding:.65rem .8rem}
.operations-toolbar button{border:0;border-radius:10px;background:#176b54;color:#fff;padding:.65rem 1.2rem;font-weight:700}
.operations-form-card{max-width:850px;margin-inline:auto;padding:1.2rem}
.table-subtitle{display:block;margin-top:.3rem;color:#64748b;font-size:.76rem;max-width:320px;white-space:normal}
.tag-chip{display:inline-block;margin:.15rem;padding:.18rem .48rem;border-radius:999px;background:#e7f5ef;color:#176b54;font-size:.75rem}
.operations-metrics{grid-template-columns:repeat(5,minmax(120px,1fr));margin-bottom:1rem}
.form-hint{direction:ltr;text-align:left;overflow-wrap:anywhere;padding:.7rem;border-radius:9px;background:#f3f6f8;color:#52677d;font-size:.75rem}
@media (max-width:900px){.operations-toolbar{grid-template-columns:1fr}.operations-metrics{grid-template-columns:repeat(2,1fr)}.staff-mobile-dock{overflow-x:auto;justify-content:flex-start}.staff-mobile-dock>a,.staff-mobile-dock>form{min-width:74px;flex:0 0 auto}}
+45
View File
@@ -0,0 +1,45 @@
/* Staff organizational operations — intentionally scoped to avoid regressions. */
.operations-page{display:grid;gap:1rem;min-width:0}
.operations-page .staff-page-head{margin-bottom:0}
.operations-page .ticket-stream,.operations-page .filters{border:1px solid #d9e4ee;background:#fff;box-shadow:0 18px 45px -38px rgba(8,55,107,.55)}
.operations-page .ticket-stream{border-radius:1rem;overflow:hidden}
.operations-page .filters{border-radius:1rem;padding:1rem}
.operations-page .stream-head{min-height:4.5rem;padding:1rem 1.15rem;border-bottom:1px solid #e5edf4;background:linear-gradient(135deg,#fff,#f6fbff)}
.operations-page .filter-form{display:grid;gap:.9rem}
.operations-page .filter-form label{display:grid;gap:.4rem;color:#294762;font-size:.75rem;font-weight:800}
.operations-page .filter-form input,.operations-page .filter-form select,.operations-page .filter-form textarea{width:100%;min-height:2.9rem;border:1px solid #cbd9e5;border-radius:.75rem;background:#fff;padding:.68rem .8rem;color:#143552;box-shadow:0 1px 2px rgba(8,55,107,.03)}
.operations-page .filter-form textarea{min-height:9rem;resize:vertical;line-height:1.9}
.operations-page .filter-form select[multiple]{min-height:8rem}
.operations-page .filter-form button,.operations-toolbar button{min-height:2.9rem;border:0;border-radius:.75rem;background:linear-gradient(135deg,#087dc1,#075a94);color:#fff;padding:.7rem 1.1rem;font-weight:900;box-shadow:0 10px 24px -16px #075a94}
.operations-toolbar{display:grid;grid-template-columns:minmax(220px,1fr) auto;gap:.75rem;padding:1rem;border-bottom:1px solid #e5edf4;background:#f9fcff}
.operations-toolbar input,.operations-toolbar select{min-height:2.8rem;border:1px solid #cbd9e5;border-radius:.75rem;background:#fff;padding:.65rem .8rem}
.operations-page .table-scroll{overflow:auto;scrollbar-width:thin}
.operations-page table{width:100%;border-collapse:separate;border-spacing:0;min-width:820px}
.operations-page th{position:sticky;top:0;z-index:1;background:#eef6fc;color:#35556f;font-size:.69rem;font-weight:900;text-align:right;white-space:nowrap;padding:.8rem .9rem;border-bottom:1px solid #d5e3ee}
.operations-page td{padding:.85rem .9rem;border-bottom:1px solid #edf2f6;color:#243f56;font-size:.73rem;vertical-align:top;line-height:1.75}
.operations-page tbody tr:hover td{background:#f8fcff}
.operations-page td a{color:#0874b5;font-weight:900}
.table-subtitle{display:block;margin-top:.2rem;color:#718598;font-size:.65rem;max-width:22rem;white-space:normal;line-height:1.65}
.tag-chip,.status-pill{display:inline-flex;align-items:center;margin:.12rem;padding:.18rem .5rem;border-radius:999px;background:#e7f5ef;color:#176b54;font-size:.65rem;font-weight:800}
.status-pill.is-danger{background:#fff0f0;color:#b42318}.status-pill.is-muted{background:#eef2f5;color:#627586}.status-pill.is-success{background:#e5f7ef;color:#08734e}
.view-counter{display:inline-grid;place-items:center;min-width:2rem;height:2rem;border-radius:.65rem;background:#e5f4ff;color:#086ea9}
.operations-metrics{grid-template-columns:repeat(5,minmax(110px,1fr));margin:0}
.operations-metrics .stat-card{min-height:7rem}
.operations-page .empty-state{text-align:center;padding:2.5rem;color:#73879a}
.operations-form-card{max-width:860px;width:100%;margin-inline:auto;padding:1.2rem}
.form-hint{direction:ltr;text-align:left;overflow-wrap:anywhere;padding:.7rem;border-radius:.65rem;background:#f3f6f8;color:#52677d;font-size:.65rem}
@media(max-width:1000px){.operations-page .dashboard{grid-template-columns:1fr}.operations-page .filters{position:static}.operations-metrics{grid-template-columns:repeat(3,1fr)}}
@media(max-width:640px){.operations-page{gap:.75rem}.operations-toolbar{grid-template-columns:1fr;padding:.75rem}.operations-metrics{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:.35rem}.operations-metrics .stat-card{min-width:9rem;scroll-snap-align:start}.operations-page .ticket-stream,.operations-page .filters{border-radius:.8rem}.operations-page td,.operations-page th{padding:.7rem}.staff-mobile-dock{overflow-x:auto;justify-content:flex-start}.staff-mobile-dock>a,.staff-mobile-dock>form{min-width:74px;flex:0 0 auto}}
/* Unified visual language for the staff operations suite. */
.operations-hero{position:relative;display:flex;align-items:center;justify-content:space-between;gap:2rem;overflow:hidden;border:1px solid rgba(255,255,255,.1);border-radius:1.25rem;background:linear-gradient(125deg,#082f55 0%,#0a5684 62%,#087c94 100%);padding:1.55rem 1.75rem;color:#fff;box-shadow:0 22px 48px -32px rgba(8,47,85,.8)}
.operations-hero:after{position:absolute;left:-4rem;top:-6rem;width:17rem;height:17rem;border-radius:50%;background:rgba(77,208,225,.12);content:""}.operations-hero>div{position:relative;z-index:1}.operations-hero .eyebrow{margin:0 0 .35rem;color:#8de3e8;font-size:.7rem;font-weight:900;letter-spacing:.06em}.operations-hero h1{margin:0;font-size:1.7rem;line-height:1.5}.operations-hero p:last-child{max-width:48rem;margin:.35rem 0 0;color:rgba(255,255,255,.68);font-size:.78rem;line-height:1.9}.operations-hero-actions{display:flex;align-items:center;gap:.65rem;flex:none}.operations-hero-actions .button{min-height:2.75rem;border-color:rgba(255,255,255,.28);background:#fff;color:#0a426c;box-shadow:none}.operations-hero-actions .button-secondary{background:rgba(255,255,255,.09);color:#fff}.security-callout,.template-guide{display:flex;align-items:center;gap:.7rem;flex:none;border:1px solid rgba(255,255,255,.18);border-radius:1rem;background:rgba(255,255,255,.09);padding:.7rem .9rem;backdrop-filter:blur(8px)}.security-callout>span,.template-guide>span{display:grid;width:2.2rem;height:2.2rem;place-items:center;border-radius:.7rem;background:#8de3e8;color:#083b5d;font-weight:900}.security-callout b,.security-callout small,.template-guide b,.template-guide small{display:block}.security-callout b,.template-guide b{font-size:.7rem}.security-callout small,.template-guide small{margin-top:.15rem;color:rgba(255,255,255,.62);font-size:.58rem}
.operations-kpis{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:.7rem}.operations-kpis.compact{grid-template-columns:repeat(3,minmax(0,1fr));max-width:50rem}.operations-kpis article{display:flex;align-items:center;gap:.7rem;min-width:0;border:1px solid #dce7ef;border-radius:1rem;background:#fff;padding:.85rem 1rem;box-shadow:0 12px 30px -28px #08376b}.operations-kpis b,.operations-kpis small{display:block}.operations-kpis b{color:#123e62;font-size:1.25rem;line-height:1}.operations-kpis small{margin-top:.3rem;color:#6f8496;font-size:.62rem;white-space:nowrap}.kpi-icon{display:grid;width:2.4rem;height:2.4rem;flex:none;place-items:center;border-radius:.75rem;background:#e6f6ef;color:#087454;font-weight:900}.kpi-icon.is-blue{background:#e6f4ff;color:#0875b5}.kpi-icon.is-amber{background:#fff4d8;color:#a76b00}.kpi-icon.is-violet{background:#f1eaff;color:#6941c6}.kpi-icon.is-coral{background:#fff0ec;color:#c84d32}
.operations-panel{overflow:hidden;border:1px solid #dce7ef;border-radius:1.1rem;background:#fff;box-shadow:0 18px 45px -38px rgba(8,55,107,.65)}.contact-filter-bar{display:grid;grid-template-columns:minmax(230px,1.7fr) repeat(3,minmax(135px,.8fr)) auto auto;align-items:end;gap:.65rem;padding:1rem;background:linear-gradient(135deg,#f6fbff,#fff);border-bottom:1px solid #e3ecf3}.contact-filter-bar label{display:grid;gap:.35rem;color:#526b80;font-size:.63rem;font-weight:800}.contact-filter-bar input,.contact-filter-bar select{width:100%;min-height:2.65rem;border:1px solid #cbd9e5;border-radius:.7rem;background:#fff;padding:.6rem .7rem;color:#163d5d}.contact-search{position:relative}.contact-search>span{position:absolute;right:.75rem;bottom:.65rem;color:#2588bd;font-size:1rem}.contact-search input{padding-right:2.2rem}.contact-filter-bar button{min-height:2.65rem;border:0;border-radius:.7rem;background:#0a6ea7;padding:.6rem 1rem;color:#fff;font-size:.7rem;font-weight:900}.filter-reset{display:grid;min-height:2.65rem;place-items:center;color:#64798c;font-size:.65rem;font-weight:800}.contact-result-meta{display:flex;align-items:center;justify-content:space-between;padding:.85rem 1.1rem;border-bottom:1px solid #e8eff4}.contact-result-meta b,.contact-result-meta small{display:block}.contact-result-meta b{color:#173f61;font-size:.75rem}.contact-result-meta small{margin-top:.15rem;color:#7a8e9e;font-size:.6rem}.contact-result-meta>a{color:#0875b5;font-size:.65rem;font-weight:900}
.contact-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem;padding:1rem;background:#f7fafc}.contact-card{display:grid;gap:.75rem;min-width:0;border:1px solid #dce7ef;border-radius:1rem;background:#fff;padding:1rem;transition:.18s ease;box-shadow:0 10px 28px -26px #08376b}.contact-card:hover{transform:translateY(-2px);border-color:#9dcbe2;box-shadow:0 18px 36px -29px #08376b}.contact-card header{display:flex;align-items:center;gap:.7rem}.contact-avatar{display:grid;width:2.65rem;height:2.65rem;flex:none;place-items:center;border-radius:.8rem;background:linear-gradient(145deg,#dff4ff,#dff7ef);color:#084d73;font-size:1rem;font-weight:900}.contact-identity{min-width:0;flex:1}.contact-identity h2{overflow:hidden;margin:0;color:#153f60;font-size:.88rem;text-overflow:ellipsis;white-space:nowrap}.contact-identity p{overflow:hidden;margin:.15rem 0 0;color:#718698;font-size:.63rem;text-overflow:ellipsis;white-space:nowrap}.contact-type{flex:none;border-radius:999px;background:#e7f4fb;padding:.2rem .48rem;color:#146b98;font-size:.57rem;font-weight:900}.contact-type.type-supplier{background:#fff3d8;color:#966000}.contact-type.type-carrier{background:#f0eaff;color:#6841b8}.contact-meta{display:flex;flex-wrap:wrap;gap:.4rem .9rem;color:#5f7689;font-size:.64rem}.contact-groups{display:flex;min-height:1.6rem;flex-wrap:wrap;gap:.3rem}.contact-groups span{border-radius:999px;background:#edf5f8;padding:.18rem .48rem;color:#49677c;font-size:.58rem;font-weight:800}.contact-groups small{color:#93a2ae;font-size:.6rem}.contact-ticket-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:.35rem}.contact-ticket-stats span{display:grid;gap:.1rem;border-radius:.6rem;background:#f3f6f8;padding:.45rem;text-align:center;color:#718394;font-size:.55rem}.contact-ticket-stats b{color:#173f60;font-size:.82rem}.contact-ticket-stats .needs-action{background:#fff5df;color:#916000}.contact-ticket-stats .needs-action b{color:#c37700}.contact-card footer{display:flex;align-items:center;justify-content:space-between;border-top:1px solid #edf2f5;padding-top:.7rem}.contact-card footer a{color:#557187;font-size:.64rem;font-weight:900}.contact-card footer .primary-action{border-radius:.6rem;background:#e8f6ff;padding:.4rem .65rem;color:#0875b5}.contact-empty{grid-column:1/-1}.contact-empty>span{display:grid;width:3rem;height:3rem;margin:0 auto .5rem;place-items:center;border-radius:1rem;background:#eaf5fb;color:#1679aa;font-size:1.3rem}
.operations-split,.template-layout,.dispatch-layout{display:grid;grid-template-columns:minmax(0,1fr) 20rem;align-items:start;gap:1rem}.panel-heading{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.1rem;border-bottom:1px solid #e5edf3;background:#f8fbfd}.panel-heading small{color:#74889a;font-size:.6rem}.panel-heading h2{margin:.15rem 0 0;color:#173f60;font-size:.95rem}.panel-heading>span{border-radius:999px;background:#e7f4fb;padding:.3rem .6rem;color:#126c9d;font-size:.6rem;font-weight:900}.group-card-list,.template-card-list{display:grid;gap:.55rem;padding:.8rem}.group-card,.template-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:.75rem;border:1px solid #e0e9ef;border-radius:.8rem;padding:.75rem;transition:.15s}.group-card:hover,.template-card:hover{border-color:#acd2e5;background:#fafdff}.group-symbol,.template-icon{display:grid;width:2.35rem;height:2.35rem;place-items:center;border-radius:.7rem;background:#e8f5fb;color:#0870a6;font-weight:900}.group-card h3,.template-card h3{margin:0;color:#173f60;font-size:.78rem}.group-card p,.template-card p{margin:.12rem 0;color:#667d90;font-size:.62rem}.group-card small,.template-card small{color:#8a9aa7;font-size:.56rem}.group-card>a,.template-card>a{color:#0875b5;font-size:.62rem;font-weight:900}.operations-form-side{overflow:hidden;border:1px solid #d8e4ec;border-radius:1rem;background:#fff;box-shadow:0 18px 40px -36px #08376b;position:sticky;top:5.6rem}.operations-form-side>header{display:flex;align-items:center;gap:.65rem;padding:1rem;background:linear-gradient(135deg,#0a4d78,#087b91);color:#fff}.operations-form-side>header>span{display:grid;width:2rem;height:2rem;place-items:center;border-radius:.6rem;background:rgba(255,255,255,.16);font-weight:900}.operations-form-side header small{font-size:.56rem;color:rgba(255,255,255,.65)}.operations-form-side header h2{margin:.12rem 0 0;font-size:.85rem}.operations-form{display:grid;gap:.75rem;padding:1rem}.operations-form label{display:grid;gap:.35rem}.operations-form label>span{color:#405e75;font-size:.65rem;font-weight:900}.operations-form input,.operations-form select,.operations-form textarea{width:100%;min-height:2.65rem;border:1px solid #c8d8e4;border-radius:.7rem;background:#fbfdff;padding:.6rem .7rem;color:#143e60}.operations-form textarea{min-height:6rem;resize:vertical}.operations-form button{min-height:2.75rem;border:0;border-radius:.7rem;background:linear-gradient(135deg,#0879b7,#075b8d);color:#fff;font-size:.7rem;font-weight:900}.operations-form>a{text-align:center;color:#6e8293;font-size:.62rem;font-weight:800}.operations-form .errorlist,.editor-section .errorlist,.dispatch-composer .errorlist{margin:0;padding:0;color:#b42318;font-size:.6rem;list-style:none}
.contact-editor,.dispatch-composer{display:grid;gap:.85rem}.contact-editor{max-width:58rem;width:100%;margin-inline:auto}.editor-section,.dispatch-composer>section{overflow:hidden;border:1px solid #dbe6ee;border-radius:1rem;background:#fff;box-shadow:0 15px 38px -35px #08376b}.editor-section>header,.dispatch-composer>section>header{display:flex;align-items:center;gap:.7rem;border-bottom:1px solid #e8eef3;padding:.85rem 1rem;background:#f9fcfe}.editor-section>header>span,.dispatch-composer>section>header>span{display:grid;width:2rem;height:2rem;flex:none;place-items:center;border-radius:.65rem;background:linear-gradient(135deg,#0a699f,#098d9c);color:#fff;font-size:.7rem;font-weight:900}.editor-section h2,.dispatch-composer h2{margin:0;color:#173f60;font-size:.82rem}.editor-section header p,.dispatch-composer header p{margin:.15rem 0 0;color:#73889a;font-size:.6rem}.editor-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem;padding:1rem}.editor-grid label,.group-selector,.message-editor{display:grid;align-content:start;gap:.35rem;color:#3f5f77;font-size:.65rem;font-weight:900}.editor-grid input,.editor-grid select,.group-selector select,.message-editor textarea{width:100%;min-height:2.75rem;border:1px solid #c8d8e4;border-radius:.72rem;background:#fbfdff;padding:.62rem .72rem;color:#123f61}.editor-grid input:focus,.editor-grid select:focus,.group-selector select:focus,.message-editor textarea:focus{border-color:#1689bd;outline:3px solid rgba(22,137,189,.11);background:#fff}.editor-grid small,.group-selector small{color:#7a8e9e;font-size:.56rem;font-weight:500}.editor-grid em,.group-selector em{color:#d05c3b;font-style:normal}.editor-wide{grid-column:1/-1}.group-selector,.message-editor{margin:1rem}.group-selector select{min-height:9rem}.location-status{margin:-.35rem 1rem .85rem;border-radius:.6rem;background:#edf7fc;padding:.55rem .7rem;color:#39708e;font-size:.58rem}.location-status.is-error{background:#fff0ed;color:#b04432}.editor-actions{display:flex;align-items:center;gap:.7rem;border:1px solid #d9e5ed;border-radius:1rem;background:#fff;padding:.8rem}.editor-actions button{min-height:2.75rem;border:0;border-radius:.7rem;background:linear-gradient(135deg,#0879b7,#075b8d);padding:.65rem 1.4rem;color:#fff;font-weight:900}.editor-actions a{color:#657d90;font-size:.65rem;font-weight:900}.editor-actions span{margin-right:auto;color:#8798a5;font-size:.58rem}
.dispatch-composer>footer{display:flex;align-items:center;justify-content:space-between;gap:1rem;border:1px solid #d7e4ec;border-radius:1rem;background:#fff;padding:.9rem 1rem}.dispatch-composer footer b,.dispatch-composer footer small{display:block}.dispatch-composer footer b{color:#173f60;font-size:.68rem}.dispatch-composer footer small{margin-top:.18rem;color:#73889a;font-size:.56rem}.dispatch-composer footer button{min-height:2.8rem;border:0;border-radius:.72rem;background:linear-gradient(135deg,#0879b7,#087c86);padding:.65rem 1rem;color:#fff;font-size:.68rem;font-weight:900}.message-editor textarea{min-height:11rem;resize:vertical;line-height:1.9}.dispatch-history{overflow:hidden;border:1px solid #d8e4ec;border-radius:1rem;background:#fff;position:sticky;top:5.6rem}.dispatch-history>header{display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #e5edf3;padding:1rem}.dispatch-history header small{color:#7b8d9d;font-size:.56rem}.dispatch-history header h2{margin:.12rem 0 0;color:#173f60;font-size:.88rem}.dispatch-history header>span{display:grid;width:2rem;height:2rem;place-items:center;border-radius:.65rem;background:#e8f4fb;color:#0873a9;font-size:.65rem;font-weight:900}.dispatch-history>div{display:grid;max-height:39rem;overflow:auto}.dispatch-history-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:.55rem;border-bottom:1px solid #edf2f5;padding:.75rem;color:inherit}.dispatch-history-card:hover{background:#f7fbfd}.dispatch-state{width:.5rem;height:.5rem;border-radius:50%;background:#8da0ae}.dispatch-state.state-sent{background:#12a36d}.dispatch-state.state-queued{background:#e19b18}.dispatch-state.state-partial{background:#dc5c42}.dispatch-history-card b{display:block;overflow:hidden;color:#24485f;font-size:.68rem;text-overflow:ellipsis;white-space:nowrap}.dispatch-history-card small{display:block;margin-top:.15rem;color:#718698;font-size:.56rem}.dispatch-history-card p{display:flex;gap:.6rem;margin:.35rem 0 0;color:#8798a5;font-size:.52rem}.dispatch-history-card em{color:#8aa0b0;font-style:normal}
.template-card-list{max-height:44rem;overflow:auto}.variable-box{border:1px dashed #b9cedb;border-radius:.7rem;background:#f7fbfd;padding:.7rem}.variable-box>b{display:block;margin-bottom:.45rem;color:#3e6077;font-size:.62rem}.variable-box>div{display:flex;flex-wrap:wrap;gap:.3rem}.variable-box code{border-radius:.35rem;background:#e7f3f9;padding:.18rem .35rem;color:#075e8d;font-size:.53rem}
@media(max-width:1100px){.operations-kpis{grid-template-columns:repeat(3,1fr)}.contact-filter-bar{grid-template-columns:repeat(2,minmax(0,1fr))}.contact-search{grid-column:1/-1}.operations-split,.template-layout,.dispatch-layout{grid-template-columns:1fr}.operations-form-side,.dispatch-history{position:static}.dispatch-history>div,.template-card-list{max-height:none}}
@media(max-width:700px){.operations-hero{align-items:stretch;flex-direction:column;padding:1.1rem}.operations-hero h1{font-size:1.3rem}.operations-hero-actions{align-items:stretch;flex-direction:column}.security-callout,.template-guide{align-self:stretch}.operations-kpis,.operations-kpis.compact{display:flex;max-width:none;overflow-x:auto;padding-bottom:.25rem}.operations-kpis article{min-width:9rem}.contact-filter-bar{grid-template-columns:1fr}.contact-search{grid-column:auto}.contact-card-grid{grid-template-columns:1fr;padding:.65rem}.contact-result-meta{align-items:flex-start;flex-direction:column;gap:.4rem}.editor-grid{grid-template-columns:1fr;padding:.8rem}.editor-wide{grid-column:auto}.editor-actions,.dispatch-composer>footer{align-items:stretch;flex-direction:column}.editor-actions span{margin:0}.group-card,.template-card{grid-template-columns:auto minmax(0,1fr) auto}.group-card .status-pill,.template-card .status-pill{grid-column:2}.group-card>a,.template-card>a{grid-column:3;grid-row:1/3}.contact-ticket-stats{grid-template-columns:repeat(2,1fr)}}
+2
View File
@@ -0,0 +1,2 @@
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-tracking:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-content:""}}}@layer theme{:root,:host{--font-sans:Vazirmatn,ui-sans-serif,system-ui;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-200:oklch(88.5% .062 18.334);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-800:oklch(47.3% .137 46.201);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-800:oklch(43.2% .095 166.913);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-400:oklch(70.4% .04 256.788);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-normal:400;--font-weight-medium:500;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--blur-sm:8px;--blur-xl:24px;--blur-2xl:40px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-ink:#08376b;--color-ink-soft:#0b4c8c;--color-cream:#eee;--color-soft:#eaeaea;--color-paper:#fff;--color-sea:#0693e3;--color-sea-dark:#1977ce;--color-blue:#1977ce;--color-mint:#e5f4ff;--color-coral:#fa9f00;--color-sun:#ffc451}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--defLine truncated
+7
View File
@@ -0,0 +1,7 @@
.intent-finder{display:flex;gap:14px;padding:20px;margin-bottom:20px;border:1px solid #bae6fd;border-radius:20px;background:linear-gradient(135deg,#f0f9ff,#ecfdf5)}
.intent-icon{width:46px;height:46px;flex:0 0 46px;display:grid;place-items:center;border-radius:14px;background:#075985;color:#fff;font-size:1.6rem}
.intent-copy{min-width:0;flex:1}.intent-copy h2{margin:0 0 4px;font-size:1.15rem}.intent-copy p{margin:0 0 12px;color:#52677d}
.intent-search{display:flex;align-items:center;background:#fff;border:2px solid #cbd5e1;border-radius:14px;padding:3px 12px}.intent-search:focus-within{border-color:#0284c7;box-shadow:0 0 0 3px #bae6fd}.intent-search input{border:0!important;box-shadow:none!important;margin:0;min-height:46px;flex:1}.intent-search kbd{color:#64748b;font:inherit;font-size:.75rem}
.intent-results{display:grid;gap:8px;margin-top:10px}.intent-result{display:grid;grid-template-columns:1fr auto;gap:3px 10px;text-align:right;padding:11px 13px;border:1px solid #dbeafe;border-radius:12px;background:#fff;color:#0f172a}.intent-result:hover{border-color:#0284c7;background:#f8fdff}.intent-result span{color:#0369a1;font-size:.8rem}.intent-result small{grid-column:1/-1;color:#64748b}.intent-message{margin:8px 2px!important;font-size:.85rem}
.manual-routing{border:1px solid #e2e8f0;border-radius:16px;margin-bottom:22px;overflow:hidden}.manual-routing summary{cursor:pointer;padding:14px 16px;background:#f8fafc;display:flex;justify-content:space-between;gap:8px}.manual-routing summary small{color:#64748b}.manual-routing-body{padding:18px}.routing-selectors{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.routing-selectors .field{min-width:0;margin-bottom:8px}.routing-subject{margin-bottom:0}.routing-subject small{display:block;margin-top:6px;color:#64748b;font-weight:500}.location-fields select{width:100%;min-height:48px;background:#fff}.submit-ticket{position:sticky;bottom:calc(8px + env(safe-area-inset-bottom));z-index:5}.request-form{min-width:0}
@media(max-width:640px){.request-layout{display:block}.request-aside{display:none}.request-form.card{padding:14px;border-radius:18px}.intent-finder{padding:14px;gap:10px}.intent-icon{width:40px;height:40px;flex-basis:40px}.intent-search kbd{display:none}.manual-routing summary{display:block}.manual-routing summary small{display:block;margin-top:4px}.manual-routing-body{padding:14px}.routing-selectors{gap:8px}.routing-selectors select{padding-inline:10px}.expert-picker{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.expert-card{padding:11px}.expert-card img,.expert-avatar{width:56px;height:56px}.step-title{margin-top:24px}.upload-zone{padding:12px}}
+1
View File
@@ -0,0 +1 @@
.field{margin-bottom:18px}.expert-picker{border:0;padding:0;margin:22px 0;display:grid;grid-template-columns:repeat(auto-fill,minmax(155px,1fr));gap:12px}.expert-picker legend{font-weight:700;margin-bottom:10px}.expert-card{position:relative;border:2px solid #e2e8f0;border-radius:14px;padding:15px;display:flex;flex-direction:column;align-items:center;text-align:center;cursor:pointer;transition:.2s}.expert-card:has(input:checked){border-color:#0284c7;background:#f0f9ff;box-shadow:0 0 0 3px #bae6fd}.expert-card input{position:absolute;opacity:0}.expert-card img,.expert-avatar{width:72px;height:72px;border-radius:50%;object-fit:cover;margin-bottom:8px;background:#e0f2fe;display:grid;place-items:center;font-size:2rem;color:#075985}.expert-card small{color:#64748b}.expert-empty{grid-column:1/-1}.upload-zone{border:2px dashed #94a3b8;border-radius:14px;padding:18px;margin:18px 0;background:#f8fafc}.upload-zone>label{cursor:pointer;color:#0369a1}.file-preview{display:grid;grid-template-columns:repeat(auto-fill,minmax(135px,1fr));gap:10px;margin-top:12px}.file-chip{position:relative;background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:8px;overflow:hidden}.file-chip img{width:100%;height:90px;object-fit:cover;border-radius:7px}.file-chip button{position:absolute;top:3px;left:3px;padding:2px 7px;background:#b91c1c}.file-chip small{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.voice-recorder{border-radius:14px;padding:16px;background:#eff6ff;border:1px solid #bfdbfe;margin:18px 0}.voice-head,.voice-actions{display:flex;align-items:center;justify-content:space-between;gap:8px}.voice-actions{justify-content:flex-start;margin:12px 0;flex-wrap:wrap}.ghost{background:#fff;color:#b91c1c;border:1px solid #fecaca}.submit-ticket{width:100%;font-weight:700;font-size:1.05rem}
+9
View File
@@ -0,0 +1,9 @@
# Iran location data
The province and city names in `iran-locations.json` were derived from
[`sajaddp/list-of-cities-in-Iran`](https://github.com/sajaddp/list-of-cities-in-Iran),
which is distributed under the GNU General Public License v3.0.
The upstream dataset states that it is based on Iran's official administrative
divisions through 1402 (2023). The local file contains only province names and
the upstream `cities-filtered.json` city names, grouped by province.
+1
View File
@@ -0,0 +1 @@
[{"province":"آذربایجان شرقی","cities":["آذرشهر","آقکند","اچاچی","اربطان","اسفهلان","اسکو","اهر","ایلخچی","باسمنج","بخشایش","بناب","تبریز","تبریز1","تبریز2","تبریز3","تبریز4","تبریز5","تبریز6","تبریز7","تبریز8","ترک","ترکمانچای","تسوج","تیمورلو","جلفا","خاروانا","خامنه","خداجوخراجو","خسروشاه","خمارلو","خواجه","داریان","دوزدوزان","زرنق","زنوز","سراب","سردرود","سهند","سیس","شبستر","شربیان","شرفخانه","شندآباد","صوفیان","عاشقلو","علیشاه","کردکندی","کشکسرای","کلوانق","کلیبر","گوگان","لاریجان","لاهیجان","لیلان","مراغه","مرند","ملکان","ممقان","مهربان","میانه","نظرکهریزی","هادیشهر","هریس","هشترود","هوراند","وایقان","ورزقان","یامچی"]},{"province":"آذربایجان غربی","cities":["آواجیق","ارومیه","اشنویه","ایواوغلی","باروق","بازرگان","بکتاش","بوکان","پلدشت","پیرانشهر","تکاب","چهاربرج","حاجیلار","خلیفان","خوی","ربط","زرآباد","سردشت","سرو","سلماس","سیلوانه","سیمینه","شوط","فیرورق","قطور","قوشچی","کشاورز","لاجان","ماکو","محمدیار","محمودآباد","مرگنلر","مهاباد","میاندوآب","میرآباد","نالوس","نقده","نلاس","نوشین","یولاگلدی"]},{"province":"اردبیل","cities":["آراللو","اردبیل","اردیموسی","اصلاندوز","النی","اولتان","ثمرین","جعفرآباد","خلخال","رضی","زهرا","زیوه","سرعین","عنبران","فخراباد","فیروزآباد","قصابه","کلور","کوراییم","گرمی","گیوی","لاهرود","مرادلو","نمین","نیر","هشتجین","هیر"]},{"province":"اصفهان","cities":["ابریشم","ابوزیدآباد","اردستان","اژیه","اشترجان","اصغرآباد","اصفهان","افوس","انارک","بادرود","باغشاد","بافران","برزک","بهارستان","بیده","پیربکران","تودشک","تیران","جندق","جوزدان","چادگان","چرمهین","چمگردان","حنا","خالدآباد","خوانسار","خور","خورزوق","داران","دامنه","درچه","دستگرد","دهاقان","دهق","دیزیچه","رزوه","رضوانشهر","زازران","زواره","زیار","زیباشهر","سجزی","سمیرم","سین","شاپورآباد","شهرضا","طاد","طالخونچه","عسگران","علویجه","فرخی","فریدونشهر","فلاورجان","فولادشهر","قمصر","قهجاورستان","قهدریجان","کاشان","کرکوند","کمشچه","کمه","کهریزسنگ","کوشک","کوهپایه","گرگاب","گزبرخوار","گلپایگان","گلدشت","گلشن","گلشهر","گوگد","مبارکه","مجلسی","محمدآباد","مشکات","منظریه","مهاباد","میمه","مینادشت","نایین","نصرآباد","نطنز","نیاسر","هرند","ورزنه","ورنامخواست","وزوان","ونک","ویست"]},{"province":"البرز","cities":["آسارا","اشتهارد","تنکمان","چهارباغ","طالقان","فردیس","کرج","کوهسار","گرمدره","گلسار","ماهدشت","مهستان","نظرآباد","هشتگرد"]},{"province":"ایلام","cities":["آبدانان","ارکواز","ایلام","ایوان","بدره","بلاوه","پهله","توحید","جعفراباد","چوار","دلگشا","دهلران","زرنه","سرابله","شباب","لومار","ماژین","مهر","مهران","مورموری","موسیان","میمه"]},{"province":"بوشهر","cities":["آباد","آبدان","انارستان","اهرم","بادوله","برازجان","بردخون","بردستان","بندردیر","بندردیلم","بندرریگ","بندرکنگان","بندرگناوه","بنک","بهارستان","بوشکان","بوشهر","بوشهر1","بوشهر2","بیدخون","جم","چغادک","خارک","خورموج","دالکی","دلوار","دوراهک","ریز","سیراف","شبانکاره","شنبه","شیرینو","عسلویه","کاکی","کلمه","وحدتیه"]},{"province":"تهران","cities":["آبسرد","آبعلی","ارجمند","اسلامشهر","اندیشه","باغستان","باقرشهر","بومهن","پاکدشت","پردیس","پرند","پیشوا","تجریش","تهران","جوادآباد","چهاردانگه","خسرواباد","دماوند","رباطکریم","رودهن","ری","سعیداباد","شاهدشهر","شمشک","شهریار","شهریار1","شهریار2","شهریار3","صالحیه","صباشهLine truncated
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

+18
View File
@@ -0,0 +1,18 @@
document.querySelectorAll('[data-ticket-composer]').forEach(form=>{
const canonical=form.querySelector('input[name="files"]'),preview=form.querySelector('[data-file-preview]');
if(!canonical||!preview)return;
canonical.classList.add('canonical-file-input');
let files=[];
const status=form.querySelector('[data-compression-status]');
const compress=file=>new Promise(resolve=>{
if(!file.type.startsWith('image/')||file.type==='image/gif'||typeof Compressor==='undefined')return resolve(file);
new Compressor(file,{quality:.76,maxWidth:1920,maxHeight:1920,convertSize:1500000,success(blob){const ext=blob.type==='image/jpeg'?'.jpg':file.name.match(/\.[^.]+$/)?.[0]||'.jpg';resolve(new File([blob],file.name.replace(/\.[^.]+$/,ext),{type:blob.type,lastModified:Date.now()}))},error(){resolve(file)}});
});
const sync=()=>{const dt=new DataTransfer();files.forEach(file=>dt.items.add(file));canonical.files=dt.files;preview.replaceChildren();files.forEach((file,index)=>{const item=document.createElement('div');item.className='file-chip';if(file.type.startsWith('image/')){const img=document.createElement('img');const url=URL.createObjectURL(file);img.src=url;img.onload=()=>URL.revokeObjectURL(url);item.appendChild(img)}const name=document.createElement('small');name.textContent=`${file.name} · ${(file.size/1024/1024).toFixed(1)} MB`;item.appendChild(name);const remove=document.createElement('button');remove.type='button';remove.textContent='×';remove.setAttribute('aria-label','حذف فایل');remove.onclick=()=>{files.splice(index,1);sync()};item.appendChild(remove);preview.appendChild(item)})};
const add=async selected=>{if(status)status.textContent='در حال بهینه‌سازی تصاویر…';const prepared=await Promise.all(Array.from(selected).map(compress));files=[...files,...prepared];sync();if(status)status.textContent='تصاویر آماده ارسال هستند؛ نسخه اصلی روی گوشی شما تغییری نکرده است.'};
form.querySelectorAll('[data-gallery-input],[data-document-input]').forEach(input=>input.addEventListener('change',async()=>{await add(input.files);input.value=''}));
canonical.addEventListener('change',async()=>{if(canonical.dataset.syncing)return;const selected=Array.from(canonical.files);canonical.value='';await add(selected)});
form.addEventListener('voice-added',event=>{files=[...files,event.detail];sync()});
form.addEventListener('voice-removed',event=>{files=files.filter(file=>file!==event.detail);sync()});
form.addEventListener('submit',()=>form.querySelectorAll('button[type=submit],button:not([type])').forEach(button=>button.disabled=true));
});
+42
View File
@@ -0,0 +1,42 @@
document.querySelectorAll('form[data-chat-coach]').forEach(form=>{
const input=form.querySelector('textarea[name="body"]');
if(!input)return;
const rapidWindowMs=2*60*1000;
const autoDismissMs=3000;
let dismissed=false;
let dismissTimer=null;
const readLastTwoMessageTimes=()=>Array.from(document.querySelectorAll('[data-chat-coach-own][data-chat-coach-at]'))
.map(node=>Number(node.dataset.chatCoachAt)*1000)
.filter(Number.isFinite)
.sort((a,b)=>a-b)
.slice(-2);
const hint=document.createElement('aside');
hint.className='chat-coach chat-coach-floating';hint.hidden=true;hint.setAttribute('role','status');hint.setAttribute('aria-live','polite');
hint.innerHTML='<span class="chat-coach-icon" aria-hidden="true">✦</span><div><b>برای دریافت پاسخ دقیق‌تر</b><p>لطفاً همه توضیحات و سؤال‌های خود را در یک پیام کامل بنویسید و سپس ارسال کنید.</p></div><button type="button" data-chat-coach-dismiss aria-label="بستن راهنما" title="بستن">×</button>';
document.body.append(hint);
const dismiss=({focusInput=false}={})=>{
dismissed=true;
hint.hidden=true;
if(dismissTimer)clearTimeout(dismissTimer);
dismissTimer=null;
if(focusInput)input.focus();
};
const showTemporarily=()=>{
if(!hint.hidden)return;
hint.hidden=false;
dismissTimer=setTimeout(()=>dismiss(),autoDismissMs);
};
const detect=()=>{
const [previous,last]=readLastTwoMessageTimes();
const rapidPair=Number.isFinite(previous)&&Number.isFinite(last)&&last>=previous&&last-previous<=rapidWindowMs;
if(!dismissed&&rapidPair)showTemporarily();
else if(!rapidPair)hint.hidden=true;
};
hint.querySelector('[data-chat-coach-dismiss]').addEventListener('click',()=>dismiss({focusInput:true}));
const conversation=document.querySelector('[data-conversation]');
if(conversation)new MutationObserver(detect).observe(conversation,{childList:true,subtree:true});
detect();
});
+132
View File
@@ -0,0 +1,132 @@
document.querySelectorAll('[data-conversation-workspace]').forEach(workspace=>{
const scroller=workspace.querySelector('[data-conversation]');
const conversationEnd=workspace.querySelector('[data-conversation-end]');
const jump=workspace.querySelector('[data-jump-latest]');
const form=workspace.querySelector('[data-ticket-composer]');
const input=form?.querySelector('textarea');
const composer=workspace.querySelector('[data-composer-shell]');
const composerToggle=workspace.querySelector('[data-composer-toggle]');
const baseKey=workspace.dataset.draftKey||location.pathname;
let mode='reply';
const atBottom=()=>scroller.scrollHeight-scroller.scrollTop-scroller.clientHeight<80;
const scrollLatest=(smooth=false)=>{const top=scroller.scrollHeight;if(smooth&&typeof scroller.scrollTo==='function')scroller.scrollTo({top,behavior:'smooth'});else scroller.scrollTop=top};
let initialPin=true;
const scheduleLatest=()=>{[0,40,120,300,700,1200].forEach(delay=>setTimeout(()=>{if(initialPin)scrollLatest(false)},delay))};
scheduleLatest();
window.addEventListener('load',scheduleLatest,{once:true});
window.addEventListener('pageshow',scheduleLatest);
document.fonts?.ready?.then(scheduleLatest);
scroller.querySelectorAll('img,audio').forEach(media=>{const event=media.tagName==='IMG'?'load':'loadedmetadata';media.addEventListener(event,()=>{if(initialPin)scrollLatest(false)},{once:true})});
const sizeObserver='ResizeObserver' in window?new ResizeObserver(()=>{if(initialPin)scrollLatest(false)}):null;
sizeObserver?.observe(scroller);if(conversationEnd?.parentElement)sizeObserver?.observe(conversationEnd.parentElement);
setTimeout(()=>{initialPin=false;sizeObserver?.disconnect()},1800);
['wheel','touchstart','pointerdown','keydown'].forEach(eventName=>scroller.addEventListener(eventName,()=>{initialPin=false;sizeObserver?.disconnect()},{once:true,passive:true}));
scroller.addEventListener('scroll',()=>{jump.hidden=atBottom()});
jump?.addEventListener('click',()=>{scrollLatest(true);jump.hidden=true});
const groupDates=()=>{scroller.querySelectorAll('.date-divider').forEach(item=>item.remove());let previousDate='';scroller.querySelectorAll('[data-message]').forEach(message=>{if(message.dataset.date!==previousDate){const divider=document.createElement('div');divider.className='date-divider';divider.innerHTML=`<span>${message.dataset.dayLabel}</span>`;message.before(divider);previousDate=message.dataset.date}})};
groupDates();
document.body.addEventListener('htmx:beforeSwap',event=>{if(event.detail.target?.matches('[data-load-older]')){scroller.dataset.previousHeight=scroller.scrollHeight}});
document.body.addEventListener('htmx:afterSwap',event=>{if(event.detail.target?.matches('[data-load-older]')){const previous=Number(scroller.dataset.previousHeight||0);groupDates();scroller.scrollTop+=scroller.scrollHeight-previous}});
const resize=()=>{if(!input)return;input.style.height='auto';input.style.height=`${Math.min(Math.max(input.scrollHeight,112),240)}px`};
const draftKey=()=>`${baseKey}-${mode}`;
const status=workspace.querySelector('[data-draft-status]');
const replyResult=workspace.dataset.replyResult||new URLSearchParams(location.search).get('reply_result')||'';
const submissionSucceeded=replyResult==='reply'||replyResult==='note';
if(submissionSucceeded){sessionStorage.removeItem(`${baseKey}-reply`);sessionStorage.removeItem(`${baseKey}-note`)}
const setComposerOpen=(open,focus=true)=>{composer?.classList.toggle('is-collapsed',!open);composerToggle?.setAttribute('aria-expanded',String(open));if(open&&focus)setTimeout(()=>input?.focus(),80)};
const saveDraft=()=>{if(!input)return;sessionStorage.setItem(draftKey(),input.value);if(status){status.textContent=input.value?'پیش‌نویس ذخیره شد':'';clearTimeout(saveDraft.timer);saveDraft.timer=setTimeout(()=>status.textContent='',1800)}};
const loadDraft=()=>{if(!input)return;input.value=sessionStorage.getItem(draftKey())||'';resize();input.dispatchEvent(new Event('input',{bubbles:true}))};
if(input){input.setAttribute('rows','5');input.setAttribute('placeholder','شرح کامل پاسخ، اطلاعات تکمیلی و نتیجه مورد انتظار خود را بنویسید…');input.addEventListener('input',()=>{resize();saveDraft()});loadDraft()}
const hasDraft=Boolean(sessionStorage.getItem(`${baseKey}-reply`)||sessionStorage.getItem(`${baseKey}-note`));
if(submissionSucceeded){form?.reset();if(input){input.value='';resize()}setComposerOpen(false,false)}else setComposerOpen(hasDraft||replyResult==='error',false);
composerToggle?.addEventListener('click',()=>setComposerOpen(true));
workspace.querySelectorAll('[data-composer-close]').forEach(button=>button.addEventListener('click',()=>setComposerOpen(false,false)));
composer?.addEventListener('keydown',event=>{if(event.key==='Escape'){setComposerOpen(false,false);composerToggle?.focus()}});
const primarySubmit=form?.querySelector('[data-primary-submit]');
const guideToPrimarySubmit=event=>{event.preventDefault();event.stopPropagation();if(!primarySubmit)return;primarySubmit.scrollIntoView({behavior:'smooth',block:'center'});primarySubmit.classList.remove('submit-attention');void primarySubmit.offsetWidth;primarySubmit.classList.add('submit-attention');setTimeout(()=>primarySubmit.focus({preventScroll:true}),450)};
workspace.querySelectorAll('[data-scroll-to-submit]').forEach(control=>{control.addEventListener('click',guideToPrimarySubmit);control.addEventListener('keydown',event=>{if(event.key==='Enter'||event.key===' '){guideToPrimarySubmit(event)}})});
workspace.querySelectorAll('[data-composer-mode]').forEach(button=>button.addEventListener('click',()=>{saveDraft();mode=button.dataset.composerMode;loadDraft();setTimeout(()=>input?.focus(),0)}));
workspace.querySelector('[data-toggle-recorder]')?.addEventListener('click',()=>{const recorder=workspace.querySelector('[data-voice-recorder]');recorder.hidden=!recorder.hidden;if(!recorder.hidden)recorder.querySelector('[data-record]')?.focus()});
workspace.querySelector('[data-toggle-extra]')?.addEventListener('click',()=>{const extra=workspace.querySelector('[data-composer-extra]');extra.hidden=!extra.hidden});
form?.addEventListener('submit',()=>{form.dataset.submitting='true'});
window.addEventListener('pageshow',()=>{if(submissionSucceeded){form?.reset();if(input){input.value='';resize()}setComposerOpen(false,false)}});
const pollUrl=workspace.dataset.pollUrl;
const readUrl=workspace.dataset.readUrl;
const pollInterval=3000;
let pollController=null,pollRunning=false,pollGeneration=0,pollErrors=0,nextPollAt=0;
let readRunning=false;
const cookie=name=>document.cookie.split('; ').find(row=>row.startsWith(`${name}=`))?.split('=').slice(1).join('=')||'';
const acknowledgeVisibleMessages=async()=>{
if(!readUrl||readRunning||document.visibilityState!=='visible')return;
const messageIds=[...scroller.querySelectorAll('[data-message-id]')].map(item=>item.dataset.messageId).filter(Boolean);
if(!messageIds.length)return;
readRunning=true;
try{await fetch(readUrl,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-CSRFToken':decodeURIComponent(cookie('csrftoken'))},body:JSON.stringify({message_ids:messageIds})})}catch(error){console.error('Message read acknowledgement failed',error)}finally{readRunning=false}
};
acknowledgeVisibleMessages();
// Keep the staff/customer conversation synchronized even while another tab is
// active. Browsers may throttle background timers, so visibility is used only
// to trigger an immediate catch-up, never as a hard polling gate.
// navigator.onLine only reports the browser's network-interface heuristic.
// It can be false while this Django origin is still reachable (notably on
// local networks, installed PWAs and some mobile browsers). Let fetch be the
// source of truth and use the existing error backoff when the origin really
// is unavailable.
const canPoll=()=>Boolean(pollUrl);
const schedulePoll=()=>{const delay=pollErrors?Math.min(30000,pollInterval*(2**Math.min(pollErrors,3))):pollInterval;nextPollAt=Date.now()+delay};
const applyPollUpdate=data=>{
if(!data.changed)return;
const wasAtBottom=atBottom();
const fragment=document.createRange().createContextualFragment(data.html||'');
if(data.replace)scroller.querySelectorAll('[data-message],.date-divider,.conversation-empty').forEach(item=>item.remove());
else scroller.querySelectorAll('.conversation-empty').forEach(item=>item.remove());
scroller.insertBefore(fragment,conversationEnd);
workspace.dataset.pollVersion=data.version||'';workspace.dataset.pollCursor=data.cursor||'';
const count=workspace.querySelector('[data-conversation-count]');if(count)count.textContent=String(data.count??'');
workspace.querySelectorAll('[data-ticket-status]').forEach(item=>item.textContent=data.status||item.textContent);
groupDates();
acknowledgeVisibleMessages();
scroller.querySelectorAll('img:not([data-poll-bound]),audio:not([data-poll-bound])').forEach(media=>{media.dataset.pollBound='true';const event=media.tagName==='IMG'?'load':'loadedmetadata';media.addEventListener(event,()=>{if(wasAtBottom)scrollLatest(false)},{once:true})});
if(wasAtBottom){scrollLatest(true);jump.hidden=true}else jump.hidden=false;
};
const poll=async()=>{
if(!canPoll()||pollRunning)return;
const generation=++pollGeneration;pollRunning=true;const controller=new AbortController();pollController=controller;
try{
const url=new URL(pollUrl,location.origin);url.searchParams.set('version',workspace.dataset.pollVersion||'');url.searchParams.set('cursor',workspace.dataset.pollCursor||'');
const response=await fetch(url,{method:'GET',signal:controller.signal,cache:'no-store',headers:{Accept:'application/json'}});
if(response.redirected){location.assign(response.url);return}
if(!response.ok)throw new Error(`HTTP ${response.status}`);
applyPollUpdate(await response.json());pollErrors=0;
}catch(error){if(error.name!=='AbortError'){pollErrors+=1;console.error('Ticket polling failed',error)}}finally{if(generation===pollGeneration){pollRunning=false;pollController=null;schedulePoll()}}
};
const startPolling=()=>{if(!canPoll()||pollRunning||Date.now()<nextPollAt)return;poll()};
const stopPolling=()=>{pollGeneration+=1;if(pollController){pollController.abort();pollController=null}pollRunning=false;nextPollAt=0};
const restartPolling=()=>{stopPolling();startPolling()};
document.addEventListener('visibilitychange',()=>{if(document.visibilityState==='visible'){restartPolling();acknowledgeVisibleMessages()}});
window.addEventListener('focus',startPolling);
window.addEventListener('pageshow',restartPolling);
window.addEventListener('online',restartPolling);
// One independent heartbeat cannot be lost in the load/pageshow race that can
// cancel a recursively scheduled timeout. pollRunning prevents overlap and
// nextPollAt preserves the normal interval and network-error backoff.
const pollHeartbeat=setInterval(startPolling,1000);
window.addEventListener('beforeunload',()=>{clearInterval(pollHeartbeat);stopPolling()},{once:true});
startPolling();
const resetMessageMenu=menu=>{if(!menu)return;const editor=menu.querySelector('[data-message-editor]');const choices=menu.querySelector('[data-message-menu-choices]');const input=menu.querySelector('[data-message-edit-input]');if(editor)editor.hidden=true;if(choices)choices.hidden=false;if(input){input.value=input.dataset.originalValue||'';input.dispatchEvent(new Event('input',{bubbles:true}))}};
const closeMessageMenu=menu=>{if(!menu)return;menu.open=false;resetMessageMenu(menu)};
workspace.addEventListener('toggle',event=>{const menu=event.target.closest?.('[data-message-menu]');if(menu?.open)workspace.querySelectorAll('[data-message-menu][open]').forEach(other=>{if(other!==menu)closeMessageMenu(other)})},true);
workspace.addEventListener('click',event=>{const close=event.target.closest('[data-message-menu-close]');if(close){event.preventDefault();closeMessageMenu(close.closest('[data-message-menu]'));return}const edit=event.target.closest('[data-message-edit-open]');if(edit){const menu=edit.closest('[data-message-menu]');menu.querySelector('[data-message-menu-choices]').hidden=true;menu.querySelector('[data-message-editor]').hidden=false;const input=menu.querySelector('[data-message-edit-input]');input.focus();input.setSelectionRange(input.value.length,input.value.length);return}const back=event.target.closest('[data-message-edit-back]');if(back){event.preventDefault();resetMessageMenu(back.closest('[data-message-menu]'))}});
workspace.addEventListener('input',event=>{if(!event.target.matches('[data-message-edit-input]'))return;const count=event.target.closest('[data-message-editor]').querySelector('[data-message-edit-count]');if(count)count.textContent=`${event.target.value.length.toLocaleString('fa-IR')} / ۴۰۰۰`});
document.addEventListener('click',event=>{workspace.querySelectorAll('[data-message-menu][open]').forEach(menu=>{if(!menu.contains(event.target))closeMessageMenu(menu)})});
workspace.addEventListener('keydown',event=>{if(event.key==='Escape'){const menu=event.target.closest('[data-message-menu]')||workspace.querySelector('[data-message-menu][open]');if(menu){event.preventDefault();closeMessageMenu(menu);menu.querySelector(':scope > summary')?.focus()}}});
workspace.querySelectorAll('[data-toggle-panel]').forEach(button=>button.addEventListener('click',()=>{const panel=workspace.querySelector(`#${button.dataset.togglePanel}`);workspace.querySelectorAll('[data-workspace-panel]').forEach(item=>item.classList.toggle('panel-open',item===panel&&!item.classList.contains('panel-open')))}));
workspace.querySelectorAll('[data-close-panel]').forEach(button=>button.addEventListener('click',()=>button.closest('[data-workspace-panel]').classList.remove('panel-open')));
});
+1
View File
@@ -0,0 +1 @@
(()=>{const dialog=document.querySelector('[data-image-viewer]');if(!dialog)return;const image=dialog.querySelector('[data-image-preview]'),title=dialog.querySelector('[data-image-title]'),download=dialog.querySelector('[data-image-download]');document.addEventListener('click',event=>{const trigger=event.target.closest('[data-image-open]');if(!trigger)return;image.src=trigger.dataset.imageSrc;image.alt=trigger.dataset.imageName||'تصویر پیوست';title.textContent=trigger.dataset.imageName||'تصویر پیوست';download.href=trigger.dataset.imageSrc.replace('/view/','/download/');dialog.showModal()});dialog.querySelector('[data-image-close]').addEventListener('click',()=>dialog.close());dialog.addEventListener('click',event=>{if(event.target===dialog)dialog.close()});dialog.addEventListener('close',()=>image.removeAttribute('src'))})();
+38
View File
@@ -0,0 +1,38 @@
document.querySelectorAll('[data-location-picker]').forEach(async picker=>{
const province=picker.querySelector('[data-province-input]');
const city=picker.querySelector('[data-city-input]');
const provinceList=picker.querySelector('[data-province-options]')||(province?.matches('select')?province:null);
const cityList=picker.querySelector('[data-city-options]')||(city?.matches('select')?city:null);
const hint=picker.querySelector('[data-location-hint]');
if(!province||!city||!provinceList||!cityList)return;
const normalize=value=>(value||'').trim().replace(/ي/g,'ی').replace(/ك/g,'ک');
const setHint=(text,error=false)=>{if(!hint)return;hint.textContent=text;hint.classList.toggle('is-error',error)};
const fill=(list,values,placeholder='')=>{
const selected=normalize(list.value);
const options=values.map(value=>{const option=document.createElement('option');option.value=value;option.textContent=value;return option});
if(list.matches('select')){const empty=document.createElement('option');empty.value='';empty.textContent=placeholder;options.unshift(empty)}
list.replaceChildren(...options);
if(values.includes(selected))list.value=selected;
};
try{
const response=await fetch(picker.dataset.locationsUrl,{cache:'force-cache'});
if(!response.ok)throw new Error('location data unavailable');
const rows=await response.json();
const locations=new Map(rows.map(row=>[normalize(row.province),row.cities]));
fill(provinceList,rows.map(row=>row.province),'انتخاب استان');
const syncCities=(clearInvalid=false)=>{
const cities=locations.get(normalize(province.value))||[];
fill(cityList,cities,'انتخاب شهر');
city.disabled=!cities.length;
if(clearInvalid&&city.value&&!cities.includes(normalize(city.value)))city.value='';
setHint(cities.length?`${cities.length.toLocaleString('fa-IR')} شهر برای این استان در دسترس است.`:'برای نمایش شهرها، یک استان معتبر انتخاب کنید.',Boolean(province.value&&!cities.length));
};
province.addEventListener('input',()=>syncCities(true));
province.addEventListener('change',()=>syncCities(true));
city.addEventListener('change',()=>{const cities=locations.get(normalize(province.value))||[];setHint(!city.value||cities.includes(normalize(city.value))?'موقعیت انتخابی برای همین تیکت استفاده می‌شود.':'شهر را از فهرست همین استان انتخاب کنید.',Boolean(city.value&&!cities.includes(normalize(city.value))))});
syncCities(false);
}catch(error){
province.disabled=true;city.disabled=true;setHint('فهرست شهرها بارگذاری نشد؛ صفحه را دوباره باز کنید.',true);
}
});
+15
View File
@@ -0,0 +1,15 @@
let deferredInstallPrompt=null;
const banner=document.querySelector('[data-pwa-install]'),accept=banner?.querySelector('[data-pwa-accept]'),help=banner?.querySelector('[data-pwa-help]');
const standalone=matchMedia('(display-mode: standalone)').matches||navigator.standalone===true;
const mobileDevice=navigator.userAgentData?.mobile===true||/android|iphone|ipad|ipod|mobile/i.test(navigator.userAgent)||(matchMedia('(max-width: 820px)').matches&&matchMedia('(pointer: coarse)').matches);
const isiOS=/iphone|ipad|ipod/i.test(navigator.userAgent);
const dismissed=()=>Date.now()-Number(localStorage.getItem('pwa-install-dismissed')||0)<24*60*60*1000;
const show=()=>{if(banner&&mobileDevice&&!standalone&&!dismissed())banner.hidden=false};
const setGuide=(text,label='راهنمای نصب')=>{if(help)help.textContent=text;if(accept)accept.textContent=label;banner?.classList.add('pwa-install-guidance')};
if('serviceWorker' in navigator&&window.isSecureContext){let workerRegistration=null,workerReloading=false;const assetVersion=document.documentElement.dataset.staticVersion||new URL(document.currentScript?.src||location.href).searchParams.get('v')||'';const serviceWorkerUrl=`/service-worker.js?v=${encodeURIComponent(assetVersion)}`;const updateWorker=()=>{if(workerRegistration&&document.visibilityState==='visible')workerRegistration.update().catch(()=>{})};navigator.serviceWorker.addEventListener('controllerchange',()=>{if(workerReloading)return;workerReloading=true;location.reload()});window.addEventListener('load',async()=>{try{workerRegistration=await navigator.serviceWorker.register(serviceWorkerUrl,{updateViaCache:'none'});await workerRegistration.update()}catch(error){setGuide('فعال‌سازی نصب برنامه با خطا روبه‌رو شد. صفحه را تازه‌سازی کنید.');show()}});document.addEventListener('visibilitychange',updateWorker);setInterval(updateWorker,60000)}
window.addEventListener('beforeinstallprompt',event=>{event.preventDefault();deferredInstallPrompt=event;if(accept){accept.textContent='نصب برنامه';accept.disabled=false}banner?.classList.remove('pwa-install-guidance');if(help)help.textContent='برنامه آماده نصب است؛ برای ادامه روی «نصب برنامه» بزنید.';show()});
if(mobileDevice&&isiOS&&!standalone){setGuide('در Safari روی دکمه اشتراک‌گذاری (□↑) بزنید و «Add to Home Screen» را انتخاب کنید.','نمایش راهنما');setTimeout(show,700)}
if(mobileDevice&&!isiOS&&!standalone)setTimeout(()=>{if(!deferredInstallPrompt){setGuide(window.isSecureContext?'از منوی مرورگر گزینه «Install app» یا «افزودن به صفحه اصلی» را انتخاب کنید.':'نصب مستقیم روی آدرس HTTP شبکه ممکن نیست. سامانه را با HTTPS باز کنید؛ سپس دکمه نصب فعال می‌شود.','راهنمای نصب');show()}},1800);
banner?.querySelector('[data-pwa-dismiss]')?.addEventListener('click',()=>{banner.hidden=true;localStorage.setItem('pwa-install-dismissed',Date.now())});
accept?.addEventListener('click',async()=>{if(deferredInstallPrompt){accept.disabled=true;deferredInstallPrompt.prompt();const {outcome}=await deferredInstallPrompt.userChoice;deferredInstallPrompt=null;if(outcome==='accepted')banner.hidden=true;else{accept.disabled=false;setGuide('نصب لغو شد. برای تلاش دوباره از منوی مرورگر «Install app» را انتخاب کنید.')}}else if(isiOS){setGuide('۱) Safari را باز کنید. ۲) دکمه اشتراک‌گذاری □↑ را بزنید. ۳) Add to Home Screen و سپس Add را انتخاب کنید.','متوجه شدم')}else if(!window.isSecureContext){setGuide('مرورگر برای نصب و Service Worker به HTTPS نیاز دارد. از نسخه HTTPS سامانه استفاده کنید.','نیازمند HTTPS')}else{setGuide('منوی سه‌نقطه مرورگر را باز کنید و «Install app» یا «افزودن به صفحه اصلی» را بزنید.','نصب از منوی مرورگر')}});
window.addEventListener('appinstalled',()=>{deferredInstallPrompt=null;localStorage.removeItem('pwa-install-dismissed');if(banner)banner.hidden=true});
+21
View File
@@ -0,0 +1,21 @@
document.addEventListener('DOMContentLoaded',()=>{
const root=document.querySelector('[data-customer-picker]');if(!root)return;
const search=root.querySelector('[data-customer-search]'),results=root.querySelector('[data-customer-results]'),status=root.querySelector('[data-customer-status]');
const idInput=root.querySelector('[data-customer-id]'),mobile=root.querySelector('#id_customer_mobile'),first=root.querySelector('#id_first_name'),last=root.querySelector('#id_last_name'),province=root.querySelector('#id_province'),city=root.querySelector('#id_city');
const selected=root.querySelector('[data-selected-customer]');let timer,requestToken=0;
const identityRows=[first?.closest('[data-new-customer-field]'),last?.closest('[data-new-customer-field]')].filter(Boolean);
const summaryCustomer=root.querySelector('[data-summary-customer]'),summarySubject=root.querySelector('[data-summary-subject]'),summaryCategory=root.querySelector('[data-summary-category]'),subject=root.querySelector('#id_subject'),category=root.querySelector('#id_category');
const escapeHtml=value=>String(value??'').replace(/[&<>'"]/g,char=>({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[char]));
function setNewCustomer(isNew){identityRows.forEach(row=>row.hidden=!isNew);status.className=`customer-lookup-status ${isNew?'is-new':'is-found'}`;status.textContent=isNew?'این شماره در سامانه ثبت نشده است؛ نام و نام خانوادگی مشتری جدید را تکمیل کنید.':'مشتری موجود انتخاب شد؛ مشخصات ثبت‌شده در بالا نمایش داده شده است.'}
function selectCustomer(customer){idInput.value=customer.id;mobile.value=customer.mobile;first.value=customer.first_name;last.value=customer.last_name;province.value=customer.province;city.value=customer.city;selected.hidden=false;selected.querySelector('[data-selected-name]').textContent=customer.name;selected.querySelector('[data-selected-mobile]').textContent=customer.mobile;selected.querySelector('[data-selected-location]').textContent=[customer.city,customer.province].filter(Boolean).join('، ')||'موقعیت ثبت نشده';selected.querySelector('[data-selected-stats]').textContent=`${customer.ticket_count} تیکت، ${customer.active_count} فعال`;summaryCustomer.textContent=customer.name;results.hidden=true;search.value='';setNewCustomer(false);province.dispatchEvent(new Event('input',{bubbles:true}))}
function clearCustomer(clearMobile=true){idInput.value='';selected.hidden=true;identityRows.forEach(row=>row.hidden=false);if(clearMobile)mobile.value='';first.value='';last.value='';province.value='';city.value='';summaryCustomer.textContent='هنوز انتخاب نشده';status.className='customer-lookup-status';status.textContent='شماره موبایل را وارد کنید تا عضویت مشتری بررسی شود.'}
async function lookup(params,showList=false){const token=++requestToken;try{const response=await fetch(`${root.dataset.searchUrl}?${params}`,{headers:{'Accept':'application/json'}});if(!response.ok)throw new Error();const data=await response.json();if(token!==requestToken)return;if(showList){results.innerHTML=data.results.length?data.results.map(item=>`<button type="button" data-customer-result='${escapeHtml(JSON.stringify(item))}'><b>${escapeHtml(item.name)}</b><span dir="ltr">${escapeHtml(item.mobile)}</span><small>${escapeHtml([item.city,item.province].filter(Boolean).join('، ')||'موقعیت ثبت نشده')} · ${item.ticket_count} تیکت</small></button>`).join(''):'<p>مشتری‌ای با این عبارت پیدا نشد.</p>';results.hidden=false}else if(data.results.length&&data.results[0].mobile.replace(/\D/g,'')===mobile.value.replace(/\D/g,'').replace(/^98(?=9)/,'0'))selectCustomer(data.results[0]);else{if(idInput.value)clearCustomer(false);setNewCustomer(true)}}catch{status.className='customer-lookup-status is-error';status.textContent='بررسی مشتری ممکن نشد؛ اتصال را بررسی و دوباره تلاش کنید.'}}
search.addEventListener('input',()=>{clearTimeout(timer);const value=search.value.trim();if(value.length<2){results.hidden=true;return}timer=setTimeout(()=>lookup(`q=${encodeURIComponent(value)}`,true),300)});
results.addEventListener('click',event=>{const button=event.target.closest('[data-customer-result]');if(button)selectCustomer(JSON.parse(button.dataset.customerResult))});
root.querySelector('[data-clear-customer]').addEventListener('click',()=>{clearCustomer();search.focus()});
mobile.addEventListener('input',()=>{if(idInput.value&&mobile.value!==selected.querySelector('[data-selected-mobile]').textContent)clearCustomer(false);clearTimeout(timer);const digits=mobile.value.replace(/\D/g,'');if(digits.length<10){status.className='customer-lookup-status';status.textContent='شماره موبایل را کامل وارد کنید.';return}status.textContent='در حال بررسی شماره…';timer=setTimeout(()=>lookup(`q=${encodeURIComponent(mobile.value)}`),350)});
if(idInput.value)lookup(`id=${encodeURIComponent(idInput.value)}`);else if(mobile.value)mobile.dispatchEvent(new Event('input'));
subject?.addEventListener('input',()=>summarySubject.textContent=subject.value.trim()||'هنوز وارد نشده');
category?.addEventListener('change',()=>summaryCategory.textContent=category.selectedOptions[0]?.text||'انتخاب نشده');
if(subject?.value)summarySubject.textContent=subject.value;if(category?.value)summaryCategory.textContent=category.selectedOptions[0]?.text;
});
+20
View File
@@ -0,0 +1,20 @@
(() => {
const form=document.querySelector('[data-ticket-search-url]'); if(!form)return;
const input=form.querySelector('[data-ticket-search]'); const results=form.querySelector('[data-ticket-search-results]');
const unit=form.querySelector('[data-ticket-unit]'); const category=form.querySelector('[data-ticket-category]'); let timer;
const message=text=>{results.replaceChildren(); const p=document.createElement('p'); p.className='intent-message'; p.textContent=text; results.append(p)};
const select=async item=>{
unit.value=String(item.unit_id);
const loaded=new Promise(resolve=>category.addEventListener('ticket-options-loaded',resolve,{once:true}));
unit.dispatchEvent(new Event('change',{bubbles:true})); await loaded;
category.value=String(item.category_id); category.dispatchEvent(new Event('change',{bubbles:true}));
document.querySelector('.manual-routing')?.setAttribute('open',''); message(`مسیر انتخاب شد: ${item.unit} ← ${item.category}`); category.focus();
};
const render=items=>{
results.replaceChildren(); if(!items.length){message('نتیجه دقیقی پیدا نشد؛ از انتخاب دستی استفاده کنید.');return}
items.forEach(item=>{const button=document.createElement('button');button.type='button';button.className='intent-result';
const title=document.createElement('strong');title.textContent=item.category;const meta=document.createElement('span');meta.textContent=item.unit;
const detail=document.createElement('small');detail.textContent=item.description||'انتخاب این مسیر برای درخواست';button.append(title,meta,detail);button.addEventListener('click',()=>select(item));results.append(button)});
};
input.addEventListener('input',()=>{clearTimeout(timer);const q=input.value.trim();if(q.length<2){results.replaceChildren();return}message('در حال یافتن بهترین مسیر…');timer=setTimeout(async()=>{try{const response=await fetch(`${form.dataset.ticketSearchUrl}?q=${encodeURIComponent(q)}`,{headers:{Accept:'application/json'}});render((await response.json()).results)}catch{message('جست‌وجو در دسترس نیست؛ از انتخاب دستی استفاده کنید.')}},260)});
})();
+62
View File
@@ -0,0 +1,62 @@
(() => {
const form = document.querySelector("[data-unit-options-url]");
if (!form) return;
const unit = form.querySelector("[data-ticket-unit]");
const category = form.querySelector("[data-ticket-category]");
const picker = form.querySelector("[data-expert-picker]");
if (!unit || !category || !picker) return;
let requestController;
const addGeneralQueue = (queue) => {
const label = document.createElement("label"); label.className = "expert-card";
label.dataset.generalQueue = ""; label.dataset.unitId = String(queue.unit_id);
const radio = document.createElement("input"); radio.type = "radio"; radio.name = "selected_expert"; radio.value = ""; radio.checked = true;
const avatar = document.createElement("span"); avatar.className = "expert-avatar"; avatar.textContent = "⌁";
const title = document.createElement("strong"); title.textContent = queue.label;
const detail = document.createElement("small"); detail.textContent = "اولین کارشناس آزاد همین واحد";
label.append(radio, avatar, title, detail); picker.append(label);
};
const render = (payload) => {
category.replaceChildren(new Option("انتخاب دسته‌بندی", ""));
payload.categories.forEach((item) => category.add(new Option(item.label, item.id)));
const selectedUnitLabel=unit.options[unit.selectedIndex]?.textContent?.trim() || "واحد";
const queue=payload.queue || {unit_id:unit.value,label:`صف عمومی ${selectedUnitLabel}`};
picker.replaceChildren(); addGeneralQueue(queue);
payload.experts.forEach((item) => {
const label=document.createElement("label"); label.className="expert-card";
const radio=document.createElement("input"); radio.type="radio"; radio.name="selected_expert"; radio.value=item.id;
const image=document.createElement("img"); image.src=item.avatar_url; image.alt=`تصویر ${item.name}`; image.width=56; image.height=56; image.loading="lazy";
const title=document.createElement("strong"); title.textContent=item.name;
const detail=document.createElement("small"); detail.textContent=item.job_title;
label.append(radio,image,title,detail); picker.append(label);
});
if (!payload.experts.length) {
const empty=document.createElement("p"); empty.className="muted expert-empty";
empty.textContent="برای این واحد کارشناس قابل انتخابی ثبت نشده است؛ درخواست به صف عمومی می‌رود.";
picker.append(empty);
}
};
unit.addEventListener("change", async () => {
requestController?.abort(); requestController=new AbortController();
const requestedUnit=unit.value;
category.disabled=true;
try {
const optionsUrl=new URL(form.dataset.unitOptionsUrl,window.location.origin);
optionsUrl.searchParams.set("unit",requestedUnit);
optionsUrl.searchParams.set("v",document.documentElement.dataset.staticVersion || "1");
const response=await fetch(optionsUrl, {headers:{Accept:"application/json"},credentials:"same-origin",cache:"no-store",signal:requestController.signal});
if (!response.ok) throw new Error("options request failed");
const payload=await response.json();
if (unit.value!==requestedUnit) return;
render(payload);
category.dispatchEvent(new CustomEvent("ticket-options-loaded",{detail:{ok:true,unitId:requestedUnit}}));
} catch (error) {
if (error.name==="AbortError") return;
console.error("Failed to update ticket unit options", error);
picker.replaceChildren();
const message=document.createElement("p"); message.className="muted expert-empty"; message.setAttribute("role","alert");
message.textContent="دریافت کارشناسان این واحد ناموفق بود؛ لطفاً دوباره تلاش کنید."; picker.append(message);
category.dispatchEvent(new CustomEvent("ticket-options-loaded",{detail:{ok:false,unitId:requestedUnit}}));
} finally { if (unit.value===requestedUnit) category.disabled=false; }
});
})();
+8
View File
@@ -0,0 +1,8 @@
document.addEventListener('submit',event=>{
const form=event.target;if(!form.matches('form'))return;
requestAnimationFrame(()=>{if(!form.checkValidity())return;form.querySelectorAll('button[type="submit"],button:not([type])').forEach(button=>{button.disabled=true;button.setAttribute('aria-busy','true');if(!button.dataset.label)button.dataset.label=button.textContent;button.textContent='در حال ثبت…'})});
});
document.querySelectorAll('.flash').forEach(flash=>{
const close=document.createElement('button');close.type='button';close.className='flash-close';close.setAttribute('aria-label','بستن پیام');close.textContent='×';close.addEventListener('click',()=>flash.remove());flash.appendChild(close);
if(flash.classList.contains('success'))setTimeout(()=>{flash.classList.add('flash-leaving');setTimeout(()=>flash.remove(),250)},7000);
});
+12
View File
@@ -0,0 +1,12 @@
document.querySelectorAll('[data-voice-recorder]').forEach(root=>{
let recorder,stream,chunks=[],started,timer,pausedAt=0,pausedMs=0,voiceFile;
const form=root.closest('form'),record=root.querySelector('[data-record]'),pause=root.querySelector('[data-pause]'),stop=root.querySelector('[data-stop]'),remove=root.querySelector('[data-delete]'),audio=root.querySelector('audio'),clock=root.querySelector('[data-timer]');
const supported=window.isSecureContext&&navigator.mediaDevices?.getUserMedia&&window.MediaRecorder;
if(!supported){record.disabled=true;record.title='ضبط صدا فقط در HTTPS یا localhost و مرورگر سازگار فعال است';root.insertAdjacentHTML('beforeend','<small class="recorder-error">مرورگر یا اتصال فعلی امکان ضبط امن صدا را ندارد.</small>');return}
const stopTracks=()=>{stream?.getTracks().forEach(track=>track.stop());stream=null};
const reset=()=>{if(voiceFile)form.dispatchEvent(new CustomEvent('voice-removed',{detail:voiceFile}));voiceFile=null;stopTracks();if(audio.src)URL.revokeObjectURL(audio.src);audio.removeAttribute('src');audio.hidden=true;remove.hidden=true;clock.textContent='00:00';record.disabled=false;pause.disabled=true;pause.textContent='مکث';stop.disabled=true};
record.addEventListener('click',async()=>{try{stream=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:true,noiseSuppression:true,autoGainControl:true}});const mime=['audio/webm;codecs=opus','audio/mp4','audio/ogg;codecs=opus','audio/webm'].find(type=>MediaRecorder.isTypeSupported(type));recorder=new MediaRecorder(stream,mime?{mimeType:mime}:undefined);chunks=[];pausedMs=0;recorder.ondataavailable=event=>{if(event.data.size)chunks.push(event.data)};recorder.onerror=()=>{stopTracks();alert('ضبط صدا متوقف شد. دوباره تلاش کنید.')};recorder.onstop=()=>{clearInterval(timer);stopTracks();const type=recorder.mimeType.split(';')[0]||'audio/webm',blob=new Blob(chunks,{type});if(!blob.size)return reset();audio.src=URL.createObjectURL(blob);audio.hidden=false;remove.hidden=false;const ext=type.includes('ogg')?'ogg':type.includes('mp4')?'m4a':'webm';voiceFile=new File([blob],`voice-${Date.now()}.${ext}`,{type});form.dispatchEvent(new CustomEvent('voice-added',{detail:voiceFile}))};recorder.start(1000);started=Date.now();record.disabled=true;pause.disabled=false;stop.disabled=false;timer=setInterval(()=>{const elapsed=Date.now()-started-pausedMs-(recorder.state==='paused'?Date.now()-pausedAt:0),seconds=Math.max(0,Math.floor(elapsed/1000));clock.textContent=`${String(Math.floor(seconds/60)).padStart(2,'0')}:${String(seconds%60).padStart(2,'0')}`},500)}catch(error){stopTracks();const denied=error.name==='NotAllowedError';alert(denied?'دسترسی میکروفن رد شده است. از تنظیمات مرورگر، دسترسی Microphone را برای این سایت فعال کنید.':'میکروفن در دسترس نیست یا توسط برنامه دیگری استفاده می‌شود.')}});
pause.addEventListener('click',()=>{if(recorder?.state==='recording'){recorder.pause();pausedAt=Date.now();pause.textContent='ادامه ضبط'}else if(recorder?.state==='paused'){pausedMs+=Date.now()-pausedAt;recorder.resume();pause.textContent='مکث'}});
stop.addEventListener('click',()=>{if(recorder&&recorder.state!=='inactive')recorder.stop();pause.disabled=true;stop.disabled=true});
remove.addEventListener('click',reset);window.addEventListener('pagehide',stopTracks);
});
+16
View File
@@ -0,0 +1,16 @@
document.addEventListener('DOMContentLoaded', async () => {
if (!('OTPCredential' in window) || !window.isSecureContext) return;
const form = document.querySelector('[data-webotp-form]');
const input = form?.querySelector('[data-webotp]');
if (!form || !input) return;
const controller = new AbortController();
form.addEventListener('submit', () => controller.abort(), { once: true });
try {
const credential = await navigator.credentials.get({ otp: { transport: ['sms'] }, signal: controller.signal });
if (!credential?.code) return;
input.value = credential.code;
form.requestSubmit();
} catch (error) {
if (error.name !== 'AbortError') console.debug('WebOTP unavailable', error);
}
});
+1
View File
@@ -0,0 +1 @@
{"id":"/","name":"گفت‌وگو با واحد فروش","short_name":"واحد فروش","description":"ثبت و پیگیری درخواست‌های فروش لوله گستر گلپایگان","start_url":"/tickets/","scope":"/","display":"standalone","background_color":"#eeeeee","theme_color":"#08376b","lang":"fa","dir":"rtl","icons":[{"src":"/static/images/pwa-icon.png","sizes":"1024x1024","type":"image/png","purpose":"any maskable"}]}
+134
View File
@@ -0,0 +1,134 @@
@import "tailwindcss";
@source "../../templates/**/*.html";
@source "../js/**/*.js";
@font-face{font-family:Vazirmatn;src:url("../fonts/vazirmatn-arabic-wght-normal.woff2") format("woff2-variations");font-weight:100 900;font-display:swap}@font-face{font-family:Vazirmatn;src:url("../fonts/vazirmatn-latin-wght-normal.woff2") format("woff2-variations");font-weight:100 900;font-display:swap}
@theme{--font-sans:Vazirmatn,ui-sans-serif,system-ui;--color-ink:#08376b;--color-ink-soft:#0b4c8c;--color-cream:#eeeeee;--color-soft:#eaeaea;--color-paper:#ffffff;--color-sea:#0693e3;--color-sea-dark:#1977ce;--color-blue:#1977ce;--color-mint:#e5f4ff;--color-coral:#fa9f00;--color-sun:#ffc451;--shadow-panel:0 18px 55px -35px rgba(8,55,107,.35);--shadow-lift:0 22px 55px -28px rgba(6,147,227,.42)}
:root{--color-ink:#08376b;--color-ink-soft:#0b4c8c;--color-cream:#eeeeee;--color-soft:#eaeaea;--color-paper:#ffffff;--color-sea:#0693e3;--color-sea-dark:#1977ce;--color-blue:#1977ce;--color-mint:#e5f4ff;--color-coral:#fa9f00;--color-sun:#ffc451;--theme-thread:#eaeaea;--theme-own-message:#dcefff;--theme-note:#fff1d5;--shadow-panel:0 18px 55px -35px rgba(8,55,107,.35);--shadow-lift:0 22px 55px -28px rgba(6,147,227,.42)}
@layer base{*{@apply box-border}html{@apply scroll-smooth}body{@apply m-0 min-h-screen bg-cream font-sans text-ink antialiased}button,a,input,textarea,select{@apply focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-sea/20}a{@apply transition}h1{@apply text-[1.7rem] font-black leading-tight tracking-tight sm:text-4xl}h2{@apply text-xl font-extrabold leading-tight}h3{@apply text-base font-extrabold}p{@apply leading-7}label{@apply mb-2 block text-sm font-bold}input:not([type=checkbox]):not([type=radio]),textarea,select{@apply w-full rounded-2xl border border-ink/10 bg-white px-4 py-3 text-base shadow-sm transition placeholder:text-slate-400 hover:border-sea/30 focus:border-sea focus:ring-4 focus:ring-sea/10 sm:text-sm}textarea{@apply min-h-36 resize-y}button,.button{@apply inline-flex min-h-12 items-center justify-center gap-2 rounded-2xl bg-ink px-5 py-3 text-sm font-extrabold text-white shadow-sm transition hover:-translate-y-0.5 hover:bg-sea-dark hover:shadow-lift disabled:pointer-events-none disabled:opacity-50}form p{@apply mb-5}.errorlist{@apply mb-2 list-none rounded-xl bg-red-50 px-3 py-2 text-xs font-bold text-red-700}}
@layer components{
.site-header{@apply sticky top-0 z-40 border-b border-ink/5 bg-cream/90 backdrop-blur-xl}.header-inner{@apply mx-auto flex h-17 max-w-7xl items-center justify-between px-4 sm:px-7}.logo{@apply flex items-center gap-3 text-ink}.logo-mark{@apply grid size-10 place-items-center rounded-[14px] bg-ink text-lg font-black text-white}.logo-copy{@apply font-black}.logo-copy small{@apply block text-[9px] font-medium tracking-wide text-ink/50}.desktop-nav{@apply hidden items-center gap-1 sm:flex}.desktop-nav a{@apply rounded-xl px-3 py-2 text-sm font-bold text-ink/65 hover:bg-white hover:text-sea}.desktop-nav .logout{@apply text-coral}.customer-main{@apply mx-auto w-full max-w-6xl px-4 pb-28 pt-6 sm:px-7 sm:pb-12 sm:pt-10}.mobile-dock{@apply fixed inset-x-3 bottom-3 z-50 grid grid-cols-3 rounded-[22px] border border-white/80 bg-ink/95 p-1.5 shadow-2xl backdrop-blur-xl sm:hidden}.mobile-dock a{@apply flex min-h-12 flex-col items-center justify-center gap-0.5 rounded-2xl text-[10px] font-bold text-white/60}.mobile-dock a.primary{@apply bg-sea text-white}.dock-icon{@apply text-base}
.staff-shell{@apply min-h-screen lg:grid lg:grid-cols-[250px_1fr]}.staff-sidebar{@apply hidden bg-ink p-5 text-white lg:flex lg:min-h-screen lg:flex-col lg:justify-between}.staff-brand{@apply mb-10 flex items-center gap-3}.staff-brand .logo-mark{@apply bg-sea}.staff-brand small{@apply block text-xs text-white/45}.staff-menu{@apply grid gap-1.5}.staff-menu a{@apply flex items-center gap-3 rounded-2xl px-4 py-3 text-sm font-bold text-white/60 hover:bg-white/8 hover:text-white}.staff-menu a.active{@apply bg-sea text-white}.staff-profile{@apply rounded-2xl bg-white/7 p-4}.staff-profile strong{@apply block text-sm}.staff-profile span{@apply text-xs text-white/45}.staff-main{@apply min-w-0}.staff-topbar{@apply sticky top-0 z-30 flex h-17 items-center justify-between border-b border-ink/5 bg-cream/90 px-4 backdrop-blur-xl sm:px-7}.staff-topbar h2{@apply text-base}.staff-topbar-actions{@apply flex items-center gap-2}.staff-topbar a{@apply rounded-xl px-3 py-2 text-xs font-bold text-ink/60 hover:bg-white}.staff-content{@apply mx-auto max-w-[1500px] px-4 pb-24 pt-6 sm:px-7 lg:pb-10}.staff-mobile-dock{@apply fixed inset-x-3 bottom-3 z-50 grid grid-cols-3 rounded-[22px] bg-ink p-1.5 text-white shadow-2xl lg:hidden}.staff-mobile-dock a{@apply flex min-h-12 flex-col items-center justify-center text-[10px] font-bold text-white/60}.staff-mobile-dock a.active{@apply rounded-2xl bg-sea text-white}
.page-kicker{@apply mb-2 text-xs font-black tracking-wider text-sea}.page-head{@apply mb-6 flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between}.page-head p{@apply mt-2 max-w-xl text-sm text-ink/55}.back-link{@apply inline-flex items-center gap-2 text-xs font-extrabold text-sea}.card{@apply rounded-[26px] border border-ink/7 bg-paper p-5 shadow-panel sm:p-6}.button.secondary,button.secondary{@apply border border-ink/10 bg-paper text-ink shadow-none hover:border-sea/30 hover:bg-mint}.button.coral,button.coral{@apply bg-coral}.muted{@apply text-sm text-ink/50}.flash{@apply mb-5 rounded-2xl border border-sea/15 bg-mint px-4 py-3 text-sm font-bold text-sea-dark}.flash.error{@apply border-red-200 bg-red-50 text-red-700}.flash.success{@apply border-emerald-200 bg-emerald-50 text-emerald-800}
.hero-panel{@apply relative mb-7 overflow-hidden rounded-[30px] bg-ink px-5 py-7 text-white sm:px-8 sm:py-9}.hero-panel:after{@apply absolute -left-14 -top-20 size-52 rounded-full bg-sea/45 content-['']}.hero-panel>*{@apply relative z-10}.hero-panel .page-kicker{@apply text-mint}.hero-panel h1{@apply max-w-xl}.hero-panel p{@apply mt-3 max-w-lg text-sm text-white/55}.hero-actions{@apply mt-6 flex flex-col gap-2 sm:flex-row sm:flex-wrap}.hero-panel .hero-actions .button{@apply mt-0 shadow-none hover:shadow-none}.hero-panel .hero-history-button{@apply border border-white/25 bg-white/10 text-white backdrop-blur-sm hover:border-white/45 hover:bg-white/20}.hero-panel .hero-history-button span{@apply text-lg leading-none}.page-head#recent-requests{@apply scroll-mt-24}
.ticket-grid{@apply grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3}.ticket-card{@apply relative flex min-h-48 flex-col justify-between overflow-hidden rounded-[24px] border border-ink/7 bg-paper p-5 text-ink shadow-panel transition hover:-translate-y-1 hover:border-sea/25 hover:shadow-lift}.ticket-card:before{@apply absolute inset-y-0 right-0 w-1 bg-sea/0 transition content-['']}.ticket-card:hover:before{@apply bg-sea}.ticket-card-top{@apply flex items-start justify-between gap-3}.ticket-number{@apply font-mono text-[11px] font-bold tracking-wide text-ink/40}.ticket-card h2{@apply mt-4 line-clamp-2 text-lg}.ticket-meta{@apply mt-5 flex items-end justify-between gap-3 border-t border-ink/6 pt-4}.ticket-meta small{@apply block text-[11px] text-ink/45}.expert-line{@apply mt-1 text-xs font-bold text-ink/70}.badge{@apply inline-flex w-fit items-center gap-1.5 rounded-full bg-mint px-3 py-1 text-[11px] font-extrabold text-sea-dark}.badge:before{@apply size-1.5 rounded-full bg-sea content-['']}.priority-urgent{@apply bg-red-50 text-red-700}.priority-urgent:before{@apply bg-red-500}.priority-important{@apply bg-amber-50 text-amber-800}.priority-important:before{@apply bg-amber-500}.empty{@apply col-span-full rounded-[28px] border border-dashed border-ink/15 bg-paper/60 px-5 py-16 text-center}.empty-icon{@apply mx-auto mb-4 grid size-14 place-items-center rounded-full bg-mint text-2xl}.empty h2{@apply mb-2}.empty .button{@apply mt-5}
.request-layout{@apply grid gap-5 lg:grid-cols-[minmax(0,1fr)_300px]}.request-form{@apply order-2 lg:order-1}.request-aside{@apply order-1 lg:order-2}.step-title{@apply mb-5 flex items-center gap-3 border-b border-ink/6 pb-4}.step-number{@apply grid size-8 shrink-0 place-items-center rounded-full bg-ink text-xs font-black text-white}.field{@apply mb-5}.expert-picker{@apply mb-7 grid grid-cols-2 gap-2 border-0 p-0 sm:grid-cols-3}.expert-picker legend{@apply col-span-full mb-3 text-sm font-extrabold}.expert-card{@apply relative flex min-h-36 cursor-pointer flex-col items-center justify-center rounded-[20px] border-2 border-ink/8 bg-white p-3 text-center transition hover:border-sea/30}.expert-card:has(input:checked){@apply border-sea bg-mint shadow-sm}.expert-card input{@apply absolute opacity-0}.expert-card img,.expert-avatar{@apply mb-2 grid size-14 place-items-center rounded-full bg-cream object-cover text-xl font-black text-sea}.expert-card strong{@apply text-xs}.expert-card small{@apply mt-1 text-[10px] text-ink/45}.expert-empty{@apply col-span-full}.upload-zone{@apply my-5 rounded-[22px] border-2 border-dashed border-ink/15 bg-cream/60 p-5 text-center transition hover:border-sea/40}.upload-zone>label{@apply cursor-pointer text-sm text-sea}.file-preview{@apply mt-3 grid grid-cols-2 gap-2 sm:grid-cols-3}.file-chip{@apply relative overflow-hidden rounded-xl border border-ink/8 bg-white p-2}.file-chip img{@apply h-24 w-full rounded-lg object-cover}.file-chip button{@apply absolute left-1 top-1 min-h-0 rounded-lg bg-coral px-2 py-0.5}.voice-recorder,.voice{@apply my-4 rounded-[22px] border border-sea/15 bg-mint/65 p-4}.voice-head,.voice-actions,.voice{@apply flex flex-wrap items-center gap-2}.voice-head{@apply justify-between}.voice-actions{@apply mt-3}.voice-actions button,.voice button{@apply min-h-10 rounded-xl px-3 py-2 text-xs}.ghost{@apply border border-coral/20 bg-white text-coral}.submit-ticket{@apply w-full bg-sea text-base}.help-card{@apply rounded-[26px] bg-ink p-6 text-white}.help-card h3{@apply text-white}.help-list{@apply mt-5 grid gap-4}.help-item{@apply flex gap-3 text-sm text-white/60}.help-item b{@apply grid size-7 shrink-0 place-items-center rounded-full bg-white/10 text-xs text-white}
.conversation-shell{@apply grid gap-4 lg:grid-cols-[minmax(0,1fr)_280px]}.conversation-column{@apply min-w-0}.conversation{@apply flex max-h-[62vh] min-h-72 flex-col gap-3 overflow-y-auto rounded-[26px] bg-[#e9e5dc] p-3 sm:p-5}.message{@apply w-fit max-w-[92%] rounded-[20px] rounded-tr-md bg-paper px-4 py-3 shadow-sm sm:max-w-[78%]}.message.mine{@apply mr-auto rounded-tr-[20px] rounded-tl-md bg-[#cfeee7]}.message.note{@apply max-w-full rounded-[20px] border border-dashed border-amber-400 bg-[#fff3ce]}.message header{@apply mb-1 flex justify-between gap-6 text-[10px]}.message header b{@apply text-ink/65}.message time{@apply text-ink/35}.message p{@apply break-words text-sm leading-7}.attachment{@apply mt-2 flex rounded-xl bg-white/70 px-3 py-2 text-xs font-bold text-sea}.message-actions{@apply mt-2 flex justify-end gap-2 text-[10px]}.message-actions details{@apply m-0}.composer{@apply mt-3 rounded-[26px] border border-ink/7 bg-paper p-4 shadow-panel sm:p-5}.composer textarea{@apply min-h-24 border-0 bg-cream/70 shadow-none}.mode{@apply mb-4 grid grid-cols-2 gap-1 rounded-2xl bg-cream p-1}.mode button{@apply min-h-10 bg-transparent text-ink/50 shadow-none hover:translate-y-0}.mode button.active{@apply bg-ink text-white}.mode button.note-button.active{@apply bg-amber-500 text-ink}.ticket-side{@apply grid gap-3 self-start lg:sticky lg:top-23}.info-card{@apply rounded-[22px] border border-ink/7 bg-paper p-5}.info-list{@apply mt-4 grid gap-3}.info-row{@apply flex items-start justify-between gap-3 border-b border-ink/5 pb-3 text-xs last:border-0 last:pb-0}.info-row span{@apply text-ink/45}.info-row b{@apply text-left}.history-item{@apply mt-2 flex flex-col gap-1 border-t border-ink/6 pt-3 text-xs}.grant{@apply mt-2 flex items-center justify-between gap-2 rounded-xl bg-cream p-2 text-xs}.danger-button{@apply min-h-9 bg-coral px-3 py-1.5}
.stats-grid{@apply mb-5 grid grid-cols-2 gap-2 lg:grid-cols-4}.stat-card{@apply rounded-[20px] border border-ink/6 bg-paper p-4}.stat-label{@apply text-[11px] font-bold text-ink/40}.stat-value{@apply mt-2 text-2xl font-black}.stat-card.alert .stat-value{@apply text-coral}.dashboard{@apply grid grid-cols-1 gap-4 xl:grid-cols-[270px_minmax(0,1fr)]}.filters{@apply self-start rounded-[24px] border border-ink/7 bg-paper p-4 xl:sticky xl:top-23}.filter-heading{@apply mb-4 flex items-center justify-between}.tabs{@apply mb-5 grid grid-cols-2 gap-1 border-b border-ink/6 pb-4}.tabs a{@apply rounded-xl px-3 py-2 text-[11px] font-bold text-ink/50 hover:bg-mint hover:text-sea-dark}.filter-form{@apply grid gap-3 sm:grid-cols-2 xl:grid-cols-1}.check{@apply flex min-h-11 items-center gap-2 rounded-xl bg-cream px-3}.check input{@apply size-4 accent-sea}.staff-list{@apply grid gap-2}.staff-ticket{@apply grid grid-cols-[1fr_auto] gap-4 rounded-[22px] border border-ink/7 bg-paper p-4 text-ink shadow-panel transition hover:border-sea/25 hover:shadow-lift sm:p-5}.staff-ticket-main{@apply min-w-0}.staff-ticket-head{@apply flex flex-wrap items-center gap-2}.staff-ticket h2{@apply mt-2 truncate text-base}.staff-ticket p{@apply mt-2 text-xs text-ink/50}.staff-ticket-side{@apply flex flex-col items-end justify-between gap-3}.staff-ticket-badges{@apply flex flex-wrap justify-end gap-1}.staff-layout{@apply grid gap-4 xl:grid-cols-[240px_minmax(0,1fr)_240px] xl:items-start}.staff-layout>aside{@apply grid gap-3 self-start xl:sticky xl:top-23}.staff-layout>div{@apply min-w-0}.staff-layout dl{@apply grid grid-cols-[auto_1fr] gap-2 text-xs}.staff-layout dt{@apply text-ink/45}.staff-layout dd{@apply m-0 text-left font-bold}.staff-layout aside form{@apply mt-3 border-t border-ink/6 pt-3}.staff-layout aside form button{@apply w-full}.staff-layout aside details{@apply rounded-xl border border-ink/8 p-3}.staff-layout aside summary{@apply cursor-pointer text-sm font-bold}
.auth-shell{@apply mx-auto grid min-h-[calc(100vh-9rem)] max-w-5xl items-center gap-8 lg:grid-cols-2}.auth-intro{@apply hidden lg:block}.auth-intro-icon{@apply mb-6 grid size-14 place-items-center rounded-[18px] bg-sea text-2xl text-white}.auth-intro h2{@apply text-5xl}.auth-intro p{@apply mt-4 max-w-md text-ink/55}.auth{@apply mx-auto w-full max-w-md p-6 sm:p-8}.auth form{@apply mt-6}.auth button{@apply w-full}.auth-links{@apply mt-6 flex justify-between gap-3 border-t border-ink/6 pt-5 text-xs font-bold}.eyebrow{@apply mb-2 text-[11px] font-black tracking-wider text-sea}
}
.conversation{background-color:var(--theme-thread)}.message.mine{background-color:var(--theme-own-message)}.message.note{background-color:var(--theme-note);border-color:var(--color-coral)}.hero-panel{border-bottom:4px solid var(--color-coral);background-image:linear-gradient(135deg,var(--color-ink),var(--color-ink-soft))}.submit-ticket{box-shadow:0 10px 30px -14px var(--color-sea)}.stats-grid .stat-card:nth-child(1) .stat-value{color:var(--color-sea)}.stats-grid .stat-card:nth-child(2){border-top:3px solid var(--color-sea-dark)}.stats-grid .stat-card:nth-child(3){background:var(--color-mint)}.stats-grid .stat-card:nth-child(4){border-top:3px solid var(--color-coral)}.ticket-card:nth-child(3n+2):before{background-color:var(--color-sea-dark)}.ticket-card:nth-child(3n):before{background-color:var(--color-coral)}.step-title:nth-of-type(2) .step-number{background:var(--color-sea-dark)}.help-card{border-top:4px solid var(--color-coral)}
/* Nexus-inspired operational rhythm, adapted for the Persian RTL product. */
.dashboard-hero{@apply relative mb-4 grid overflow-hidden rounded-[18px] bg-ink p-5 text-white shadow-panel sm:grid-cols-[1fr_auto] sm:items-end sm:p-7}.dashboard-hero:before{@apply pointer-events-none absolute -left-16 -top-24 size-64 rounded-full bg-sea/25 blur-2xl content-['']}.dashboard-hero:after{@apply pointer-events-none absolute bottom-0 right-0 h-1 w-1/3 bg-coral content-['']}.dashboard-hero-copy,.dashboard-signal{@apply relative z-10}.dashboard-overline{@apply mb-5 flex items-center gap-2 text-[10px] font-extrabold tracking-wider text-mint}.live-dot{@apply relative size-2 rounded-full bg-coral}.live-dot:after{@apply absolute inset-0 animate-ping rounded-full bg-coral content-['']}.dashboard-hero h1{@apply text-3xl sm:text-4xl}.dashboard-hero p{@apply mt-2 max-w-2xl text-sm text-white/55}.dashboard-signal{@apply mt-6 flex min-w-48 flex-col border-r border-white/15 pr-4 sm:mt-0}.dashboard-signal span,.dashboard-signal small{@apply text-[10px] text-white/45}.dashboard-signal strong{@apply my-1 text-sm text-white}
.stats-grid{@apply gap-2}.stat-card{@apply relative min-h-32 overflow-hidden rounded-[14px] p-4 shadow-none transition hover:-translate-y-0.5 hover:border-sea/25 hover:shadow-panel}.stat-card:after{@apply absolute -bottom-8 -left-8 size-20 rounded-full bg-sea/5 content-['']}.stat-head{@apply flex items-start justify-between}.metric-mark,.panel-index{@apply font-mono text-[9px] font-bold tracking-widest text-ink/25}.stat-value{@apply text-3xl leading-none}.stat-card small{@apply mt-3 block text-[10px] text-ink/40}.stats-grid .stat-card:nth-child(3){background:linear-gradient(145deg,var(--color-mint),var(--color-paper))}.stats-grid .stat-card:nth-child(4){background:linear-gradient(145deg,var(--theme-note),var(--color-paper))}
.dashboard{@apply gap-3 xl:grid-cols-[250px_minmax(0,1fr)]}.filters,.ticket-stream{@apply rounded-[16px] border border-ink/7 bg-paper shadow-panel}.filters{@apply p-4}.filter-heading{@apply items-start border-b border-ink/6 pb-4}.filter-heading h3,.stream-head h2{@apply mt-1 text-sm}.filter-heading a{@apply text-[10px] font-bold text-sea}.tabs{@apply grid-cols-1 gap-0.5}.tabs a{@apply flex min-h-9 items-center justify-between rounded-lg px-3 py-2}.tabs a:after{@apply text-ink/20 content-['←']}.filter-form label{@apply text-xs}.filter-form input,.filter-form select{@apply rounded-xl py-2.5}.ticket-stream{@apply min-w-0 overflow-hidden}.stream-head{@apply flex items-center justify-between border-b border-ink/7 px-4 py-4 sm:px-5}.stream-status{@apply flex items-center gap-2 rounded-full bg-mint px-3 py-1 text-[10px] font-extrabold text-sea-dark}.stream-status i{@apply size-1.5 rounded-full bg-sea}.ticket-stream .staff-list{@apply gap-0}.ticket-stream .staff-ticket{@apply rounded-none border-x-0 border-t-0 p-4 shadow-none last:border-b-0 hover:translate-y-0 hover:border-sea/20 hover:bg-mint/30 hover:shadow-none}.ticket-stream .staff-ticket h2{@apply text-sm}.ticket-stream .staff-ticket p{@apply mt-1}.ticket-stream .staff-ticket:before{@apply absolute right-0 top-0 h-full w-0 bg-sea transition-all content-['']}.ticket-stream .staff-ticket:hover:before{@apply w-1}
@media (prefers-reduced-motion:reduce){.live-dot:after{animation:none}.stat-card,.staff-ticket{transition:none}}
/* Focused ticket conversation workspace */
body:has(.ticket-workspace){overflow:hidden}.customer-main:has(.ticket-workspace),.staff-content:has(.ticket-workspace){max-width:none;padding:0}.ticket-workspace{height:calc(100dvh - 4.25rem);min-height:32rem;background:var(--color-soft);overflow:hidden}.ticket-workspace-head{@apply flex min-h-18 items-center justify-between gap-3 border-b border-ink/8 bg-paper px-3 py-2 sm:px-5}.ticket-title{@apply flex min-w-0 items-center gap-3}.ticket-title>div{@apply min-w-0}.ticket-title h1{@apply truncate text-base sm:text-xl}.workspace-back,.icon-button{@apply grid size-10 shrink-0 place-items-center rounded-xl border border-ink/8 bg-cream text-ink shadow-none transition hover:border-sea/30 hover:bg-mint}.ticket-head-actions{@apply flex shrink-0 items-center gap-2}.ticket-head-actions form{@apply m-0}.ticket-head-actions form button{@apply min-h-10 rounded-xl px-3 py-2}.workspace-grid{display:grid;height:calc(100% - 4.5rem);min-height:0}.customer-grid{grid-template-columns:minmax(0,1fr) 280px}.staff-conversation-grid{grid-template-columns:240px minmax(0,1fr) 240px}.conversation-pane{position:relative;display:grid;grid-template-rows:auto minmax(0,1fr) auto;min-width:0;min-height:0;background:var(--color-paper);border-inline:1px solid rgba(8,55,107,.07)}.conversation-toolbar{@apply flex min-h-12 items-center justify-between border-b border-ink/6 bg-paper px-4}.conversation-toolbar>div{@apply flex items-center gap-2 text-xs}.conversation-toolbar small{@apply text-[10px] text-ink/40}
.ticket-workspace .conversation{display:block;max-height:none;min-height:0;overflow-y:auto;overscroll-behavior:contain;scroll-behavior:smooth;border-radius:0;padding:1rem;background:linear-gradient(180deg,var(--color-soft),var(--color-cream));scrollbar-gutter:stable}.ticket-workspace .conversation:focus-visible{outline:3px solid color-mix(in srgb,var(--color-sea) 25%,transparent);outline-offset:-3px}.ticket-workspace .message{position:relative;display:flex;width:100%;max-width:none;gap:.625rem;border-radius:0;background:transparent;padding:0;box-shadow:none;margin:.65rem 0}.ticket-workspace .message.mine{flex-direction:row-reverse;background:transparent}.message-avatar{@apply grid size-8 shrink-0 place-items-center rounded-xl bg-ink text-[11px] font-black text-white}.message.mine .message-avatar{@apply bg-sea}.message.note .message-avatar{@apply bg-coral text-ink}.message-bubble{position:relative;max-width:min(78%,46rem);border:1px solid rgba(8,55,107,.07);border-radius:18px 5px 18px 18px;background:var(--color-paper);padding:.7rem .85rem;box-shadow:0 8px 24px -22px rgba(8,55,107,.65)}.message.mine .message-bubble{border-radius:5px 18px 18px 18px;background:var(--theme-own-message)}.message.note{justify-content:center}.message.note .message-bubble{width:min(92%,52rem);max-width:none;border:1px dashed color-mix(in srgb,var(--color-coral) 60%,transparent);border-radius:14px;background:var(--theme-note)}.message-bubble header{@apply mb-1.5 flex flex-wrap items-center gap-2}.message-bubble header time{@apply mr-auto}.internal-label{@apply rounded-full bg-coral/15 px-2 py-0.5 text-[9px] font-black text-ink}.message-bubble>p{@apply text-sm leading-7}.edited-label,.revision-link{@apply ml-2 text-[9px] text-ink/35}.revision-link{@apply font-bold text-sea}.deleted-message{@apply italic text-ink/40}.date-divider{@apply sticky top-1 z-10 my-4 flex items-center justify-center}.date-divider span{@apply rounded-full border border-ink/8 bg-paper/90 px-3 py-1 text-[9px] font-bold text-ink/45 shadow-sm backdrop-blur}
.attachment-list{@apply mt-3 grid gap-2}.attachment{margin-top:0}.attachment-image{@apply block max-w-72 overflow-hidden p-1}.attachment-image img{@apply max-h-52 w-full rounded-lg object-cover}.attachment-image span{@apply block truncate px-2 py-1 text-[10px]}.attachment-file{@apply flex max-w-sm items-center gap-3 bg-white/75}.file-icon{@apply grid size-9 shrink-0 place-items-center rounded-lg bg-mint text-lg}.attachment-file b,.attachment-file small{@apply block}.attachment-file small{@apply mt-0.5 text-[9px] font-normal text-ink/40}.attachment-audio{@apply block max-w-md}.attachment-audio audio{@apply my-2 h-10 w-full}.attachment-audio>a{@apply text-[10px]}.message-menu{position:absolute;top:.35rem;left:.35rem}.message.mine .message-menu{left:auto;right:.35rem}.message-menu>summary{@apply grid size-8 cursor-pointer list-none place-items-center rounded-full text-xs tracking-widest text-ink/40 transition hover:bg-white hover:text-sea;box-shadow:none}.message-menu>summary::-webkit-details-marker{display:none}.message-menu[open]>summary{@apply bg-white text-sea;box-shadow:0 5px 15px -10px #08376b}.message-menu-panel{@apply absolute left-0 z-20 mt-1 w-72 overflow-hidden rounded-2xl border border-ink/10 bg-paper shadow-xl}.message.mine .message-menu-panel{right:0;left:auto}.message-menu-head{@apply flex items-center justify-between border-b border-ink/8 bg-ink/[.025] px-4 py-3}.message-menu-head b,.message-menu-head small{@apply block}.message-menu-head b{@apply text-xs text-ink}.message-menu-head small{@apply mt-0.5 text-[9px] font-normal text-ink/45}.message-menu-close{@apply grid size-8 min-h-0 place-items-center rounded-full bg-transparent p-0 text-lg font-normal text-ink/45 shadow-none hover:bg-ink/5 hover:text-ink}.message-edit-form{@apply p-4}.message-edit-form label{@apply mb-1.5 text-[10px] text-ink/65}.message-menu-panel textarea{@apply min-h-24 rounded-xl bg-ink/[.025] p-3 text-xs leading-6 shadow-none}.message-menu-actions{@apply mt-3 grid grid-cols-2 gap-2}.message-menu-actions button{@apply m-0 min-h-10 w-full rounded-xl px-3 py-2 text-xs}.message-edit-save{@apply bg-sea}.message-edit-cancel{@apply border border-ink/10 bg-white text-ink/60 shadow-none hover:bg-ink/5 hover:text-ink}.message-delete-zone{@apply flex items-center justify-between gap-3 border-t border-red-200 bg-red-50/50 px-4 py-3}.message-delete-zone b,.message-delete-zone small{@apply block}.message-delete-zone b{@apply text-[10px] text-red-700}.message-delete-zone small{@apply mt-0.5 text-[9px] text-red-700/60}.message-delete-zone form{@apply m-0}.message-delete-button{@apply m-0 min-h-8 rounded-lg border border-red-200 bg-white px-3 py-1 text-[10px] text-red-700 shadow-none hover:bg-red-500 hover:text-white}@media(max-width:639px){.message-menu-panel{position:fixed;right:.75rem!important;bottom:5rem;left:.75rem!important;top:auto;width:auto;max-height:calc(100dvh - 7rem);overflow:auto}}.conversation-empty{@apply grid h-full min-h-64 place-content-center text-center}.conversation-empty>span{@apply mx-auto mb-3 grid size-12 place-items-center rounded-full bg-mint text-sea}.conversation-empty p{@apply mt-1 text-xs text-ink/45}
.ticket-workspace .composer{position:relative;z-index:15;margin:0;border:0;border-top:1px solid rgba(8,55,107,.08);border-radius:0;padding:.65rem .85rem max(.65rem,env(safe-area-inset-bottom));box-shadow:0 -14px 40px -30px rgba(8,55,107,.55)}.composer-context{@apply mb-2 flex items-start justify-between}.composer-context b,.composer-context small{@apply block}.composer-context b{@apply text-xs}.composer-context small,.composer-context>[data-draft-status]{@apply mt-0.5 text-[9px] text-ink/40}.ticket-workspace .composer textarea{max-height:9rem;min-height:2.75rem;resize:none;border-radius:13px;background:var(--color-cream);padding:.7rem .85rem;line-height:1.7}.ticket-workspace input[type=file]{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}.composer-bar{@apply mt-2 flex items-center gap-2}.composer-tools{@apply flex items-center gap-1}.tool-button{@apply mb-0 inline-flex min-h-10 cursor-pointer items-center gap-1 rounded-xl border border-ink/8 bg-paper px-3 text-xs font-bold text-ink shadow-none hover:border-sea/30 hover:bg-mint}.tool-button span{@apply hidden sm:inline}.composer-hint{@apply hidden flex-1 text-center text-[9px] text-ink/30 lg:block}.send-button{@apply mr-auto min-h-10 rounded-xl bg-sea px-4 py-2}.compact-recorder{@apply my-2 rounded-xl p-3}.compact-recorder[hidden],.composer-extra[hidden]{display:none}.composer-extra{@apply mt-2 rounded-xl border border-ink/8 bg-cream p-3}.composer-extra label{@apply text-xs}.new-message-jump{@apply absolute bottom-36 left-1/2 z-20 min-h-9 -translate-x-1/2 rounded-full bg-ink px-4 py-2 text-[10px] shadow-xl}.new-message-jump[hidden]{display:none}.staff-composer .mode{@apply mb-2}.staff-composer.note-mode{background:var(--theme-note);border-top-color:color-mix(in srgb,var(--color-coral) 45%,transparent)}.staff-composer.note-mode textarea{@apply bg-white}.staff-composer.note-mode .send-button{@apply bg-coral text-ink}.file-preview:empty{display:none}.ticket-workspace .file-preview{@apply mb-2 mt-2 grid grid-cols-2 gap-2 sm:grid-cols-4}.ticket-workspace .file-chip{@apply text-[9px]}
.workspace-side{min-height:0;overflow-y:auto;padding:.75rem;background:var(--color-cream)}.workspace-side .info-card{@apply mb-3 rounded-[14px] p-4 shadow-none}.panel-close{@apply hidden}.ticket-operations form{@apply mt-3 border-t border-ink/6 pt-3}.ticket-operations form button{@apply w-full}.ticket-operations details{@apply mt-3 rounded-xl border border-ink/8 p-3}.ticket-operations summary{@apply cursor-pointer text-xs font-bold}
@media(max-width:1023px){body:has(.ticket-workspace) .mobile-dock,body:has(.ticket-workspace) .staff-mobile-dock{display:none}.ticket-workspace{height:calc(100dvh - 4.25rem)}.staff-conversation-grid,.customer-grid{grid-template-columns:minmax(0,1fr)}.workspace-side{position:fixed;inset:4.25rem 0 0 auto;z-index:60;width:min(88vw,22rem);transform:translateX(105%);border-left:1px solid rgba(8,55,107,.1);box-shadow:-20px 0 60px -35px rgba(8,55,107,.7);transition:transform .25s ease}.workspace-side.panel-open{transform:translateX(0)}.panel-close{@apply mb-3 grid size-10 place-items-center rounded-xl bg-ink text-white}.message-bubble{max-width:86%}}
@media(max-width:639px){.site-header{display:none}.customer-main:has(.ticket-workspace){padding:0}.ticket-workspace{height:100dvh}.ticket-workspace-head{@apply min-h-16}.workspace-grid{height:calc(100% - 4rem)}.ticket-title h1{@apply max-w-[48vw] text-sm}.ticket-head-actions .badge{@apply max-w-24 truncate}.conversation-toolbar{@apply min-h-10}.ticket-workspace .conversation{@apply px-2.5 py-3}.message-avatar{@apply size-7 rounded-lg}.message-bubble{max-width:88%;padding:.6rem .7rem}.message.note .message-bubble{width:96%}.ticket-workspace .composer{@apply px-2.5 pt-2}.composer-context small{max-width:70vw}.composer-hint{display:none}.send-button{@apply px-3}.new-message-jump{bottom:8.5rem}.ticket-head-actions form{display:none}}
@media(prefers-reduced-motion:reduce){.ticket-workspace .conversation{scroll-behavior:auto}.workspace-side{transition:none}}
.load-older{@apply mx-auto my-3 flex min-h-9 rounded-full border border-ink/10 bg-paper px-4 py-2 text-[10px] font-bold text-sea shadow-sm hover:bg-mint}.load-older.htmx-request{@apply pointer-events-none opacity-60}
/* Ticket correspondence: deliberate long-form replies, not instant chat. */
.ticket-workspace .conversation{background:var(--color-cream)}.ticket-workspace .message,.ticket-workspace .message.mine{display:grid;grid-template-columns:2.25rem minmax(0,1fr);align-items:start;gap:.75rem;margin:1rem auto;max-width:58rem}.ticket-workspace .message.mine{flex-direction:initial}.message-bubble,.message.mine .message-bubble{width:100%;max-width:none;border-radius:10px;border-right:3px solid var(--color-sea);background:var(--color-paper);padding:1rem 1.1rem;box-shadow:0 8px 24px -24px rgba(8,55,107,.7)}.message.mine .message-bubble{border-right-color:var(--color-ink);background:var(--color-paper)}.message.note{display:grid;justify-content:initial}.message.note .message-bubble{width:100%;max-width:none;border:1px solid color-mix(in srgb,var(--color-coral) 45%,transparent);border-right:3px solid var(--color-coral);border-radius:10px;background:var(--theme-note)}.message-bubble>p{font-size:.875rem;line-height:2;text-align:justify}.message-bubble header{padding-bottom:.5rem;border-bottom:1px solid rgba(8,55,107,.06)}.message-avatar{border-radius:9px}.ticket-workspace .composer{padding:1rem 1.1rem max(1rem,env(safe-area-inset-bottom));border-top:3px solid var(--color-sea);background:var(--color-paper)}.composer-context{margin-bottom:.75rem}.composer-context b{font-size:.875rem}.composer-context small{margin-top:.25rem;font-size:.6875rem;line-height:1.7}.ticket-workspace .composer textarea{min-height:7rem;max-height:15rem;border-radius:10px;background:#fff;border-color:rgba(8,55,107,.14);padding:.9rem 1rem}.ticket-workspace .composer textarea:focus{background:#fff}.composer-bar{margin-top:.75rem;padding-top:.75rem;border-top:1px solid rgba(8,55,107,.06)}.send-button{min-height:2.75rem;border-radius:10px;padding-inline:1.1rem}.staff-composer.note-mode{border-top:3px solid var(--color-coral)}.mode{max-width:30rem}.mode button{border-radius:9px}.date-divider{position:static}.date-divider span{background:transparent;border:0;box-shadow:none}.new-message-jump{bottom:17rem}
@media(max-width:639px){.ticket-workspace .message,.ticket-workspace .message.mine{grid-template-columns:1.75rem minmax(0,1fr);gap:.5rem;margin:.75rem 0}.message-bubble,.message.mine .message-bubble{max-width:none;padding:.8rem}.message-bubble>p{text-align:start}.ticket-workspace .composer textarea{min-height:6rem}.composer-bar{flex-wrap:wrap}.composer-tools{order:2}.send-button{order:1;width:100%;margin:0}.composer-hint{display:block;order:3;width:100%;text-align:right}.new-message-jump{bottom:19rem}}
/* Collapsible reply panel keeps the correspondence history dominant. */
.ticket-workspace .composer.is-collapsed{padding:.55rem .85rem;border-top:1px solid rgba(8,55,107,.1);background:var(--color-paper)}.composer.is-collapsed>form,.composer.is-collapsed>.mode{display:none}.composer-launch{display:none;width:100%;min-height:3.5rem;align-items:center;justify-content:flex-start;gap:.75rem;border:1px solid rgba(8,55,107,.1);border-radius:11px;background:linear-gradient(135deg,var(--color-paper),var(--color-mint));padding:.55rem .75rem;color:var(--color-ink);box-shadow:none;text-align:right}.composer.is-collapsed .composer-launch{display:flex}.composer-launch:hover{transform:none;border-color:color-mix(in srgb,var(--color-sea) 35%,transparent);background:var(--color-mint)}.composer-launch-icon{@apply grid size-9 shrink-0 place-items-center rounded-lg bg-sea text-lg text-white}.composer-launch b,.composer-launch small{display:block}.composer-launch b{@apply text-xs}.composer-launch small{@apply mt-0.5 text-[9px] font-medium text-ink/45}.composer-launch-arrow{@apply mr-auto text-sm text-sea}.composer-close{@apply text-ink/55}.composer:not(.is-collapsed) .composer-launch{display:none}.composer.is-collapsed~*{transition:none}.composer.is-collapsed+.new-message-jump{bottom:5rem}.ticket-workspace .composer.is-collapsed{box-shadow:0 -10px 30px -28px rgba(8,55,107,.65)}
@media(max-width:639px){.ticket-workspace .composer.is-collapsed{@apply px-2.5 py-2}.composer-launch{min-height:3.25rem}.composer-launch small{max-width:65vw}.composer-close{order:3}.new-message-jump{bottom:5.5rem}.ticket-workspace .composer:not(.is-collapsed){max-height:62dvh;overflow-y:auto}}
.conversation-pane:has(.composer.is-collapsed) .new-message-jump{bottom:5rem}.conversation-pane:not(:has(.composer.is-collapsed)) .new-message-jump{bottom:17rem}@media(max-width:639px){.conversation-pane:has(.composer.is-collapsed) .new-message-jump{bottom:5.5rem}.conversation-pane:not(:has(.composer.is-collapsed)) .new-message-jump{bottom:19rem}}
body:has(.ticket-workspace) .flash{position:fixed;top:5rem;left:50%;z-index:100;width:min(calc(100% - 2rem),42rem);margin:0;transform:translateX(-50%);box-shadow:0 18px 50px -25px rgba(8,55,107,.55);animation:flash-in .22s ease-out}.flash{position:relative;padding-left:3rem}.flash-close{position:absolute;left:.5rem;top:50%;min-height:2rem;width:2rem;transform:translateY(-50%);border-radius:.5rem;background:transparent;padding:0;color:currentColor;box-shadow:none}.flash-close:hover{transform:translateY(-50%);background:rgba(255,255,255,.6)}.flash-leaving{opacity:0;transform:translate(-50%,-.5rem)!important;transition:.25s ease}@keyframes flash-in{from{opacity:0;transform:translate(-50%,-.5rem)}to{opacity:1;transform:translate(-50%,0)}}
.flash.flash-leaving{transform:none!important}body:has(.ticket-workspace) .flash.flash-leaving{transform:translate(-50%,-.5rem)!important}
/* Searchable Iran province/city fields shared by profile and new-ticket forms. */
.location-fields{@apply mb-6 rounded-2xl border border-sea/15 bg-mint/40 p-4 sm:p-5}.location-heading{@apply mb-4 flex items-start justify-between gap-3}.location-heading p{@apply mt-1 text-xs text-ink/50}.location-heading>span{@apply shrink-0 rounded-full bg-sea/10 px-3 py-1 text-[10px] font-black text-sea}.location-fields .field{@apply mb-0}.location-fields input:disabled{@apply cursor-not-allowed bg-slate-100 text-ink/40}.location-hint{@apply mb-0 mt-3 text-[11px] font-medium text-ink/50}.location-hint.is-error{@apply text-red-700}
/* Staff operations UI: compact queues, explicit state, and consistent navigation. */
.staff-shell{@apply bg-soft lg:grid-cols-[264px_minmax(0,1fr)]}.staff-sidebar{position:sticky;top:0;height:100dvh;overflow-y:auto;background:linear-gradient(180deg,var(--color-ink),#06284d);padding:1.25rem}.staff-brand{@apply mb-8 rounded-2xl p-2 text-white hover:bg-white/5}.staff-menu-label{@apply mb-2 px-3 text-[10px] font-black tracking-wider text-white/35}.staff-menu{@apply gap-1}.staff-menu a{position:relative;min-height:2.9rem;border:1px solid transparent;border-radius:.75rem;padding:.65rem .75rem;color:rgba(255,255,255,.62)}.staff-menu a>span{@apply grid size-8 shrink-0 place-items-center rounded-lg bg-white/7 text-base}.staff-menu a>b{@apply text-xs}.staff-menu a:hover{@apply bg-white/7 text-white}.staff-menu a.active{background:linear-gradient(135deg,var(--color-sea),var(--color-blue));border-color:rgba(255,255,255,.15);box-shadow:0 14px 28px -18px rgba(6,147,227,.8)}.staff-menu a.active:after{position:absolute;right:-1.25rem;width:.22rem;height:1.75rem;border-radius:.25rem 0 0 .25rem;background:var(--color-coral);content:''}.staff-menu a.active>span{@apply bg-white/15}.staff-profile{@apply flex items-center gap-3 border border-white/8 bg-white/5 p-3}.staff-profile-avatar{@apply grid size-10 shrink-0 place-items-center rounded-xl bg-coral font-black text-ink}.staff-profile>div>span{@apply block}.staff-topbar{@apply h-[4.5rem] border-ink/7 bg-paper/90}.staff-topbar>div:first-child small{@apply text-[9px] font-bold text-sea}.staff-topbar h2{@apply mt-0.5 text-sm}.staff-content{@apply max-w-[1560px] pt-5 lg:px-8}
.staff-page-head{@apply mb-5 flex flex-col justify-between gap-4 rounded-2xl border border-ink/7 bg-paper p-5 shadow-panel sm:flex-row sm:items-end sm:p-6}.staff-page-head h1{@apply mt-1 text-2xl sm:text-3xl}.staff-page-head p:last-child{@apply mt-2 max-w-2xl text-xs text-ink/50 sm:text-sm}.staff-sync{@apply flex shrink-0 items-center gap-3 rounded-xl border border-sea/10 bg-mint px-4 py-2.5}.staff-sync b,.staff-sync small{@apply block}.staff-sync b{@apply text-xs text-sea-dark}.staff-sync small{@apply mt-0.5 text-[9px] text-ink/40}
.stats-grid{@apply gap-3}.stat-card{position:relative;overflow:hidden;border-radius:1rem;padding:1rem;color:var(--color-ink);box-shadow:0 10px 30px -28px rgba(8,55,107,.8);transition:.2s ease}.stat-card[href]:hover{@apply -translate-y-0.5 border-sea/25 shadow-lift}.stat-card.is-active{@apply border-sea bg-mint}.stat-card.is-active:after{position:absolute;inset:auto 0 0;height:.2rem;background:var(--color-sea);content:''}.stat-head{@apply flex items-center gap-2}.stat-icon{@apply grid size-7 place-items-center rounded-lg bg-mint text-xs font-black text-sea}.stat-card.alert .stat-icon{@apply bg-coral/15 text-coral}.stat-value{@apply mt-3}.stat-card small{@apply text-[10px] text-ink/45}
.queue-switcher{@apply mb-4 flex gap-1 overflow-x-auto rounded-xl border border-ink/7 bg-paper p-1.5 shadow-sm}.queue-switcher a{@apply shrink-0 rounded-lg px-3 py-2 text-[10px] font-bold text-ink/50 hover:bg-mint hover:text-sea-dark}.queue-switcher a.active{@apply bg-ink text-white shadow-sm}.dashboard{@apply items-start xl:grid-cols-[260px_minmax(0,1fr)]}.filters{@apply border-ink/8}.filter-heading{@apply mb-3}.filter-form{@apply gap-2.5}.filter-form label{@apply mb-0}.filter-form button{@apply mt-1 w-full rounded-xl}.search-field input{background-image:linear-gradient(transparent,transparent)}.stream-meta{@apply flex items-center gap-2}.stream-meta>span:first-child{@apply hidden text-[10px] font-bold text-ink/40 sm:inline}.ticket-stream{@apply border-ink/8}.stream-head{@apply min-h-16 bg-cream/45}.stream-head h2{@apply text-base}
.ticket-stream .staff-ticket{position:relative;grid-template-columns:minmax(0,1fr) auto;min-height:7.25rem;padding:1rem 1.15rem;border-right:3px solid var(--color-sea)}.ticket-stream .staff-ticket.priority-edge-important{border-right-color:var(--color-blue)}.ticket-stream .staff-ticket.priority-edge-urgent{border-right-color:var(--color-coral)}.ticket-stream .staff-ticket:hover{background:linear-gradient(90deg,var(--color-paper),var(--color-mint))}.staff-ticket-head time{@apply text-[9px] font-medium text-ink/35}.staff-ticket h2{@apply mt-2.5 truncate text-[15px]}.ticket-row-meta{@apply mt-3 flex flex-wrap items-center gap-x-3 gap-y-1 text-[10px] text-ink/45}.ticket-row-meta span{position:relative}.ticket-row-meta span+span:before{position:absolute;right:-.45rem;content:'•';color:rgba(8,55,107,.25)}.ticket-locked{@apply mt-3 rounded-lg bg-coral/10 px-3 py-2 text-[10px] font-bold text-ink/60}.staff-ticket-side{@apply min-w-32}.staff-ticket-badges{@apply flex-nowrap}.ticket-owner{@apply max-w-40 truncate text-[9px] font-bold text-ink/40}.ticket-open{@apply flex items-center gap-1 text-[10px] font-black text-sea}.ticket-open b{@apply transition}.staff-ticket:hover .ticket-open b{@apply -translate-x-1}.staff-list .empty{@apply rounded-none border-0 py-16 shadow-none}
.staff-mobile-dock{@apply grid-cols-4}.staff-mobile-dock a{@apply rounded-xl px-1}.staff-mobile-dock a.active{background:linear-gradient(135deg,var(--color-sea),var(--color-blue))}
@media(max-width:639px){.staff-content{@apply px-3 pt-3}.staff-page-head{@apply mb-3 p-4}.staff-page-head h1{@apply text-xl}.staff-sync{@apply w-full}.stats-grid{@apply mb-3}.stat-card{@apply p-3}.stat-value{@apply text-xl}.queue-switcher{@apply -mx-1}.dashboard{@apply gap-3}.filters{@apply p-3}.filter-form{@apply grid-cols-2}.filter-form .search-field,.filter-form .check,.filter-form button{@apply col-span-2}.ticket-stream .staff-ticket{@apply grid-cols-1 gap-3 p-3.5}.staff-ticket-side{@apply min-w-0 flex-row items-center}.ticket-owner{display:none}.ticket-open{@apply mr-auto}.staff-ticket-badges{@apply justify-start}.stream-head{@apply px-3}.stream-status{display:none}}
/* High-contrast staff typography and semantic states. Keep critical text opaque. */
.staff-shell{--staff-text:#123a63;--staff-muted:#526b85;--staff-subtle:#60758b;--staff-border:#ccd8e5;--status-new-bg:#e4f4ff;--status-new-fg:#07517f;--status-open-bg:#e6ebff;--status-open-fg:#263d8f;--status-staff-bg:#fff0cf;--status-staff-fg:#754000;--status-customer-bg:#dff1ff;--status-customer-fg:#07518b;--status-reopened-bg:#ffe4d8;--status-reopened-fg:#8a3511;--status-resolved-bg:#dff5e9;--status-resolved-fg:#17613c;--status-closed-bg:#e9edf2;--status-closed-fg:#44576b;color:var(--staff-text)}
.staff-menu a{color:#d3e1f0}.staff-menu a:hover{color:#fff}.staff-menu a.active{background:linear-gradient(135deg,var(--color-sea),var(--color-sea-dark))}.staff-menu-label{color:#b6c9dd;font-size:.75rem}.staff-brand small,.staff-profile>div>span{color:#c2d2e3;font-size:.75rem}.staff-menu a>b{font-size:.875rem;line-height:1.6}.staff-menu a em{margin-right:auto;min-width:1.55rem;border-radius:999px;background:var(--color-coral);padding:.15rem .4rem;color:#3d2900;font-size:.75rem;font-style:normal;text-align:center}.staff-action-link:not(.active){background:rgba(250,159,0,.1);border-color:rgba(250,159,0,.22)}
.staff-topbar>div:first-child small{color:#1977ce;font-size:.75rem}.staff-topbar h2{font-size:1rem}.staff-topbar-actions>span{color:var(--staff-muted)!important;font-size:.8rem}.staff-topbar a{color:var(--staff-text);font-size:.8rem}
.staff-page-head .eyebrow{color:#1977ce;font-size:.75rem}.staff-page-head h1{color:#08376b;font-size:1.75rem;line-height:1.5}.staff-page-head p:last-child{color:var(--staff-muted);font-size:.875rem;line-height:1.9}.staff-sync b{color:#07517f;font-size:.8125rem}.staff-sync small{color:var(--staff-muted);font-size:.75rem}
.stat-label{color:var(--staff-muted);font-size:.8125rem}.stat-card small{color:var(--staff-muted);font-size:.75rem}.stat-value{color:#08376b}.panel-index{color:var(--staff-muted);font-family:Vazirmatn,ui-sans-serif,system-ui;font-size:.75rem;letter-spacing:0}.queue-switcher a{color:var(--staff-muted);font-size:.8125rem}.queue-switcher a.active{color:#fff}
.dashboard{grid-template-columns:minmax(0,1fr)}@media(min-width:1024px){.dashboard{grid-template-columns:280px minmax(0,1fr)}.filters{position:sticky;top:5.75rem}}
.filters{border-color:var(--staff-border);background:#fff}.filter-heading{align-items:center}.filter-title{display:flex;align-items:center;gap:.65rem}.filter-icon{display:grid;width:2.25rem;height:2.25rem;place-items:center;border-radius:.65rem;background:#e4f4ff;color:#07517f;font-size:1.15rem}.filter-heading h3{margin-top:.15rem;color:#08376b;font-size:.9rem}.filter-heading>a{color:#1269ad;font-size:.75rem;text-decoration:underline;text-underline-offset:3px}.filter-form label{color:#244b72;font-size:.8125rem}.filter-form input,.filter-form select{border-color:#b9c9d9;color:#123a63;font-size:.8125rem}.check{color:#244b72!important}.check span{font-size:.8125rem}
.stream-head .panel-index{color:#526b85}.stream-head h2{color:#08376b;font-size:1.05rem}.stream-meta>span:first-child{color:var(--staff-muted);font-size:.75rem}.stream-status{color:#07517f;font-size:.75rem}
.ticket-stream .staff-ticket{border-bottom-color:#d5dee8;border-right-width:4px;color:var(--staff-text)}.ticket-stream .staff-ticket.status-row-waiting_staff,.ticket-stream .staff-ticket.status-row-reopened{background:linear-gradient(90deg,#fff,#fff9ec);border-right-color:#e58d00}.ticket-stream .staff-ticket.status-row-waiting_staff:hover,.ticket-stream .staff-ticket.status-row-reopened:hover{background:linear-gradient(90deg,#fff9ec,#fff2d6)}.staff-ticket-head{gap:.55rem}.staff-ticket-head .ticket-number{color:#365a7d;font-family:Vazirmatn,ui-sans-serif,system-ui;font-size:.75rem;font-weight:800}.staff-ticket-head time{margin-right:auto;color:var(--staff-muted);font-size:.75rem;font-weight:600}.staff-ticket h2{color:#08376b;font-size:1.05rem;line-height:1.8;white-space:normal}.action-required{border:1px solid #e7a027;border-radius:999px;background:#fff0cf;padding:.2rem .55rem;color:#754000;font-size:.7rem;font-weight:900}.ticket-row-meta{gap:.45rem;margin-top:.65rem;color:var(--staff-muted);font-size:.75rem}.ticket-row-meta span{display:inline-flex;align-items:center;min-height:1.8rem;border:1px solid #d3dde7;border-radius:.5rem;background:#f6f8fa;padding:.25rem .55rem;line-height:1.5}.ticket-row-meta span+span:before{display:none}.ticket-locked{color:#65420b;font-size:.75rem}.ticket-owner{max-width:11rem;color:#526b85;font-size:.75rem}.ticket-open{color:#1269ad;font-size:.78rem}.staff-ticket-badges{gap:.35rem}.staff-ticket-badges .badge{border:1px solid transparent;padding:.3rem .65rem;font-size:.75rem;line-height:1.4}.staff-ticket-badges .badge:before{width:.42rem;height:.42rem}.staff-ticket-badges .priority-normal{border-color:#cbd7e2;background:#f0f4f7;color:#3f566d}.staff-ticket-badges .priority-normal:before{background:#60758b}.staff-ticket-badges .priority-important{border-color:#e5b44e;background:#fff3d6;color:#704800}.staff-ticket-badges .priority-urgent{border-color:#e79b91;background:#ffebe8;color:#8b2d22}
.staff-ticket-badges .status-new{border-color:#93c8e8;background:var(--status-new-bg);color:var(--status-new-fg)}.staff-ticket-badges .status-new:before{background:var(--status-new-fg)}.staff-ticket-badges .status-open{border-color:#aebbed;background:var(--status-open-bg);color:var(--status-open-fg)}.staff-ticket-badges .status-open:before{background:var(--status-open-fg)}.staff-ticket-badges .status-waiting_staff{border-color:#e3b35b;background:var(--status-staff-bg);color:var(--status-staff-fg)}.staff-ticket-badges .status-waiting_staff:before{background:#d98200}.staff-ticket-badges .status-waiting_customer{border-color:#8fc5e9;background:var(--status-customer-bg);color:var(--status-customer-fg)}.staff-ticket-badges .status-waiting_customer:before{background:#1977ce}.staff-ticket-badges .status-reopened{border-color:#e9a184;background:var(--status-reopened-bg);color:var(--status-reopened-fg)}.staff-ticket-badges .status-reopened:before{background:#b64d20}.staff-ticket-badges .status-resolved{border-color:#8dceb0;background:var(--status-resolved-bg);color:var(--status-resolved-fg)}.staff-ticket-badges .status-resolved:before{background:#218653}.staff-ticket-badges .status-closed{border-color:#bdc8d3;background:var(--status-closed-bg);color:var(--status-closed-fg)}.staff-ticket-badges .status-closed:before{background:#60758b}
.staff-mobile-dock{grid-template-columns:repeat(6,minmax(0,1fr))}.staff-mobile-dock a{color:#c7d6e6;font-size:.6875rem}.staff-mobile-dock a.active{color:#fff;background:linear-gradient(135deg,var(--color-sea),var(--color-sea-dark))}
@media(max-width:639px){.staff-page-head h1{font-size:1.35rem}.staff-page-head p:last-child{font-size:.8125rem}.stats-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.filter-form label{font-size:.8rem}.staff-ticket h2{font-size:.95rem}.ticket-row-meta{font-size:.72rem}.staff-ticket-head time{margin-right:0}.staff-ticket-side{flex-wrap:wrap}.staff-ticket-badges .badge{font-size:.7rem}.staff-mobile-dock{inset-inline:.5rem;bottom:.5rem}.staff-mobile-dock a{font-size:.625rem}}
/* Company identity */
.header-company-logo{display:block;width:5.5rem;height:auto;max-height:2.4rem;flex-shrink:0;object-fit:contain}
.staff-brand{display:flex;flex-direction:column;align-items:stretch;gap:.8rem;margin-bottom:1.75rem;padding:.5rem;text-align:center}
.staff-logo-panel{display:flex;width:100%;min-height:4.5rem;align-items:center;justify-content:center;border:1px solid rgba(255,255,255,.42);border-radius:.9rem;background:#fff;padding:.65rem .9rem}
.staff-company-logo{display:block;width:8.75rem;height:auto;max-height:3.35rem;object-fit:contain}
.staff-brand-copy{display:block;min-width:0;padding-inline:.35rem}.staff-brand b{display:block;color:#fff;font-size:.92rem;font-weight:900;line-height:1.8}.staff-brand small{display:block;margin-top:.1rem;color:#c7d7e8;font-size:.72rem;font-weight:600;line-height:1.7}.staff-brand:hover .staff-logo-panel{border-color:rgba(6,147,227,.75)}.staff-brand:hover .staff-brand-copy b{color:#fff}.logo-copy{line-height:1.45}
.auth-panel{width:100%;max-width:28rem;margin-inline:auto}.auth-brand{display:flex;align-items:center;flex-direction:column;gap:.55rem;margin-bottom:1.35rem;padding-bottom:1rem;border-bottom:1px solid rgba(8,55,107,.09);text-align:center}
.auth-brand img{display:block;width:8.5rem;height:auto;max-height:3.7rem;object-fit:contain;flex-shrink:0}
.auth-brand strong{display:block;color:var(--color-ink);font-size:.82rem;font-weight:900;line-height:1.6}
.auth-brand small{display:block;margin-top:.1rem;color:#526b85;font-size:.67rem;font-weight:600}
.auth-footer{margin:.65rem auto 0;padding:.2rem .75rem;color:#60758b;font-size:.65rem;font-weight:500;line-height:1.8;text-align:center}
.ticket-company-logo{display:block;width:3.25rem;height:auto;max-height:1.45rem;flex-shrink:0;object-fit:contain}
.site-footer{display:flex;min-height:2rem;align-items:center;justify-content:center;gap:.35rem;padding:.4rem 1rem;color:#60758b;font-size:.68rem;font-weight:500;text-align:center}
.staff-main>.site-footer{border-top:1px solid rgba(8,55,107,.06)}
body:has(.ticket-workspace) .ticket-workspace{height:calc(100dvh - 4.25rem - 2rem)}
@media(max-width:639px){.logo-copy{font-size:.82rem}.header-company-logo{width:4.75rem;max-height:2.1rem}.auth-brand{gap:.5rem}.auth-brand img{width:7rem;max-height:3.1rem}.auth-brand>div{min-width:0}.auth-footer{font-size:.6rem}.ticket-company-logo{width:2.5rem;max-height:1.1rem}.site-footer{padding-inline:3.5rem;font-size:.62rem;line-height:1.6}body:has(.ticket-workspace) .ticket-workspace{height:calc(100dvh - 2rem)}}
/* Session actions, staff-created tickets and install prompt */
.desktop-nav form,.staff-topbar-actions form{margin:0}.logout-button{min-height:auto;border:0;background:transparent;padding:.5rem .75rem;color:var(--color-coral);box-shadow:none}.logout-button:hover{transform:none;background:#fff;color:#b45309;box-shadow:none}
.customer-mobile-dock{grid-template-columns:repeat(4,minmax(0,1fr))}.customer-mobile-dock form{margin:0}.customer-mobile-dock form button{display:flex;width:100%;min-height:3rem;flex-direction:column;align-items:center;justify-content:center;gap:.125rem;border-radius:1rem;background:transparent;padding:0;color:rgba(255,255,255,.6);font-size:.625rem;box-shadow:none}.customer-mobile-dock form button:hover{transform:none;background:rgba(255,255,255,.08);box-shadow:none}
.staff-create-card{max-width:48rem;margin-inline:auto}.staff-create-card form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.25rem 1rem}.staff-create-card form>p:has(textarea),.staff-create-card form>p:has(input[type=file]),.staff-create-card form>button,.staff-create-card .errorlist{grid-column:1/-1}.staff-create-card textarea{min-height:10rem}
.pwa-install{position:fixed;right:1rem;bottom:1rem;z-index:80;display:flex;width:min(30rem,calc(100vw - 2rem));align-items:center;justify-content:space-between;gap:1rem;border:1px solid rgba(6,147,227,.25);border-radius:1rem;background:#fff;padding:1rem;box-shadow:0 20px 60px -30px rgba(8,55,107,.7)}.pwa-install[hidden]{display:none}.pwa-install b,.pwa-install small{display:block}.pwa-install small{margin-top:.2rem;color:#526b85;font-size:.72rem}.pwa-install>div:last-child{display:flex;gap:.4rem}.pwa-install button{min-height:2.4rem;padding:.45rem .75rem;background:#eaeaea;color:#526b85;box-shadow:none}.pwa-install button.primary{background:var(--color-sea);color:#fff}
@media(max-width:639px){.staff-create-card form{grid-template-columns:1fr}.pwa-install{right:.65rem;bottom:5.5rem;width:calc(100vw - 1.3rem);align-items:stretch;flex-direction:column}.pwa-install>div:last-child button{flex:1}}
/* Media capture, image inspection and message read receipts */
.customer-mobile-dock a.primary{background:transparent;color:rgba(255,255,255,.6)}.customer-mobile-dock a.active{background:linear-gradient(135deg,var(--color-sea),var(--color-sea-dark));color:#fff}@media(max-width:639px){body:has(.customer-mobile-dock)>.site-footer{margin-bottom:calc(5.5rem + env(safe-area-inset-bottom))}}
.composer-context{gap:.75rem}.composer-context-actions{display:flex;flex:none;align-items:center;gap:.5rem}.composer-context-actions>[data-draft-status]{color:#60758b;font-size:.58rem}.composer-send-icon{display:grid;width:2.5rem;height:2.5rem;min-height:2.5rem;flex:none;place-items:center;border:1px solid rgba(6,147,227,.25);border-radius:999px;background:var(--color-sea);padding:0;color:#fff;box-shadow:none}.composer-send-icon:hover{transform:none;background:var(--color-sea-dark);box-shadow:none}.composer-send-icon svg{width:1.2rem;height:1.2rem;fill:currentColor}@keyframes submit-attention{0%,100%{outline:0 solid transparent;background-color:var(--color-sea)}45%{outline:4px solid rgba(250,159,0,.24);background-color:var(--color-coral)}}.send-button.submit-attention{animation:submit-attention .7s ease-out 1}@media(prefers-reduced-motion:reduce){.send-button.submit-attention{animation:none;outline:3px solid rgba(250,159,0,.28)}}
.media-picker-actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.65rem}.media-picker-button{display:flex;min-height:3rem;align-items:center;justify-content:center;border:1px solid #9ec8e5;border-radius:.85rem;background:#fff;padding:.7rem;color:#0b5f9b;font-size:.78rem;font-weight:900;cursor:pointer}.media-picker-button.gallery-button{border-color:#0693e3;background:#e9f7ff}.media-picker>[data-gallery-input],.media-picker>[data-document-input],.canonical-files,.canonical-file-input{position:absolute!important;width:1px!important;height:1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important}.compression-note{display:block;margin-top:.65rem;color:#526b85;font-size:.68rem}.recorder-error{display:block;margin-top:.6rem;color:#9b2c2c;font-size:.7rem}.attachment-image{display:grid!important;gap:.45rem}.attachment-image>button{display:block;min-height:0;background:transparent;padding:0;color:#08376b;box-shadow:none}.attachment-image>button:hover{transform:none;background:transparent;box-shadow:none}.attachment-image img{display:block;width:min(24rem,100%);max-height:18rem;border-radius:.65rem;object-fit:cover}.attachment-image span{display:block;padding:.45rem .25rem;text-align:right;font-size:.68rem}.attachment-download{padding:.35rem;color:#1977ce;font-size:.68rem}.image-viewer{width:min(70rem,calc(100vw - 2rem));max-width:none;border:0;border-radius:1rem;background:#fff;padding:0;color:#08376b;box-shadow:0 25px 80px #031b33aa}.image-viewer::backdrop{background:#031b33d9;backdrop-filter:blur(4px)}.image-viewer header,.image-viewer footer{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem}.image-viewer header{border-bottom:1px solid #dae6ef}.image-viewer header button{min-height:2.3rem;border-radius:.65rem;padding:.3rem .75rem}.image-viewer-stage{display:grid;min-height:14rem;max-height:75vh;place-items:center;overflow:auto;background:#0c2236}.image-viewer-stage img{display:block;max-width:100%;max-height:75vh;object-fit:contain}.image-viewer footer{justify-content:flex-end}.message-receipts{margin-top:.45rem!important;border-top:1px solid #d5e3ec;padding-top:.35rem}.message-receipts summary{color:#526b85;font-size:.62rem;font-weight:700}.message-receipts ul{display:grid;gap:.25rem;margin:.4rem 0 0;padding:0;list-style:none}.message-receipts li{display:flex;justify-content:space-between;gap:.7rem;color:#526b85;font-size:.6rem}.message-receipts time{color:#647b91}
@media(max-width:639px){.media-picker-actions{grid-template-columns:1fr}.image-viewer{width:calc(100vw - .75rem)}.image-viewer-stage{max-height:78vh}}
/* Ticket media and staff sidebar refinements */
.image-viewer{position:fixed;inset:0;margin:auto;max-height:min(90dvh,56rem)}.image-viewer[open]{display:flex;flex-direction:column}.image-viewer-stage{flex:1;min-height:0}.reply-media-picker{margin:.75rem 0;border:1px dashed #9fc3dc;border-radius:1rem;background:#f6fbff;padding:.75rem}.reply-media-picker>[data-gallery-input],.reply-media-picker>[data-document-input]{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}.staff-developer-credit{margin:.65rem .4rem 0;border-top:1px solid rgba(255,255,255,.12);padding:.7rem .25rem 0;color:#c7d7e8;font-size:.62rem;line-height:1.8;text-align:center}
/* Staff customer directory and assisted ticket creation */
.customer-page-head{align-items:flex-end}.customer-directory{padding:0;overflow:hidden}.customer-directory-search{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:end;gap:.75rem;padding:1.25rem;background:linear-gradient(135deg,#f5faff,#fff)}.customer-directory-search label{display:grid;gap:.4rem;color:var(--color-navy);font-size:.8rem;font-weight:800}.customer-directory-search input{width:100%;min-height:3rem}.customer-directory-search a{padding:.8rem;color:#526b85;font-weight:700}.customer-result-head{display:flex;justify-content:space-between;gap:1rem;padding:1rem 1.25rem;border-top:1px solid #dbe8f4;border-bottom:1px solid #dbe8f4;color:#526b85}.customer-result-head span{color:var(--color-navy);font-weight:900}.customer-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;padding:1.25rem;background:#f7fafc}.customer-card{display:grid;gap:1rem;border:1px solid #d7e5f2;border-radius:1rem;background:#fff;padding:1.15rem;box-shadow:0 10px 28px -24px #08376b}.customer-card header{display:flex;align-items:center;gap:.75rem}.customer-card header h2{margin:0;color:#173a5e;font-size:1rem}.customer-card header a{display:inline-block;margin-top:.2rem;color:#1977ce;font-size:.8rem}.customer-avatar{display:grid;width:2.75rem;height:2.75rem;place-items:center;border-radius:.8rem;background:#dff2ff;color:#08376b;font-weight:900}.customer-location{margin:0;color:#526b85;font-size:.78rem}.customer-ticket-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:.45rem}.customer-ticket-stats span{display:grid;gap:.15rem;border-radius:.65rem;background:#f1f5f9;padding:.55rem;text-align:center;color:#526b85;font-size:.65rem}.customer-ticket-stats b{color:#08376b;font-size:1rem}.customer-ticket-stats .needs-action{background:#fff4dd;color:#985f00}.customer-ticket-stats .needs-action b{color:#c67600}.customer-new-ticket{border-top:1px solid #e4edf5;padding-top:.8rem;color:#1977ce;font-size:.78rem;font-weight:900}.customer-ticket-create{display:block}.customer-picker-head{display:flex;align-items:start;justify-content:space-between;gap:1rem;margin-bottom:1rem;border-bottom:1px solid #dbe8f4;padding-bottom:1rem}.customer-picker-head h2{margin:.2rem 0;color:#173a5e;font-size:1.1rem}.customer-picker-head p{margin:0;color:#526b85;font-size:.78rem}.customer-picker-head a{white-space:nowrap;color:#1977ce;font-size:.75rem;font-weight:800}.customer-search-box{display:grid;gap:.4rem;margin-bottom:.75rem;color:#173a5e;font-size:.8rem;font-weight:900}.customer-search-box small{color:#647b91;font-size:.68rem;font-weight:500}.customer-search-results{position:relative;z-index:4;display:grid;gap:.35rem;max-height:18rem;margin-bottom:.8rem;overflow:auto;border:1px solid #cdddeb;border-radius:.75rem;background:#fff;padding:.4rem;box-shadow:0 18px 35px -28px #08376b}.customer-search-results[hidden]{display:none}.customer-search-results button{display:grid;grid-template-columns:1fr auto;gap:.15rem .75rem;width:100%;min-height:auto;border:0;border-radius:.55rem;background:#f7fafc;padding:.7rem;text-align:right;box-shadow:none;color:#173a5e}.customer-search-results button:hover{background:#e8f5ff}.customer-search-results button span{grid-row:1;grid-column:2}.customer-search-results button small{grid-column:1/-1;color:#647b91}.selected-customer{display:grid;grid-template-columns:1fr 1fr auto;align-items:center;gap:1rem;margin-bottom:.8rem;border:1px solid #93d4fa;border-radius:.8rem;background:#eef9ff;padding:.8rem}.selected-customer[hidden]{display:none}.selected-customer div{display:grid;gap:.2rem}.selected-customer b{color:#08376b}.selected-customer span,.selected-customer small{color:#526b85;font-size:.75rem}.selected-customer button{min-height:auto;background:transparent;color:#1977ce;box-shadow:none;padding:.5rem}.customer-lookup-status{margin-bottom:1rem;border-radius:.65rem;background:#f1f5f9;padding:.65rem .8rem;color:#526b85;font-size:.75rem}.customer-lookup-status.is-found{background:#eaf8f0;color:#17603a}.customer-lookup-status.is-new{background:#fff5df;color:#805300}.customer-lookup-status.is-error{background:#fff0f0;color:#a32929}
@media(max-width:900px){.customer-grid{grid-template-columns:1fr}.customer-ticket-stats{grid-template-columns:repeat(2,1fr)}}
@media(max-width:639px){.customer-page-head{align-items:stretch}.customer-directory-search{grid-template-columns:1fr}.customer-directory-search button{width:100%}.customer-result-head{align-items:start;flex-direction:column;gap:.2rem}.customer-grid{padding:.7rem}.customer-picker-head{flex-direction:column}.selected-customer{grid-template-columns:1fr}.customer-ticket-create{padding:1rem}}
/* Structured staff ticket creation */
.staff-create-page{max-width:76rem;margin-inline:auto}.create-page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:2rem;margin-bottom:1.25rem}.create-page-head h1{margin:.2rem 0;color:#08376b;font-size:1.8rem;line-height:1.5}.create-page-head p:last-child{max-width:45rem;margin:0;color:#526b85;font-size:.85rem;line-height:1.9}.create-back{display:inline-flex;margin-bottom:.65rem;color:#1977ce;font-size:.75rem;font-weight:800}.customer-directory-link{display:flex;min-width:13rem;align-items:center;gap:.7rem;border:1px solid #cbddec;border-radius:1rem;background:#fff;padding:.8rem 1rem;color:#08376b;box-shadow:0 12px 28px -26px #08376b}.customer-directory-link>span{display:grid;width:2.4rem;height:2.4rem;place-items:center;border-radius:.7rem;background:#e7f5ff;color:#1977ce;font-size:1.2rem}.customer-directory-link b,.customer-directory-link small{display:block}.customer-directory-link b{font-size:.8rem}.customer-directory-link small{margin-top:.12rem;color:#60758b;font-size:.65rem}.create-progress{display:grid;grid-template-columns:repeat(3,1fr);margin:0 0 1.25rem;padding:0;overflow:hidden;border:1px solid #d8e5f0;border-radius:1rem;background:#fff;list-style:none}.create-progress li{position:relative;display:flex;align-items:center;gap:.65rem;padding:.75rem 1rem}.create-progress li+li{border-right:1px solid #e0e9f1}.create-progress li>span{display:grid;width:2rem;height:2rem;place-items:center;border-radius:.65rem;background:#eef3f7;color:#526b85;font-size:.75rem;font-weight:900}.create-progress li.active>span{background:#08376b;color:#fff}.create-progress b,.create-progress small{display:block}.create-progress b{color:#173a5e;font-size:.75rem}.create-progress small{margin-top:.1rem;color:#667d92;font-size:.62rem}.assisted-ticket-form{display:grid;grid-template-columns:minmax(0,1fr) 18.5rem;align-items:start;gap:1.25rem}.create-form-errors{grid-column:1/-1;border:1px solid #e9a6a6;border-radius:.8rem;background:#fff2f2;padding:.75rem;color:#8e2d2d}.create-form-main{display:grid;gap:1rem}.create-section{border:1px solid #d5e2ee;border-radius:1.1rem;background:#fff;padding:1.25rem;box-shadow:0 18px 40px -36px rgba(8,55,107,.7)}.create-section-head{display:flex;align-items:flex-start;gap:.75rem;margin-bottom:1.15rem;border-bottom:1px solid #e4edf4;padding-bottom:1rem}.section-number{display:grid;width:2.25rem;height:2.25rem;flex:0 0 auto;place-items:center;border-radius:.7rem;background:linear-gradient(135deg,#08376b,#1977ce);color:#fff;font-size:.8rem;font-weight:900}.create-section-head h2{margin:0;color:#123a63;font-size:1rem}.create-section-head p{margin:.25rem 0 0;color:#60758b;font-size:.72rem;line-height:1.75}.field-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.9rem}.field-control{display:grid;align-content:start;gap:.4rem;color:#244b72;font-size:.78rem;font-weight:800}.field-control>span{display:flex;align-items:center;gap:.35rem}.field-control em{color:#d36a00;font-style:normal}.field-control i{border-radius:999px;background:#eef3f7;padding:.12rem .4rem;color:#60758b;font-size:.58rem;font-style:normal;font-weight:600}.field-control input,.field-control select,.field-control textarea,.search-input-shell{width:100%;border:1px solid #b9cada;border-radius:.75rem;background:#fbfdff;color:#123a63}.field-control input,.field-control select{min-height:2.85rem}.field-control textarea{min-height:12rem;resize:vertical;line-height:1.9}.field-control input:focus,.field-control select:focus,.field-control textarea:focus,.search-input-shell:focus-within{border-color:#0693e3;outline:3px solid rgba(6,147,227,.12);background:#fff}.field-control small{color:#6a8094;font-size:.62rem;font-weight:500}.field-control .errorlist,.attachment-field .errorlist{margin:0;padding:0;color:#a32929;font-size:.68rem;list-style:none}.search-input-shell{display:flex;align-items:center;padding-inline:.75rem}.search-input-shell>span{color:#1977ce;font-size:1.2rem}.search-input-shell input{min-height:2.9rem;border:0!important;background:transparent!important;outline:0!important;box-shadow:none!important}.customer-search-box{margin-bottom:.65rem}.selected-customer{grid-template-columns:auto 1fr 1fr auto}.selected-customer-icon{display:grid;width:2rem;height:2rem;place-items:center;border-radius:999px;background:#1f8b58;color:#fff;font-weight:900}.customer-lookup-status{border-right:3px solid #8ba4ba}.customer-lookup-status.is-found{border-right-color:#25875a}.customer-lookup-status.is-new{border-right-color:#e38a00}.location-hint{margin:.65rem 0 0;color:#647b91;font-size:.65rem}.message-field{margin-bottom:1rem}.attachment-field{position:relative;display:flex;align-items:center;gap:.75rem;border:1px dashed #91b4d0;border-radius:.85rem;background:#f6fbff;padding:.9rem;color:#173a5e;cursor:pointer}.attachment-field:hover{border-color:#0693e3;background:#edf8ff}.attachment-field .attachment-icon{display:grid;width:2.35rem;height:2.35rem;flex:0 0 auto;place-items:center;border-radius:.7rem;backgrLine truncated
@media(max-width:1000px){.assisted-ticket-form{grid-template-columns:1fr}.create-summary{order:-1}.summary-sticky{position:static}.summary-sticky dl{display:grid;grid-template-columns:repeat(3,1fr);gap:.75rem}.summary-sticky dl div{border-bottom:0}.secure-delivery{display:none}.create-submit{width:auto}.create-cancel{padding-bottom:.9rem}}
@media(max-width:639px){.create-page-head{align-items:stretch;flex-direction:column;gap:1rem}.create-page-head h1{font-size:1.4rem}.customer-directory-link{min-width:0}.create-progress{grid-template-columns:1fr}.create-progress li{padding:.65rem .8rem}.create-progress li+li{border-top:1px solid #e0e9f1;border-right:0}.create-progress small{display:none}.create-section{padding:1rem}.field-grid{grid-template-columns:1fr}.field-spacer{display:none}.selected-customer{grid-template-columns:auto 1fr}.selected-customer>div:nth-of-type(2){grid-column:2}.selected-customer button{grid-column:1/-1;border-top:1px solid #bee0f3}.summary-sticky dl{grid-template-columns:1fr}.summary-sticky dl div{padding:.45rem 0}.attachment-field{align-items:flex-start;flex-wrap:wrap}.attachment-field input[type=file]{width:100%;max-width:none;margin:0}.create-summary{order:initial}.summary-sticky>header,.summary-sticky dl,.secure-delivery{display:none}.summary-sticky{position:sticky;bottom:4.7rem;z-index:20;border-color:#acd2eb;box-shadow:0 -12px 35px -25px #08376b}.create-submit{margin:.45rem}.create-cancel{display:none}}
/* Profile completion guidance and truthful PWA installation states */
.profile-completion-notice{display:grid;grid-template-columns:auto minmax(0,1fr);gap:1rem;margin:-.5rem 0 1.5rem;border:1px solid #a9d5ef;border-right:4px solid var(--color-sea);border-radius:1.15rem;background:linear-gradient(135deg,#fff,#edf8ff);padding:1.15rem;box-shadow:0 16px 38px -34px #08376b}.profile-completion-icon{display:grid;width:2.75rem;height:2.75rem;place-items:center;border-radius:.8rem;background:#dff2ff;color:#1977ce;font-size:1.25rem;font-weight:900}.profile-completion-notice h2{margin:0;color:#08376b;font-size:1rem}.profile-completion-notice p{margin:.35rem 0 0;color:#405d78;font-size:.78rem;line-height:1.9}.profile-completion-actions{display:flex;align-items:center;gap:1rem;margin-top:.85rem}.profile-completion-actions .button{min-height:2.55rem;padding:.5rem 1rem}.profile-completion-actions>a:last-child{color:#526b85;font-size:.7rem;font-weight:700}.pwa-install-icon{width:3.5rem;height:3.5rem;flex:none;border-radius:.85rem;object-fit:cover}.pwa-install-copy{min-width:0;flex:1}.pwa-install-actions{display:flex;gap:.4rem}.pwa-install-guidance{border-color:#fac66c}.pwa-install-guidance .pwa-install-copy small{color:#805300}
@media(max-width:639px){.profile-completion-notice{grid-template-columns:1fr;margin-top:0}.profile-completion-icon{width:2.4rem;height:2.4rem}.profile-completion-actions{align-items:stretch;flex-direction:column;gap:.65rem}.profile-completion-actions>a{text-align:center}.pwa-install{display:grid;grid-template-columns:auto 1fr;align-items:center}.pwa-install-actions{grid-column:1/-1}.pwa-install-actions button{flex:1}}
.composer-send-icon{cursor:pointer;user-select:none}.composer-send-icon:focus-visible{outline:3px solid rgba(6,147,227,.25);outline-offset:2px}
/* Non-blocking guidance when current-page timing/length signals resemble rapid chat. */
.chat-coach{@apply mt-2 grid grid-cols-[auto_1fr_auto] items-start gap-2.5 rounded-xl border border-amber-400/45 bg-amber-50 px-3 py-2.5 text-right;animation:chat-coach-in .2s ease-out}.chat-coach[hidden]{display:none}.chat-coach-icon{@apply grid size-7 place-items-center rounded-lg bg-amber-400/20 text-sm text-amber-800}.chat-coach b{@apply block text-[11px] text-amber-800}.chat-coach p{@apply mt-0.5 text-[10px] leading-5 text-amber-800/80}.chat-coach button{@apply grid size-7 min-h-0 place-items-center rounded-full bg-transparent p-0 text-base font-normal text-amber-800/60 shadow-none hover:bg-amber-400/15 hover:text-amber-800}@keyframes chat-coach-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
.chat-coach-floating{position:fixed;z-index:90;left:1rem;bottom:1rem;width:min(28rem,calc(100vw - 2rem));margin:0;box-shadow:0 18px 50px -24px rgba(8,55,107,.7)}
@media(max-width:639px){.chat-coach-floating{right:.65rem;bottom:5.65rem;left:.65rem;width:auto;padding:.65rem .75rem}}
/* Comfortable close target for the short-lived chat guidance toast. */
.chat-coach [data-chat-coach-dismiss]{width:2.5rem;height:2.5rem;min-height:2.5rem;border:1px solid rgba(217,119,6,.2);background:rgba(255,255,255,.65);font-size:1.5rem;line-height:1;color:rgba(120,53,15,.78);touch-action:manipulation;transition:background-color .15s ease,border-color .15s ease,color .15s ease}
.chat-coach [data-chat-coach-dismiss]:hover{border-color:rgba(217,119,6,.4);background:rgba(251,191,36,.22);color:#78350f}
.chat-coach [data-chat-coach-dismiss]:focus-visible{outline:2px solid #d97706;outline-offset:2px}
/* Compact message actions: lower-left trigger, two choices, focused editor. */
.message-menu{top:auto!important;right:auto!important;bottom:.35rem!important;left:.35rem!important}.message-menu-panel{top:auto;right:auto!important;bottom:calc(100% + .35rem);left:0!important;margin:0;width:15rem}.message-menu-choices{@apply grid gap-1 p-1.5}.message-menu-choices form{@apply m-0}.message-choice{@apply m-0 flex min-h-12 w-full items-center justify-start gap-2.5 rounded-xl bg-transparent px-3 py-2 text-right text-ink shadow-none hover:bg-mint hover:text-sea}.message-choice>span:nth-child(2){@apply min-w-0 flex-1}.message-choice b,.message-choice small{@apply block}.message-choice b{@apply text-xs}.message-choice small{@apply mt-0.5 text-[9px] font-medium text-ink/45}.message-choice-icon{@apply grid size-8 shrink-0 place-items-center rounded-lg bg-mint text-base text-sea}.message-choice-arrow{@apply text-lg text-ink/25}.message-choice-delete{@apply text-red-700 hover:bg-red-50 hover:text-red-700}.message-choice-delete .message-choice-icon{@apply bg-red-50 text-red-700}.message-editor-back{@apply grid size-8 min-h-0 place-items-center rounded-full bg-transparent p-0 text-base text-ink/50 shadow-none hover:bg-ink/5 hover:text-ink}.message-edit-meta{@apply mt-1.5 flex justify-between gap-2 text-[8px] text-ink/40}@media(max-width:639px){.message-menu-panel{top:auto!important;right:.75rem!important;bottom:5rem!important;left:.75rem!important;width:auto}.message-menu-choices{@apply p-2}.message-choice{@apply min-h-14}}
+5
View File
@@ -0,0 +1,5 @@
(()=>{var nt=!1,it=!1,W=[],ot=-1;function Ut(e){Rn(e)}function Rn(e){W.includes(e)||W.push(e),Mn()}function Wt(e){let t=W.indexOf(e);t!==-1&&t>ot&&W.splice(t,1)}function Mn(){!it&&!nt&&(nt=!0,queueMicrotask(Nn))}function Nn(){nt=!1,it=!0;for(let e=0;e<W.length;e++)W[e](),ot=e;W.length=0,ot=-1,it=!1}var T,N,$,at,st=!0;function Gt(e){st=!1,e(),st=!0}function Jt(e){T=e.reactive,$=e.release,N=t=>e.effect(t,{scheduler:r=>{st?Ut(r):r()}}),at=e.raw}function ct(e){N=e}function Yt(e){let t=()=>{};return[n=>{let i=N(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),$(i))},i},()=>{t()}]}function ve(e,t){let r=!0,n,i=N(()=>{let o=e();JSON.stringify(o),r?n=o:queueMicrotask(()=>{t(o,n),n=o}),r=!1});return()=>$(i)}var Xt=[],Zt=[],Qt=[];function er(e){Qt.push(e)}function te(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,Zt.push(t))}function Ae(e){Xt.push(e)}function Oe(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function lt(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}function tr(e){for(e._x_effects?.forEach(Wt);e._x_cleanups?.length;)e._x_cleanups.pop()()}var ut=new MutationObserver(mt),ft=!1;function ue(){ut.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),ft=!0}function dt(){kn(),ut.disconnect(),ft=!1}var le=[];function kn(){let e=ut.takeRecords();le.push(()=>e.length>0&&mt(e));let t=le.length;queueMicrotask(()=>{if(le.length===t)for(;le.length>0;)le.shift()()})}function m(e){if(!ft)return e();dt();let t=e();return ue(),t}var pt=!1,Se=[];function rr(){pt=!0}function nr(){pt=!1,mt(Se),Se=[]}function mt(e){if(pt){Se=Se.concat(e);return}let t=[],r=new Set,n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].removedNodes.forEach(s=>{s.nodeType===1&&s._x_marker&&r.add(s)}),e[o].addedNodes.forEach(s=>{if(s.nodeType===1){if(r.has(s)){r.delete(s);return}s._x_marker||t.push(s)}})),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{lt(s,o)}),n.forEach((o,s)=>{Xt.forEach(a=>a(s,o))});for(let o of r)t.some(s=>s.contains(o))||Zt.forEach(s=>s(o));for(let o of t)o.isConnected&&Qt.forEach(s=>s(o));t=null,r=null,n=null,i=null}function Ce(e){return z(B(e))}function k(e,t,r){return e._x_dataStack=[t,...B(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function B(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?B(e.host):e.parentNode?B(e.parentNode):[]}function z(e){return new Proxy({objects:e},Dn)}var Dn={ownKeys({objects:e}){return Array.from(new Set(e.flatMap(t=>Object.keys(t))))},has({objects:e},t){return t==Symbol.unscopables?!1:e.some(r=>Object.prototype.hasOwnProperty.call(r,t)||Reflect.has(r,t))},get({objects:e},t,r){return t=="toJSON"?Pn:Reflect.get(e.find(n=>Reflect.has(n,t))||{},t,r)},set({objects:e},t,r,n){let i=e.find(s=>Object.prototype.hasOwnProperty.call(s,t))||e[e.length-1],o=Object.getOwnPropertyDescriptor(i,t);return o?.set&&o?.get?o.set.call(n,r)||!0:Reflect.set(i,t,r)}};function Pn(){return Reflect.ownKeys(this).reduce((t,r)=>(t[r]=Reflect.get(this,r),t),{})}function Te(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0||typeof s=="object"&&s!==null&&s.__v_skip)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function Re(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>In(n,i),s=>ht(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function In(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function ht(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),ht(e[t[0]],t.slice(1),r)}}var ir={};function y(e,t){ir[e]=t}function fe(e,t){let r=Ln(t);return Object.entries(ir).forEach(([n,i])=>{Object.defineProperty(e,`$${n}`,{get(){return i(t,r)},enumerable:!1})}),e}function Ln(e){let[t,r]=_t(e),n={interceptor:Re,...t};return te(e,r),n}function or(e,t,r,...n){try{return r(...n)}catch(i){re(i,e,t)}}function re(e,tLine truncated
${r?'Expression: "'+r+`"
`:""}`,t),setTimeout(()=>{throw e},0)}var Me=!0;function ke(e){let t=Me;Me=!1;let r=e();return Me=t,r}function R(e,t,r={}){let n;return x(e,t)(i=>n=i,r),n}function x(...e){return sr(...e)}var sr=xt;function ar(e){sr=e}function xt(e,t){let r={};fe(r,e);let n=[r,...B(e)],i=typeof t=="function"?$n(n,t):Fn(n,t,e);return or.bind(null,e,t,i)}function $n(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(z([n,...e]),i);Ne(r,o)}}var gt={};function jn(e,t){if(gt[e])return gt[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e.trim())||/^(let|const)\s/.test(e.trim())?`(async()=>{ ${e} })()`:e,o=(()=>{try{let s=new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`);return Object.defineProperty(s,"name",{value:`[Alpine] ${e}`}),s}catch(s){return re(s,t,e),Promise.resolve()}})();return gt[e]=o,o}function Fn(e,t,r){let n=jn(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=z([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>re(l,r,t));n.finished?(Ne(i,n.result,a,s,r),n.result=void 0):c.then(l=>{Ne(i,l,a,s,r)}).catch(l=>re(l,r,t)).finally(()=>n.result=void 0)}}}function Ne(e,t,r,n,i){if(Me&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Ne(e,s,r,n)).catch(s=>re(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}var wt="x-";function C(e=""){return wt+e}function cr(e){wt=e}var De={};function d(e,t){return De[e]=t,{before(r){if(!De[r]){console.warn(String.raw`Cannot find directive \`${r}\`. \`${e}\` will use the default order of execution`);return}let n=G.indexOf(r);G.splice(n>=0?n:G.indexOf("DEFAULT"),0,e)}}}function lr(e){return Object.keys(De).includes(e)}function pe(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,c])=>({name:a,value:c})),s=Et(o);o=o.map(a=>s.find(c=>c.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(dr((o,s)=>n[o]=s)).filter(mr).map(zn(n,r)).sort(Kn).map(o=>Bn(e,o))}function Et(e){return Array.from(e).map(dr()).filter(t=>!mr(t))}var yt=!1,de=new Map,ur=Symbol();function fr(e){yt=!0;let t=Symbol();ur=t,de.set(t,[]);let r=()=>{for(;de.get(t).length;)de.get(t).shift()();de.delete(t)},n=()=>{yt=!1,r()};e(r),n()}function _t(e){let t=[],r=a=>t.push(a),[n,i]=Yt(e);return t.push(i),[{Alpine:K,effect:n,cleanup:r,evaluateLater:x.bind(x,e),evaluate:R.bind(R,e)},()=>t.forEach(a=>a())]}function Bn(e,t){let r=()=>{},n=De[t.type]||r,[i,o]=_t(e);Oe(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),yt?de.get(ur).push(n):n())};return s.runCleanups=o,s}var Pe=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Ie=e=>e;function dr(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=pr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var pr=[];function ne(e){pr.push(e)}function mr({name:e}){return hr().test(e)}var hr=()=>new RegExp(`^${wt}([^:^.]+)\\b`);function zn(e,t){return({name:r,value:n})=>{let i=r.match(hr()),o=r.match(/:([a-zA-Z0-9\-_:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var bt="DEFAULT",G=["ignore","ref","data","id","anchor","bind","init","for","model","modelable","transition","show","if",bt,"teleport"];function Kn(e,t){let r=G.indexOf(e.type)===-1?bt:e.type,n=G.indexOf(t.type)===-1?bt:t.type;return G.indexOf(r)-G.indexOf(n)}function J(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function D(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>D(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)D(n,t,!1),n=n.nextElementSibling}function E(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}var _r=!1;function gr(){_r&&E("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),_r=!0,document.body||E("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),J(document,"alpine:init"),J(document,"alpine:initializing"),ue(),er(t=>S(t,D)),te(t=>P(t)),Ae((t,r)=>{pe(t,r).forEach(n=>n())});let e=t=>!Y(t.parentElement,!0);Array.from(document.querySelectorAll(br().join(","))).filter(e).forEach(t=>{S(t)}),J(document,"alpine:initialized"),setTimeout(()=>{Vn()})}var vt=[],xr=[];function yr(){return vt.map(e=>e())}function br(){return vt.concat(xr).map(e=>e())}function Le(e){vt.push(e)}function $e(e){xr.push(e)}function Y(e,t=!1){return j(e,r=>{if((t?br():yr()).some(i=>r.matches(i)))return!0})}function j(e,t){if(e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),!!e.parentElement)return j(e.parentElement,t)}}function wrLine truncated
+10
View File
@@ -0,0 +1,10 @@
/*!
* Compressor.js v1.3.0
* https://fengyuanchen.github.io/compressorjs
*
* Copyright 2018-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2026-04-06T07:12:45.816Z
*/
((e,t)=>{"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Compressor=t()})(this,function(){function a(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,o(i.key),i)}}function s(){return(s=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r,i=arguments[t];for(r in i)!{}.hasOwnProperty.call(i,r)||(e[r]=i[r])}return e}).apply(null,arguments)}function t(t,e){var r,i=Object.keys(t);return Object.getOwnPropertySymbols&&(r=Object.getOwnPropertySymbols(t),e&&(r=r.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),i.push.apply(i,r)),i}function n(i){for(var e=1;e<arguments.length;e++){var a=null!=arguments[e]?arguments[e]:{};e%2?t(Object(a),!0).forEach(function(e){var t,r;t=i,r=a[e=e],(e=o(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r}):Object.getOwnPropertyDescriptors?Object.defineProperties(i,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach(function(e){Object.defineProperty(i,e,Object.getOwnPropertyDescriptor(a,e))})}return i}function o(e){e=((e,t)=>{if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0===r)return("string"===t?String:Number)(e);if("object"!=typeof(r=r.call(e,t||"default")))return r;throw new TypeError("@@toPrimitive must return a primitive value.")})(e,"string");return"symbol"==typeof e?e:e+""}function x(e){return 0<e&&e<1/0}var e,r,l,c,h,u,f,d,i={exports:{}},O=(e=i,"undefined"!=typeof window&&(l=(r=window).HTMLCanvasElement&&r.HTMLCanvasElement.prototype,c=r.Blob&&(()=>{try{return Boolean(new Blob)}catch(e){return!1}})(),h=c&&r.Uint8Array&&(()=>{try{return 100===new Blob([new Uint8Array(100)]).size}catch(e){return!1}})(),u=r.BlobBuilder||r.WebKitBlobBuilder||r.MozBlobBuilder||r.MSBlobBuilder,f=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,d=(c||u)&&r.atob&&r.ArrayBuffer&&r.Uint8Array&&function(e){var t,r,i,a,n,o=e.match(f);if(!o)throw new Error("invalid data URI");for(t=o[2]?o[1]:"text/plain"+(o[3]||";charset=US-ASCII"),n=!!o[4],e=e.slice(o[0].length),r=(n?atob:decodeURIComponent)(e),o=new ArrayBuffer(r.length),i=new Uint8Array(o),a=0;a<r.length;a+=1)i[a]=r.charCodeAt(a);return c?new Blob([h?i:o],{type:t}):((n=new u).append(o),n.getBlob(t))},r.HTMLCanvasElement&&!l.toBlob&&(l.mozGetAsFile?l.toBlob=function(e,t,r){var i=this;setTimeout(function(){r&&l.toDataURL&&d?e(d(i.toDataURL(t,r))):e(i.mozGetAsFile("blob",t))})}:l.toDataURL&&d&&(l.msToBlob?l.toBlob=function(e,t,r){var i=this;setTimeout(function(){(t&&"image/png"!==t||r)&&l.toDataURL&&d?e(d(i.toDataURL(t,r))):e(i.msToBlob(t))})}:l.toBlob=function(e,t,r){var i=this;setTimeout(function(){e(d(i.toDataURL(t,r)))})})),e.exports?e.exports=d:r.dataURLtoBlob=d),i.exports),m={strict:!0,checkOrientation:!0,retainExif:!1,maxWidth:1/0,maxHeight:1/0,minWidth:0,minHeight:0,width:void 0,height:void 0,resize:"none",quality:.8,mimeType:"auto",convertTypes:["image/png"],convertSize:5e6,beforeDraw:null,drew:null,success:null,error:null},g="undefined"!=typeof window&&void 0!==window.document?window:{},p=Array.prototype.slice;function j(e){return Array.from?Array.from(e):p.call(e)}var b=/^image\/.+$/;function T(e){return b.test(e)}var y=String.fromCharCode;var w=g.btoa;function A(e,t){for(var r=[],i=new Uint8Array(e);0<i.length;)r.push(y.apply(null,j(i.subarray(0,8192)))),i=i.subarray(8192);return"data:".concat(t,";base64,").concat(w(r.join("")))}function v(e){var t,r,i,a,n,o,l,s=new DataView(e);try{if(255===s.getUint8(0)&&216===s.getUint8(1))for(var c=s.byteLength,h=2;h+1<c;){if(255===s.getUint8(h)&&225===s.getUint8(h+1)){r=h;break}h+=1}if(i=r&&(a=r+10,"Exif"===((e,t,r)=>{var i,a="";for(r+=t,i=t;i<r;i+=1)a+=y(e.getUint8(i));return a})(s,r+4,4))&&((l=18761===(n=s.getUint16(a)))||19789===n)&&42===s.getUint16(a+2,l)&&8<=(o=s.getUint32(a+4,l))?a+o:i)for(var u,f=s.getUint16(i,l),d=0;d<f;d+=1)if(u=i+12*d+2,274===s.getUint16(u,l)){u+=8,t=s.getUint16(u,l),s.setUint16(u,1,l);break}}catch(e){t=1}return t}var B=/\.\d*(?:0|9){12}\d*$/;function R(e,t){t=1<arguments.length&&void 0!==t?t:1e11;return B.test(e)?Math.round(e*t)/t:e}function E(e,t){var r,i=e.aspectRatio,a=e.height,e=e.width,t=1<arguments.length&&void 0!==t?t:"none",n=x(e),o=x(a);return n&&o?(r=a*i,("contain"===t||"none"===t)&&e<r||"cover"===t&&r<e?a=e/i:e=a*i):n?a=e/i:o&&(e=a*i),{width:e,height:a}}var U=g.ArrayBuffer,k=g.FileReader,D=g.URL||g.webkitURL,M=/\.\w+$/,L=g.Compressor;return(()=>{function r(e,t){if(!(this instanceof r))throw new TypeError("Cannot call a class as a function");this.file=e,this.exif=[],this.image=new Image,this.options=n(n({},m),t),this.aborted=!1,this.result=null,this.init()}return e=r,i=[{key:"noConflict",value:function(){return window.Compressor=L,r}},{key:"setDefaults",value:function(e){s(m,e)}}],(t=[{key:"init",value:function(){var i,a,n,eLine truncated
+1
View File
@@ -0,0 +1 @@
var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,addClass:null,removeClass:null,toggleClass:null,takeClass:null,swap:null,defineExtension:null,removeExtension:null,logAll:null,logNone:null,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,allowScriptTags:true,inlineScriptNonce:"",inlineStyleNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",scrollBehavior:"instant",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:["get","delete"],selfRequestsOnly:true,ignoreTitle:false,scrollIntoViewOnBoost:true,triggerSpecsCache:null,disableInheritance:false,responseHandling:[{code:"204",swap:false},{code:"[23]..",swap:true},{code:"[45]..",swap:false,error:true}],allowNestedOobSwaps:true},parseInterval:null,_:null,version:"2.0.3"};Q.onLoad=j;Q.process=kt;Q.on=ye;Q.off=be;Q.trigger=de;Q.ajax=Rn;Q.find=r;Q.findAll=x;Q.closest=g;Q.remove=z;Q.addClass=K;Q.removeClass=G;Q.toggleClass=W;Q.takeClass=Z;Q.swap=$e;Q.defineExtension=Fn;Q.removeExtension=Bn;Q.logAll=V;Q.logNone=_;Q.parseInterval=h;Q._=e;const n={addTriggerHandler:St,bodyContains:le,canAccessLocalStorage:B,findThisElement:Se,filterValues:dn,swap:$e,hasAttribute:s,getAttributeValue:te,getClosestAttributeValue:re,getClosestMatch:i,getExpressionVars:En,getHeaders:fn,getInputValues:cn,getInternalData:ie,getSwapSpecification:gn,getTriggerSpecs:st,getTarget:Ee,makeFragment:P,mergeObjects:ce,makeSettleInfo:xn,oobSwap:He,querySelectorExt:ae,settleImmediately:Kt,shouldCancel:dt,triggerEvent:de,triggerErrorEvent:fe,withExtensions:Ft};const o=["get","post","put","delete","patch"];const R=o.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");function h(e){if(e==undefined){return undefined}let t=NaN;if(e.slice(-2)=="ms"){t=parseFloat(e.slice(0,-2))}else if(e.slice(-1)=="s"){t=parseFloat(e.slice(0,-1))*1e3}else if(e.slice(-1)=="m"){t=parseFloat(e.slice(0,-1))*1e3*60}else{t=parseFloat(e)}return isNaN(t)?undefined:t}function ee(e,t){return e instanceof Element&&e.getAttribute(t)}function s(e,t){return!!e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function te(e,t){return ee(e,t)||ee(e,"data-"+t)}function c(e){const t=e.parentElement;if(!t&&e.parentNode instanceof ShadowRoot)return e.parentNode;return t}function ne(){return document}function m(e,t){return e.getRootNode?e.getRootNode({composed:t}):ne()}function i(e,t){while(e&&!t(e)){e=c(e)}return e||null}function H(e,t,n){const r=te(t,n);const o=te(t,"hx-disinherit");var i=te(t,"hx-inherit");if(e!==t){if(Q.config.disableInheritance){if(i&&(i==="*"||i.split(" ").indexOf(n)>=0)){return r}else{return null}}if(o&&(o==="*"||o.split(" ").indexOf(n)>=0)){return"unset"}}return r}function re(t,n){let r=null;i(t,function(e){return!!(r=H(t,ue(e),n))});if(r!=="unset"){return r}}function d(e,t){const n=e instanceof Element&&(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector);return!!n&&n.call(e,t)}function T(e){const t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;const n=t.exec(e);if(n){return n[1].toLowerCase()}else{return""}}function q(e){const t=new DOMParser;return t.parseFromString(e,"text/html")}function L(e,t){while(t.childNodes.length>0){e.append(t.childNodes[0])}}function N(e){const t=ne().createElement("script");se(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(Q.config.inlineScriptNonce){t.nonce=Q.config.inlineScriptNonce}return t}function A(e){return e.matches("script")&&(e.type==="text/javascript"||e.type==="module"||e.type==="")}function I(e){Array.from(e.querySelectorAll("script")).forEach(e=>{if(A(e)){const t=N(e);const n=e.parentNode;try{n.insertBefore(t,e)}catch(e){C(e)}finally{e.remove()}}})}function P(e){const t=e.replace(/<head(\s[^>]*)?>[\s\S]*?<\/head>/i,"");const n=T(t);let r;if(n==="html"){r=new DocumentFragment;const i=q(e);L(r,i.body);r.title=i.title}else if(n==="body"){r=new DocumentFragment;const i=q(t);L(r,i.body);r.title=i.title}else{const i=q('<body><template class="internal-htmx-wrapper">'+t+"</template></body>");r=i.querySelector("template").content;r.title=i.title;var o=r.querySelector("title");if(o&&o.parentNode===r){o.remove();r.title=o.innerText}}if(r){if(Q.config.allowScriptTags){I(r)}else{r.querySelectorAll("script").forEach(e=>e.remove())}}return r}function oe(e){if(e){e()}}function t(e,t){return Object.prototype.toStrinLine truncated