/* اوميكسوس — الفني · iOS design, one stylesheet for the iPhone shell, the
   Android build and the browser (docs/2026-09-22-ios-redesign.md).
   Every colour is a token with a light and a dark value; the html element
   carries .dark when the dark set is in force (app.js decides from the
   picker and the phone). Light is the default. Content surfaces carry no
   shadow; glass (blur) is for the bars that float over content only. */
:root{
  color-scheme:light;
  --bg:#F2F2F7;--card:#FFFFFF;--card2:#F2F2F7;
  --fill:rgba(120,120,128,.12);--fill2:rgba(120,120,128,.2);
  --ink:#000000;--muted:rgba(60,60,67,.6);--faint:rgba(60,60,67,.3);--hair:rgba(60,60,67,.29);
  --accent:#0077C8;--accent2:#005FA3;--accent-ink:#0077C8;--accent-soft:rgba(0,119,200,.12);
  --accent-grad:var(--accent);
  --on-accent:#FFFFFF;--on-red:#FFFFFF;
  --accent-glow-wide:rgba(0,119,200,.35);
  --green:#34C759;--green-soft:rgba(52,199,89,.16);--green-halo:rgba(52,199,89,.22);--ok:#1F7A35;
  --red:#FF3B30;--red-soft:rgba(255,59,48,.12);--red-glow:rgba(255,59,48,.3);--red-halo:rgba(255,59,48,.35);
  --amber:#FF9500;--amber-soft:rgba(255,149,0,.14);--amber-ink:#B25E00;
  --shadow:none;
  --shadow-lg:0 20px 60px rgba(0,0,0,.28);
  --sheet-shadow:0 -6px 30px rgba(0,0,0,.12);
  --seg-on:#FFFFFF;--seg-shadow:0 3px 8px rgba(0,0,0,.12),0 3px 1px rgba(0,0,0,.04);
  --glass:rgba(249,249,249,.8);--tabs-bg:rgba(249,249,249,.78);--glass-edge:rgba(255,255,255,.6);
  --scrim:rgba(0,0,0,.4);--alarm-scrim:rgba(0,0,0,.45);
  --sheet-grip:rgba(60,60,67,.3);
  --toast-bg:rgba(28,28,30,.92);--toast-ink:#FFFFFF;
  --empty-ic:rgba(60,60,67,.3);--ghost-line:rgba(60,60,67,.29);
  --sw-off:#E9E9EA;--sw-knob:#FFFFFF;--sw-knob-shadow:0 3px 8px rgba(0,0,0,.15),0 1px 1px rgba(0,0,0,.16);
  --bub-shadow:none;
  --bub-in:#E9E9EB;--bub-in-ink:#000000;--bub-in-meta:rgba(60,60,67,.6);
  --bub-out:#0077C8;--bub-out-tail:#0077C8;--bub-out-ink:#FFFFFF;--bub-out-meta:rgba(255,255,255,.78);
  --bub-peer:#F2F2F7;--bub-peer-ink:#000000;--bub-peer-line:rgba(60,60,67,.2);
  --bub-div:rgba(120,120,128,.12);
  --quote-bg:rgba(0,0,0,.05);--quote-ink:rgba(60,60,67,.7);--quote-me-bg:rgba(255,255,255,.18);--quote-me-line:rgba(255,255,255,.85);
  --link-in:#0077C8;--link-out:#FFFFFF;--orig-line:rgba(0,0,0,.14);
  --file-chip:rgba(0,0,0,.07);--file-chip-me:rgba(255,255,255,.2);
  --tick:rgba(255,255,255,.75);--tick-read:#9BEBFF;--tick-fail:#FFD1CE;
  --media-ph:rgba(0,0,0,.06);
  --media-scrim:rgba(0,0,0,.42);--media-scrim-strong:rgba(0,0,0,.5);--media-ink:#FFFFFF;
  --spin-track:rgba(255,255,255,.5);--spin-head:#FFFFFF;
  --vn-av:rgba(120,120,128,.3);--vn-av-me:rgba(255,255,255,.28);
  --vn-mic-bg:#FFFFFF;--vn-mic-shadow:0 1px 3px rgba(0,0,0,.2);
  --vn-play:#0077C8;--vn-play-me:#FFFFFF;
  --vn-bars:rgba(60,60,67,.35);--vn-bars-me:rgba(255,255,255,.5);--vn-played:#0077C8;--vn-played-me:#FFFFFF;
  --vn-knob:#0077C8;--vn-knob-me:#FFFFFF;--vn-knob-shadow:0 1px 3px rgba(0,0,0,.3);
  --vn-foot:rgba(60,60,67,.6);--vn-foot-me:rgba(255,255,255,.78);
  --vn-rate:rgba(0,0,0,.07);--vn-rate-ink:rgba(60,60,67,.8);
  --vn-rate-me:rgba(255,255,255,.22);--vn-rate-ink-me:#FFFFFF;
  /* The case disc: one flat system colour each, all dark enough for white
     12px bold (5:1 and up). Same values in the dark set. */
  --tone-new:#0077C8;--tone-arch:#6E6E73;--tone-late:#D70015;--tone-warr:#C93400;--tone-shop:#8944AB;--tone-back:#1F7A35;
  --shop-tag:#8944AB;
  --tab-h:58px;--nav-h:44px;--r:16px;
}
:root.dark{
  color-scheme:dark;
  --bg:#000000;--card:#1C1C1E;--card2:#2C2C2E;
  --fill:rgba(120,120,128,.24);--fill2:rgba(120,120,128,.32);
  --ink:#FFFFFF;--muted:rgba(235,235,245,.6);--faint:rgba(235,235,245,.3);--hair:rgba(84,84,88,.65);
  --accent:#38BDF8;--accent2:#0EA5E9;--accent-ink:#38BDF8;--accent-soft:rgba(56,189,248,.18);
  --on-accent:#0B1A2B;--on-red:#FFFFFF;
  --accent-glow-wide:rgba(56,189,248,.35);
  --green:#30D158;--green-soft:rgba(48,209,88,.18);--green-halo:rgba(48,209,88,.24);--ok:#30D158;
  --red:#FF453A;--red-soft:rgba(255,69,58,.16);--red-glow:rgba(255,69,58,.3);--red-halo:rgba(255,69,58,.35);
  --amber:#FF9F0A;--amber-soft:rgba(255,159,10,.16);--amber-ink:#FF9F0A;
  --shadow-lg:0 20px 60px rgba(0,0,0,.6);
  --sheet-shadow:0 -6px 30px rgba(0,0,0,.5);
  --seg-on:#636366;--seg-shadow:0 3px 8px rgba(0,0,0,.3);
  --glass:rgba(28,28,30,.74);--tabs-bg:rgba(28,28,30,.72);--glass-edge:rgba(255,255,255,.12);
  --scrim:rgba(0,0,0,.55);--alarm-scrim:rgba(0,0,0,.6);
  --sheet-grip:rgba(235,235,245,.3);
  --toast-bg:rgba(44,44,46,.94);--toast-ink:#FFFFFF;
  --empty-ic:rgba(235,235,245,.3);--ghost-line:rgba(84,84,88,.65);
  --sw-off:#39393D;--sw-knob:#FFFFFF;--sw-knob-shadow:0 3px 8px rgba(0,0,0,.4);
  --bub-in:#262629;--bub-in-ink:#FFFFFF;--bub-in-meta:rgba(235,235,245,.6);
  --bub-out:#0B6BC7;--bub-out-tail:#0B6BC7;--bub-out-ink:#FFFFFF;--bub-out-meta:rgba(255,255,255,.78);
  --bub-peer:#2C2C2E;--bub-peer-ink:#FFFFFF;--bub-peer-line:rgba(84,84,88,.65);
  --bub-div:rgba(120,120,128,.24);
  --quote-bg:rgba(255,255,255,.08);--quote-ink:rgba(235,235,245,.75);--quote-me-bg:rgba(0,0,0,.22);--quote-me-line:rgba(255,255,255,.85);
  --link-in:#38BDF8;--link-out:#FFFFFF;--orig-line:rgba(255,255,255,.18);
  --file-chip:rgba(255,255,255,.1);--file-chip-me:rgba(255,255,255,.16);
  --tick:rgba(255,255,255,.7);--tick-read:#9BEBFF;--tick-fail:#FFB4AE;
  --media-ph:rgba(255,255,255,.06);
  --media-scrim:rgba(0,0,0,.5);--media-scrim-strong:rgba(0,0,0,.55);--media-ink:#FFFFFF;
  --spin-track:rgba(255,255,255,.4);--spin-head:#FFFFFF;
  --vn-av:rgba(120,120,128,.35);--vn-av-me:rgba(255,255,255,.22);
  --vn-mic-bg:#1C1C1E;--vn-mic-shadow:0 1px 3px rgba(0,0,0,.5);
  --vn-play:#FFFFFF;--vn-play-me:#FFFFFF;
  --vn-bars:rgba(235,235,245,.35);--vn-bars-me:rgba(255,255,255,.45);--vn-played:#38BDF8;--vn-played-me:#FFFFFF;
  --vn-knob:#38BDF8;--vn-knob-me:#FFFFFF;--vn-knob-shadow:0 1px 3px rgba(0,0,0,.5);
  --vn-foot:rgba(235,235,245,.6);--vn-foot-me:rgba(255,255,255,.78);
  --vn-rate:rgba(255,255,255,.12);--vn-rate-ink:rgba(235,235,245,.8);
  --vn-rate-me:rgba(255,255,255,.18);--vn-rate-ink-me:#FFFFFF;
  --shop-tag:#BF5AF2;
}

/* base */
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{background:var(--bg);color:var(--ink);direction:rtl;font-size:17px;line-height:1.35;
  font-family:-apple-system,"SF Pro Text","SF Arabic",system-ui,"Segoe UI",Roboto,"Noto Naskh Arabic UI",sans-serif;
  -webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent;overscroll-behavior-y:none}
/* iPhone Safari: no pinch, no double-tap zoom, no zoom on focus (17px inputs) */
html,body{touch-action:manipulation;-webkit-text-size-adjust:100%}
svg{display:block}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
input,select,textarea{font:inherit}
/* Nothing in the app shows a scrollbar; every list still scrolls. */
*{scrollbar-width:none;-ms-overflow-style:none}
*::-webkit-scrollbar{display:none;width:0;height:0}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* shell — no header anywhere: the tab bar says where he is. The top inset is
   the status bar of the native shell (edge to edge); a Home Screen app and
   the Android build sit under an opaque bar and read it as zero. */
.app{max-width:560px;margin:0 auto;min-height:100dvh;display:flex;flex-direction:column}
.screen{flex:1;padding:calc(10px + env(safe-area-inset-top,0px)) 16px calc(var(--tab-h) + 12px + env(safe-area-inset-bottom,0px) + 24px);display:none}
.screen.on{display:block}
.screen.on.rise{animation:rise .22s cubic-bezier(.32,.72,.35,1)}
@keyframes rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* The inbox opens with its filters — an iOS segmented control stuck to the
   top. Once the list scrolls under it, it turns to glass. */
.filters{position:sticky;top:0;z-index:20;margin:calc(-10px - env(safe-area-inset-top,0px)) -16px 12px;
  padding:calc(8px + env(safe-area-inset-top,0px)) 16px 8px;transition:background .18s,box-shadow .18s}
.app.scrolled .filters{background:var(--glass);backdrop-filter:blur(24px) saturate(1.4);-webkit-backdrop-filter:blur(24px) saturate(1.4);
  box-shadow:0 1px 0 var(--hair)}
/* the ring's gap reads the bar behind it once the bar is glass */
.app.scrolled .filters .avatar.live{box-shadow:0 0 0 2px transparent,0 0 0 4.5px var(--green)}
.app.scrolled .filters .avatar.off{box-shadow:0 0 0 2px transparent,0 0 0 4.5px var(--red)}
/* The inbox cuts share the chip class the tests know; inside the control
   they are segments and nothing of the chip may leak through. */
.seg .fchip{display:inline-flex;justify-content:center;align-items:center;gap:3px;flex:1;min-height:32px;border-radius:7px;
  background:transparent;color:var(--ink);padding:0 4px;font-size:13px;font-weight:500;white-space:nowrap;box-shadow:none}
.seg .fchip.on{background:var(--seg-on);color:var(--ink);font-weight:600;box-shadow:var(--seg-shadow)}
/* The count is a quiet number beside its word — Apple never badges a
   segment; the red oval belongs to the tab bar alone. */
.seg .fchip b{font-weight:400;color:var(--muted);margin:0;font-variant-numeric:tabular-nums}
.seg .fchip.on b{color:var(--ink);font-weight:500}
/* The bar over the cuts: his picture and the search field. */
.sbar{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.avatar.me-av{width:40px;height:40px;font-size:17px;font-weight:600;overflow:hidden;padding:0;cursor:pointer;flex:none}
.avatar.me-av.big{width:48px;height:48px;font-size:20px}
.avatar img{width:100%;height:100%;object-fit:cover;border-radius:50%;display:block}
.search{flex:1;min-width:0;display:flex;align-items:center;gap:6px;background:var(--fill);border-radius:10px;min-height:36px;padding:0 10px;color:var(--muted)}
.search .s-ic svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round}
/* 17px: iPhone Safari zooms into any smaller field */
.search input{flex:1;min-width:0;background:transparent;border:0;outline:none;font-size:17px;color:var(--ink);min-height:36px;padding:0;font-family:inherit;-webkit-appearance:none;appearance:none}
.search input::placeholder{color:var(--faint)}
.search input::-webkit-search-cancel-button,.search input::-webkit-search-decoration{display:none;-webkit-appearance:none}
.search .s-x{width:26px;height:26px;border-radius:50%;background:var(--fill2);color:var(--muted);display:none;place-items:center;flex:none}
.search .s-x svg{width:12px;height:12px}
.search.has .s-x{display:grid}
.arch-row{display:flex;justify-content:center;padding:4px 0 8px}
.arch-link{border-radius:999px;padding:0 16px;min-height:36px;background:var(--fill);color:var(--accent);font-size:15px;font-weight:600}
.arch-link.on{background:var(--accent);color:var(--on-accent)}
/* Offline: the gate that withholds work says so, with the way back. */
.offline{display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--amber-soft);color:var(--amber-ink);
  border-radius:12px;padding:8px 8px 8px 14px;margin:0 0 12px;font-size:15px;font-weight:600}
.offline button{background:var(--accent);color:var(--on-accent);border-radius:999px;padding:0 14px;min-height:34px;font-weight:600;font-size:15px;flex:none}

/* groups — the inset grouped list of iOS: one surface, hairlines inside */
.card{background:var(--card);border-radius:var(--r);padding:16px;margin-bottom:16px}
h2{font-size:13px;font-weight:600;margin:0 0 10px;color:var(--muted)}
.hint{font-size:13px;color:var(--muted);line-height:1.5}

/* inbox filters: one scrollable row of capsules, the active one tinted */
.fchips{display:flex;gap:8px;overflow-x:auto;padding:2px 0 12px;margin:0}
.fchip{flex:none;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;border-radius:999px;padding:0 14px;min-height:34px;
  font-size:15px;font-weight:500;background:var(--fill);color:var(--ink);transition:background .15s,color .15s}
.fchip b{font-weight:600;font-variant-numeric:tabular-nums}
.fchip.on{background:var(--accent);color:var(--on-accent)}
.fchips.inline{padding:0 0 12px;margin:0}
/* The period belongs beside the word it qualifies, not on a line of its own. */
.card-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}
.card-head h2{margin:0;flex:none}
.card-head .fchips.inline{padding:0;margin:0;flex:1;justify-content:flex-end}
.card-head .fchip{min-height:28px;padding:0 11px;font-size:13px}

/* chat list: one card per conversation, air between them (owner's call:
   «مفصلة»), the case disc as the one signature */
.chat-list{display:flex;flex-direction:column;gap:10px;margin-bottom:12px}
.chat-list .card{margin:0}
.chat-wrap{position:relative;overflow:hidden;border-radius:var(--r)}
.chat-list > .chat-row{border-radius:var(--r)}
/* The panels a swipe reveals under the row: archive behind the row's start
   (a drag to the left), the call behind its end (a drag to the right). */
.chat-under{position:absolute;inset:0;display:flex;align-items:center;gap:8px;padding:0 20px;
  color:#fff;font-size:13px;font-weight:600;opacity:0;transition:opacity .12s}
.chat-under.arch{justify-content:flex-start;background:var(--tone-arch)}
.chat-under.call{justify-content:flex-end;background:var(--green)}
.chat-wrap.swipe-on.dir-l .chat-under.arch,.chat-wrap.swipe-on.dir-r .chat-under.call{opacity:1}
.chat-under svg{width:22px;height:22px;stroke:currentColor;fill:none}
.chat-row.swiping{transition:none}
.chat-row{position:relative;touch-action:pan-y;display:flex;gap:12px;align-items:center;padding:12px 16px;min-height:44px;cursor:pointer;
  background:var(--card);transition:background .15s;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
/* today's appointment on the row, red once its time has passed */
.ap-chip{font-size:12px;font-weight:600;color:var(--accent-ink);background:var(--accent-soft);border-radius:999px;padding:3px 9px;white-space:nowrap;font-variant-numeric:tabular-nums}
.ap-chip.late{color:var(--red);background:var(--red-soft)}
.chat-row:active{background:var(--card2)}
.avatar{width:44px;height:44px;border-radius:50%;flex:none;display:grid;place-items:center;font-weight:600;font-size:17px;
  background:var(--tone-new);color:#fff;position:relative}
.avatar.word{font-size:12px;font-weight:700}
/* The technician: his picture or his name, and a ring that says whether
   jobs reach him — green on, red off. A shadow, not a child: the circle
   clips its children for the picture. */
.avatar.big{width:48px;height:48px;font-size:20px;font-weight:600}
.avatar.live{box-shadow:0 0 0 2px var(--bg),0 0 0 4.5px var(--green)}
.avatar.off{box-shadow:0 0 0 2px var(--bg),0 0 0 4.5px var(--red)}
.card .avatar.live{box-shadow:0 0 0 2px var(--card),0 0 0 4.5px var(--green)}
.card .avatar.off{box-shadow:0 0 0 2px var(--card),0 0 0 4.5px var(--red)}
.avatar .nm-s{font-size:11px;font-weight:700;letter-spacing:-.2px;line-height:1}
.avatar.big .nm-s{font-size:13px}
.card.profile{padding:12px 16px}
.avatar.arch{background:var(--tone-arch)}
.avatar.late{background:var(--tone-late)}
.avatar.warr{background:var(--tone-warr)}
.avatar.shop{background:var(--tone-shop)}
.avatar.back{background:var(--tone-back)}
/* The owner is on this customer: the technician must not walk past it. */
.avatar.word.esc{background:var(--tone-late);animation:escpulse 1.5s ease-in-out infinite}
@keyframes escpulse{0%,100%{box-shadow:0 0 0 0 var(--red-halo)}55%{box-shadow:0 0 0 9px transparent}}
.chat-mid{flex:1;min-width:0}
/* name line: the name, then today's appointment or the wait at its end */
.chat-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.chat-name{flex:1;min-width:0;font-weight:600;font-size:17px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chat-dev{margin-top:1px;font-size:15px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chat-dev .dev{display:inline;max-width:100%;font-size:15px;color:var(--muted);font-weight:400;background:none;padding:0}
/* message line: the last line, the clock at its end on every row */
.chat-last{display:flex;align-items:baseline;justify-content:space-between;gap:8px;font-size:15px;color:var(--muted);margin-top:1px}
.chat-last .txt{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chat-time{flex:none;font-size:13px;color:var(--muted);font-variant-numeric:tabular-nums}
/* the unread count on the disc's corner, ringed so it reads on any disc colour */
.av-wrap{position:relative;flex:none}
.badge{position:absolute;top:-5px;inset-inline-start:-7px;min-width:20px;height:20px;border-radius:10px;background:var(--accent);color:var(--on-accent);font-size:12px;font-weight:600;
  display:grid;place-items:center;padding:0 6px;font-variant-numeric:tabular-nums;box-shadow:0 0 0 2px var(--card)}
.cap-card .empty{color:var(--amber-ink)}
.wait-tag{font-size:12px;font-weight:600;color:var(--amber-ink);background:var(--amber-soft);border-radius:999px;padding:3px 9px;white-space:nowrap}
.chat-side .amt{font-weight:600;color:var(--ok);font-size:15px;font-variant-numeric:tabular-nums}
.chat-side .amt.zero{color:var(--faint);font-weight:400}
.shop-tag{color:var(--shop-tag);font-weight:600}
.chip-call{display:inline-block;font-size:12px;font-weight:600;padding:1px 8px;border-radius:999px;background:var(--accent);color:var(--on-accent);margin-inline-end:6px;vertical-align:middle}
.chip-tech{display:inline-block;font-size:12px;font-weight:600;padding:1px 8px;border-radius:999px;background:var(--fill);color:var(--muted);margin-inline-end:6px;vertical-align:middle}
/* The customer's number, under his name in the inbox and in the thread, and
   on its own line on an unclaimed card for the owner's board. Who receives the
   number at all is the server's decision (ADR-004 and the owner's scrub
   switch); this only shows what was sent. */
.cph{font-variant-numeric:tabular-nums;letter-spacing:.2px;color:var(--muted);background:var(--fill);border-radius:6px;padding:1px 6px;margin-inline-end:6px;font-size:12px;white-space:nowrap}
.th-meta .cph{background:transparent;padding:0;margin-inline-end:5px}

/* thread */
.thread{position:fixed;inset:0;background:var(--card);z-index:50;display:none;flex-direction:column;max-width:560px;margin:0 auto}
.thread.on{display:flex;animation:slidein .26s cubic-bezier(.32,.72,.35,1)}
@keyframes slidein{from{transform:translateX(-28px);opacity:.4}to{transform:none;opacity:1}}
.th-top{display:flex;align-items:center;gap:8px;padding:calc(6px + env(safe-area-inset-top,0px)) 8px 6px 12px;min-height:calc(var(--nav-h) + 8px);
  background:var(--glass);backdrop-filter:blur(24px) saturate(1.4);-webkit-backdrop-filter:blur(24px) saturate(1.4);border-bottom:1px solid var(--hair)}
.th-back{width:44px;height:44px;display:grid;place-items:center;border-radius:50%;color:var(--accent);flex:none}
.th-back svg{width:26px;height:26px}
.th-back:active{opacity:.5}
/* The name is a button: the customer's card is one tap away. */
.th-info{flex:1;min-width:0;display:flex;align-items:center;gap:10px;text-align:start;padding:2px 4px 2px 0;border-radius:12px;color:inherit}
.th-info:active{opacity:.55}
.th-text{flex:1;min-width:0}
/* The job's state under the name: only when there is something to say. */
.th-state{display:flex;gap:6px;padding:6px 16px 8px;overflow-x:auto;scrollbar-width:none;background:var(--card);border-bottom:1px solid var(--hair)}
.th-state::-webkit-scrollbar{display:none}
.st-chip{flex:none;font-size:12px;font-weight:600;border-radius:999px;padding:3px 9px;white-space:nowrap;background:var(--fill);color:var(--muted);font-variant-numeric:tabular-nums}
.st-chip.acc{background:var(--accent-soft);color:var(--accent-ink)}
.st-chip.warn{background:var(--amber-soft);color:var(--amber-ink)}
.st-chip.bad{background:var(--red-soft);color:var(--red)}
.st-chip.shop{color:var(--shop-tag)}
.th-name{font-weight:600;font-size:17px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.th-meta{font-size:12px;color:var(--muted);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.th-top .avatar{width:36px;height:36px;font-size:11px}
/* A filled disc so the call reads as a button, not a decoration. */
.th-call{width:36px;height:36px;flex:none;display:grid;place-items:center;border-radius:50%;
  background:var(--accent-soft);color:var(--accent);transition:transform .12s}
.th-call svg{width:18px;height:18px}
.th-call:active{transform:scale(.92)}
.th-msgs{flex:1;touch-action:pan-y;overflow-y:auto;overflow-x:hidden;padding:12px 16px 10px;display:flex;flex-direction:column;gap:0}
.thread.loading .th-msgs::after{content:"جاري تحميل المحادثة...";display:block;text-align:center;font-size:13px;color:var(--muted);padding:12px}
/* Bubble geometry: consecutive bubbles from one side are one run — the first
   wears the tail, the rest sit 2px under it, a new run opens with 8px */
.bub{position:relative;touch-action:pan-y;overflow-wrap:anywhere;max-width:78%;min-width:72px;border-radius:18px;padding:8px 12px 9px;font-size:17px;line-height:1.35;margin:8px 0 0;border:0}
.bub.cont{margin-top:2px}
.bub.has-media.cont{margin-top:6px}
.bub.cust{align-self:flex-start;background:var(--bub-in);color:var(--bub-in-ink)}
.bub.me{align-self:flex-end;background:var(--bub-out);color:var(--bub-out-ink)}
.bub.cust:not(.cont),.bub.peer:not(.cont){border-end-start-radius:4px}
.bub.me:not(.cont),.bub.bot:not(.cont){border-end-end-radius:4px}
/* the tail is a real wedge, masked out of the bubble's own colour */
.bub::after{content:"";position:absolute;bottom:0;width:10px;height:14px;pointer-events:none;
  --tail:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 14'%3E%3Cpath d='M0 0L0 14L10 14Q2 11 0 0Z' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask:var(--tail) no-repeat 0 0/100% 100%;mask:var(--tail) no-repeat 0 0/100% 100%}
.bub.cust::after{inset-inline-start:-9px;background:var(--bub-in)}
.bub.peer::after{inset-inline-start:-9px;background:var(--bub-peer)}
.bub.me::after{inset-inline-end:-9px;transform:scaleX(-1);background:var(--bub-out-tail)}
.bub.bot::after{inset-inline-end:-9px;transform:scaleX(-1);background:var(--card2)}
.bub.cont::after,.bub.div::after{display:none}
/* a browser without masking would draw the tail as a bare rectangle */
@supports not ((-webkit-mask-image:none) or (mask-image:none)){.bub::after{display:none}}
/* the time and the ticks ride the end of the last line, and take a line of
   their own only when that line has no room for them */
.bub .t{float:inline-end;margin-inline-start:9px;margin-block-start:4px;position:relative;top:3px;
  font-size:11px;line-height:1;white-space:nowrap;color:var(--bub-in-meta);font-variant-numeric:tabular-nums}
/* over a picture the clock is an overlay, not part of any line */
.bub.has-media .t{float:none;position:absolute;inset-block-end:6px;inset-inline-end:11px;margin:0;top:auto}
.bub.me .t{color:var(--bub-out-meta)}
.mspace{display:inline-block;width:44px;height:1px}
.bub:not(.has-media) .mspace{display:none}
.bub.me .mspace{width:68px}
.bub.bot .mspace{width:46px}
.bub.has-orig{padding-bottom:22px}
/* The quoted line: a bar down its leading edge, the author over the words. */
.bub .q{display:block;border-inline-start:3px solid var(--accent);border-radius:8px;background:var(--quote-bg);
  padding:6px 9px;margin:0 0 6px;font-size:14px;line-height:1.35;overflow:hidden}
.bub .q b{display:block;font-size:12px;font-weight:600;color:var(--accent-ink);margin-bottom:1px}
.bub .q span{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;color:var(--quote-ink)}
.bub.me .q{border-inline-start-color:var(--quote-me-line);background:var(--quote-me-bg)}
.bub.me .q b{color:var(--quote-me-line)}
.bub.me .q span{color:var(--bub-out-ink);opacity:.9}
/* Dragged toward the reply; it springs back the moment the finger leaves. */
.bub.rswipe{transition:none;will-change:transform;-webkit-user-select:none;user-select:none}
/* Until it is playing the frame is the round button's; the finger that lands
   anywhere else on it is answering the line, not driving the player. */
.bub .ph.vid:not(.on) video{pointer-events:none}
.bub.rgo{box-shadow:0 0 0 2px var(--accent-glow-wide)}
/* The bar over the composer: what this message is answering. */
.rbar{flex-basis:100%;min-width:0;order:-1;display:flex;align-items:center;gap:8px;padding:0 0 4px}
.rbar .q{flex:1;min-width:0;border-inline-start:3px solid var(--accent);border-radius:8px;background:var(--fill);
  padding:6px 9px;font-size:14px;line-height:1.35}
.rbar .q b{display:block;font-size:12px;font-weight:600;color:var(--accent-ink)}
.rbar .q span{display:block;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rbar .rx{flex:none;width:32px;height:32px;border-radius:50%;background:transparent;border:0;color:var(--muted);
  display:grid;place-items:center;cursor:pointer}
.rbar .rx svg{width:18px;height:18px}
.chk{display:flex;align-items:center;gap:10px;font-size:17px}.chk input{width:22px;height:22px;accent-color:var(--accent)}
.tpick{display:flex;gap:8px}.tpick select{flex:1;min-width:0}
.bub a{color:var(--link-in);text-decoration:underline;word-break:break-all;font-weight:600}.bub.me a{color:var(--link-out)}
.bub a.tel{unicode-bidi:isolate;font-weight:600;white-space:nowrap}
.bub .orig{font-size:13px;opacity:.7;margin-top:4px;padding-top:4px;border-top:1px dashed var(--orig-line)}
.bub.short{text-align:center}
/* A one-word bubble still has to hold its clock; the ticks make mine wider. */
.bub.me,.bub.bot{min-width:92px}
.bub.div{min-width:0;align-self:center;max-width:92%;background:var(--bub-div);color:var(--muted);font-size:12px;font-weight:600;border:0;padding:4px 12px;border-radius:999px;text-align:center;margin:16px auto 4px}
/* The unread line runs the width of the thread: he sees at a glance where he
   stopped reading. */
.bub.div.unread{align-self:stretch;max-width:none;border-radius:8px;background:var(--accent-soft);color:var(--accent-ink);margin:14px 0 6px}
.bub.peer{align-self:flex-start;background:var(--bub-peer);color:var(--bub-peer-ink);border:1px solid var(--bub-peer-line)}
.bub.peer .who{font-size:12px;font-weight:600;color:var(--accent-ink);margin-bottom:2px}
.bub .t .tick{display:inline-block;vertical-align:-3px;margin-inline-start:6px}
.bub .t .tick svg{width:15px;height:13px;stroke:var(--tick)}
.bub .t .tick.read svg{stroke:var(--tick-read)}
.bub .t .tick.fail svg{stroke:var(--tick-fail)}
.bub.bot{align-self:flex-end;background:var(--card2);color:var(--muted);font-size:15px;border:1px dashed var(--hair)}
.bub.bot .t{color:var(--faint)}
.bub a.file{display:inline-block;padding:6px 12px;border-radius:999px;background:var(--file-chip);color:inherit;text-decoration:none;font-size:15px}
.bub.me a.file{background:var(--file-chip-me)}
.gone{font-size:13px;color:var(--faint)}
.bub.me .gone{color:var(--bub-out-meta)}
.fail-note{clear:both;font-size:13px;line-height:1.4;color:var(--tick-fail);margin-top:6px;font-weight:500}
/* action capsules over the composer: tinted labels on a fill, the primary one solid */
/* Two he taps every day and «المزيد»: the primary fills what is left. */
.th-actions{display:flex;gap:8px;padding:8px 16px;border:0}
.act-btn{flex:none;display:inline-flex;align-items:center;justify-content:center;gap:5px;border-radius:999px;padding:0 16px;font-size:15px;font-weight:600;min-height:40px;border:0;
  background:var(--fill);color:var(--accent);white-space:nowrap}
.act-btn:active{opacity:.6}
.act-btn.primary{flex:1;background:var(--accent);color:var(--on-accent)}
.act-btn.more svg{width:20px;height:20px;fill:currentColor}
.act-btn.danger{color:var(--red)}
.arm{background:var(--red)!important;color:var(--on-red)!important}
.win-note{margin:0 16px 8px;background:var(--amber-soft);color:var(--ink);border-radius:12px;padding:10px 12px;font-size:15px;line-height:1.4}
.arch-note{margin:0 16px calc(env(safe-area-inset-bottom,0px) + 16px);background:var(--card2);border-radius:12px;padding:14px;
  text-align:center;font-size:15px;font-weight:600;color:var(--muted)}
.arch-note span{font-weight:400;font-size:13px;color:var(--faint)}
.call-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 16px calc(env(safe-area-inset-bottom,0px) + 16px);background:var(--card2);border-radius:12px;padding:12px 14px;font-size:15px;line-height:1.5}
.call-bar b{font-size:17px}
.call-btn{background:var(--accent);color:var(--on-accent);border-radius:999px;padding:0 18px;font-weight:600;text-decoration:none;flex:none;min-height:44px;display:inline-flex;align-items:center}

/* the composer: a hairline field holding the text box, the paperclip and the
   camera, with the round accent button — mic while empty, send once there is
   text — outside it. Glass under it, like every bar over the messages. */
.composer{position:relative;display:flex;flex-wrap:wrap;align-items:flex-end;gap:8px;padding:8px 12px calc(env(safe-area-inset-bottom,0px) + 8px);border:0;
  background:var(--glass);backdrop-filter:blur(24px) saturate(1.4);-webkit-backdrop-filter:blur(24px) saturate(1.4);border-top:1px solid var(--hair);
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.cpill{flex:1;min-width:0;display:flex;align-items:flex-end;gap:1px;background:var(--card);border:1px solid var(--hair);border-radius:22px;
  padding:2px 4px;transition:border-color .15s}
.cpill:focus-within{border-color:var(--accent)}
.composer textarea{flex:1;min-width:0;background:transparent;border:0;border-radius:0;padding:8px 10px;color:var(--ink);outline:none;
  min-height:38px;max-height:118px;font-size:17px;font-family:inherit;line-height:1.35;resize:none;overflow-y:auto;-webkit-user-select:text;user-select:text}
.composer textarea::placeholder{color:var(--faint)}
.cpill .att,.cpill .cam{width:36px;height:36px;margin-bottom:1px;border-radius:50%;background:transparent;display:grid;place-items:center;flex:none;transition:transform .12s}
.cpill .att svg,.cpill .cam svg{width:22px;height:22px;stroke:var(--muted);fill:none}
.cpill .att:active,.cpill .cam:active{transform:scale(.9)}
/* Held down, the camera is recording, not shooting. */
.cpill .cam.held{color:var(--red);transform:scale(1.12)}
.composer.recing .att{visibility:hidden;pointer-events:none}
.send{width:44px;height:44px;border-radius:50%;background:var(--accent);display:grid;place-items:center;flex:none;transition:transform .12s}
.send svg{width:20px;height:20px;stroke:var(--on-accent)}
.send:active{transform:scale(.94)}
/* No callout, no selection, no drag: iOS turns a long press into its own
   menu unless the button AND its parent opt out. */
#mainBtn{touch-action:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;will-change:transform;transition:transform .08s}
#mainBtn.press{transform:scale(.94)}
/* the glyph inside the button is never the touch target: the timer repaint
   would detach the node the touch was bound to */
#mainBtn svg,.cpill .cam svg,.cpill .att svg{pointer-events:none}
.composer.recing .cpill{border-color:var(--red)}
.composer textarea.recing{color:var(--red);-webkit-user-select:none;user-select:none;pointer-events:none}
.composer textarea.recing::placeholder{color:var(--red);opacity:.9;animation:recblink 1.2s infinite}
@keyframes recblink{0%,100%{opacity:.9}50%{opacity:.45}}
/* the hold: the mic follows the finger toward the X, the hint fades as it
   goes, the lock pill rises to meet it. */
.rec-lock{position:absolute;inset-inline-end:14px;bottom:calc(100% + 6px);display:flex;flex-direction:column;align-items:center;gap:2px;padding:8px 10px;border-radius:999px;background:var(--card);box-shadow:var(--shadow-lg);font-size:11px;color:var(--muted);transition:transform .1s;animation:lockbob 1.1s ease-in-out infinite;pointer-events:none;z-index:5}
.rec-lock svg{width:18px;height:18px;stroke:var(--accent-ink)}
.rec-lock.on{background:var(--accent);color:var(--on-accent);animation:none}
.rec-lock.on svg{stroke:var(--on-accent)}
.rec-lock.hidden{display:none}
@keyframes lockbob{0%,100%{translate:0 0}50%{translate:0 -4px}}
.cpill .cancel{background:var(--red)}
.cpill .cancel svg{stroke:var(--on-red)}
.composer textarea:disabled{opacity:.9}
.composer .send.rec{background:var(--red);animation:recpulse 1.2s infinite}
@keyframes recpulse{0%,100%{box-shadow:0 0 0 0 var(--red-halo)}50%{box-shadow:0 0 0 10px transparent}}
/* the recording row takes the text box's place inside the field */
.cpill.recing textarea{display:none}
#recRow{flex:1;min-width:0;min-height:38px;display:flex;align-items:center;gap:10px;padding:0 12px;font-variant-numeric:tabular-nums}
.rec-dot{width:9px;height:9px;border-radius:50%;background:var(--red);flex:none;animation:recblink 1.2s infinite}
#recRow.opening .rec-dot{background:var(--muted);animation:none}
.rec-time{font-size:15px;font-weight:600;color:var(--red);flex:none;direction:ltr}
#recRow.opening .rec-time{color:var(--muted);font-weight:500;font-size:14px}
#recHint{flex:1;min-width:0;display:flex;align-items:center;justify-content:center;gap:4px;font-size:13px;color:var(--muted);white-space:nowrap;overflow:hidden;transition:opacity .05s}
#recHint svg{width:15px;height:15px;flex:none;stroke:var(--muted);animation:hintnudge 1s ease-in-out infinite}
@keyframes hintnudge{0%,100%{translate:0 0}50%{translate:4px 0}}
@media (max-width:360px){#recHint span{display:none}}

/* media bubble: the picture fills the bubble edge to edge, the time rides its
   bottom corner on a soft scrim, a caption sits under it in the same bubble */
.bub.has-media{padding:3px}
.bub.md-img:has(.ph),.bub.md-vid:has(.ph){padding:0;max-width:72%}
.bub.md-file,.bub.has-media:not(:has(.ph)):not(:has(.vn)){padding:8px 12px}
.bub .ph{display:block;position:relative;border-radius:inherit;overflow:hidden;width:100%;max-height:340px;
  background:var(--media-ph);box-shadow:0 0 0 1px var(--hair)}
.bub img,.bub video{display:block;width:100%;height:100%;max-width:100%;object-fit:cover;border-radius:inherit;background:transparent;
  opacity:0;transition:opacity .2s}
.bub .ph.ready img,.bub .ph.ready video{opacity:1}
/* The picture sets the bubble's width, so a caption wraps inside the frame and
   never stretches the bubble past it. */
.bub.md-img,.bub.md-vid{width:min(268px,72vw)}
.bub .ph:not(.ready){background:linear-gradient(100deg,var(--media-ph) 30%,var(--card2) 50%,var(--media-ph) 70%);
  background-size:220% 100%;animation:phwait 1.1s linear infinite}
@keyframes phwait{from{background-position:180% 0}to{background-position:-40% 0}}
.bub .ph:not(.ready) .vplay{display:none}
/* It did not arrive. An empty frame says nothing; this says what happened
   and takes the tap that asks for it again. */
.ph-fail{display:none}
.bub .ph.failed{background:var(--media-ph);animation:none}
.bub .ph.failed img,.bub .ph.failed video,.bub .ph.failed .vplay{display:none}
.bub .ph.failed .ph-fail{display:flex;align-items:center;justify-content:center;text-align:center;
  position:absolute;inset:0;padding:10px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer}
.bub.has-cap .ph{border-end-start-radius:4px;border-end-end-radius:4px}
.bub .cap{padding:6px 10px 18px;font-size:17px;line-height:1.35}
.bub.md-img:has(.ph) .t,.bub.md-vid:has(.ph) .t{inset-block-end:7px;inset-inline-end:8px;color:var(--media-ink);background:var(--media-scrim);border-radius:999px;padding:2px 8px;
  backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.bub.md-img:has(.ph) .t .tick svg,.bub.md-vid:has(.ph) .t .tick svg{stroke:var(--media-ink)}
.bub.has-cap.md-img .t,.bub.has-cap.md-vid .t{background:none;padding:0;backdrop-filter:none;-webkit-backdrop-filter:none;
  inset-block-end:6px;inset-inline-end:11px;color:var(--bub-in-meta)}
.bub.me.has-cap .t{color:var(--bub-out-meta)}
.bub .vplay{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:54px;height:54px;border-radius:50%;
  background:var(--media-scrim-strong);display:grid;place-items:center;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.bub .vplay svg{width:26px;height:26px;color:var(--media-ink);margin-inline-start:3px}
.bub .ph.on .vplay{display:none}
.bub .ph.on video{max-height:none;object-fit:contain}
/* an upload still in flight: the picture is already there, dimmed, spinning */
.bub .up{display:none;position:absolute;top:50%;left:50%;width:30px;height:30px;margin:-15px 0 0 -15px;border-radius:50%;
  border:2.5px solid var(--spin-track);border-top-color:var(--spin-head);animation:vspin .8s linear infinite}
.bub.pending .up{display:block}
.bub.pending img,.bub.pending video{opacity:.55}
@keyframes vspin{to{transform:rotate(360deg)}}

/* voice note — one 44px row (avatar, play button, waveform) with a single
   small line under the wave carrying the length, the speed pill and the
   unplayed dot */
.bub.md-aud{padding:6px 8px 6px;max-width:88%}
.vn{display:flex;flex-direction:column;gap:1px;min-width:min(272px,68vw)}
.vn-row{display:flex;align-items:center;gap:10px;min-height:42px}
/* The sender's face sits on the bubble's outer edge and the play button faces
   it across the wave: incoming reads avatar-left, play-right; mine, mirrored. */
.vn-av{order:3}.vn-play{order:1}.vn-mid{order:2}
.bub.me .vn-av{order:1}.bub.me .vn-play{order:3}
.vn audio{display:none}
.vn-av{position:relative;width:44px;height:44px;flex:none;border-radius:50%;display:grid;place-items:center;font-size:16px;font-weight:600;
  color:#fff;background:var(--vn-av)}
.bub.me .vn-av{background:var(--vn-av-me)}
/* The mic says whether the note has been heard: grey until it is, then blue. */
.vn-mic{position:absolute;bottom:-1px;inset-inline-end:-1px;width:16px;height:16px;padding:2.5px;border-radius:50%;
  color:var(--vn-bars);background:var(--vn-mic-bg);box-shadow:var(--vn-mic-shadow);transition:color .15s}
.vn.heard .vn-mic{color:var(--vn-played)}
.bub.me .vn-mic{color:var(--vn-bars-me)}
.bub.me .vn.heard .vn-mic{color:var(--vn-played-me)}
.vn-play{width:30px;height:30px;flex:none;display:grid;place-items:center;border-radius:50%;color:var(--vn-play);transition:transform .12s}
.bub.me .vn-play{color:var(--vn-play-me)}
.vn-play:active{transform:scale(.92)}
.vn-play svg{width:22px;height:22px}
.vn-play .ic-pause,.vn.playing .vn-play .ic-play{display:none}
.vn.playing .vn-play .ic-pause{display:block}
.vn-mid{flex:1;min-width:0;display:flex;align-items:center}
.vn-wave{position:relative;flex:1;min-width:0;height:26px;display:flex;align-items:center;touch-action:none;cursor:pointer}
/* Playback runs away from the play button: right to left on an incoming note,
   left to right on the technician's own, whose row is mirrored. */
.bub.me .vn-wave{direction:ltr}
.vn-bars{display:flex;align-items:center;justify-content:space-between;width:100%;height:100%}
.vn-bars i{width:2px;flex:none;border-radius:2px;background:var(--vn-bars);transition:background .1s}
.vn-bars i.on{background:var(--vn-played)}
.bub.me .vn-bars i{background:var(--vn-bars-me)}
.bub.me .vn-bars i.on{background:var(--vn-played-me)}
.bub.cust .vn-bars,.bub.peer .vn-bars{color:var(--vn-bars)}
.bub.bot .vn-bars{color:var(--muted)}
.bub.me .vn-bars{color:var(--vn-bars-me)}
.vn-knob{position:absolute;top:50%;width:11px;height:11px;margin-top:-5.5px;margin-inline-start:-5.5px;border-radius:50%;
  background:var(--vn-knob);box-shadow:var(--vn-knob-shadow);pointer-events:none}
.bub.me .vn-knob{background:var(--vn-knob-me)}
.vn-foot{display:flex;align-items:center;height:14px;font-size:11px;color:var(--vn-foot);font-variant-numeric:tabular-nums;
  padding-inline-start:54px}
.bub.me .vn-foot{color:var(--vn-foot-me)}
.vn-t{flex:none}
/* the pill holds its room from the first paint, so the line never shifts */
.vn-rate{display:none;width:44px;height:44px;flex:none;place-items:center;border-radius:50%;order:3;
  font-size:13px;font-weight:700;background:var(--vn-rate);color:var(--vn-rate-ink);font-variant-numeric:tabular-nums}
.vn.started .vn-rate{display:grid}
.vn.started .vn-av{display:none}
.bub.me .vn-rate{order:1;background:var(--vn-rate-me);color:var(--vn-rate-ink-me)}
.vn.loading .vn-play{opacity:.55}
.vn.loading .vn-play svg{animation:vnspin 1s linear infinite}
@keyframes vnspin{to{transform:rotate(360deg)}}

/* broadcast cards: one group per job — a header row, label/value rows the way
   iOS lays out details, and the one prominent button */
.job-card{background:var(--card);border-radius:var(--r);padding:0 16px 16px;margin-bottom:16px;border:0}
.job-head{display:flex;align-items:center;gap:10px;margin:0 -16px;padding:13px 16px;border-bottom:1px solid var(--hair)}
.job-id{font-weight:600;color:var(--ink);font-size:17px}
.job-age{margin-inline-start:auto;font-size:13px;color:var(--amber-ink);font-weight:600;background:var(--amber-soft);border-radius:999px;padding:3px 10px}
.job-line{font-size:17px;color:var(--muted);margin:0 -16px;padding:11px 16px;display:flex;gap:12px;align-items:center;justify-content:space-between;border-bottom:1px solid var(--hair)}
.job-line b{color:var(--ink);font-weight:400;text-align:end}
.claim{width:100%;margin-top:14px;background:var(--accent);color:var(--on-accent);border-radius:12px;padding:0 16px;font-size:17px;font-weight:600;min-height:50px;transition:transform .12s,opacity .12s}
.claim:active{transform:scale(.98);opacity:.9}

/* appointments */
.ap-row{display:flex;gap:12px;align-items:center;padding:12px 0;min-height:44px;cursor:pointer}
.ap-row + .ap-row{border-top:1px solid var(--hair)}
.ap-time{font-weight:600;color:var(--accent-ink);font-size:17px;min-width:82px;font-variant-numeric:tabular-nums}
.ap-mid{flex:1;min-width:0}
.ap-name{font-weight:400;font-size:17px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ap-meta{font-size:13px;color:var(--muted);margin-top:2px}
.ap-late{color:var(--red);font-size:12px;font-weight:600;background:var(--red-soft);border-radius:999px;padding:3px 9px;white-space:nowrap}

/* me / stats */
.stat-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.stat{background:var(--card2);border-radius:12px;padding:14px;border:0}
.stat .n{font-size:28px;font-weight:700;margin-top:2px;font-variant-numeric:tabular-nums;letter-spacing:-.3px;line-height:1.2}
.stat .l{font-size:13px;color:var(--muted)}
.stat.money .n{color:var(--ok)}
/* appearance picker: the iOS segmented control */
.seg{display:flex;gap:2px;background:var(--fill);border-radius:9px;padding:2px}
.seg-b{flex:1;min-height:32px;border-radius:7px;padding:0 6px;font-size:13px;font-weight:500;color:var(--ink);transition:background .15s}
.seg-b.on{background:var(--seg-on);box-shadow:var(--seg-shadow);font-weight:600}
/* the iOS switch: 51 by 31, green when on */
.sw{width:51px;height:31px;border-radius:16px;background:var(--sw-off);position:relative;transition:background .25s;flex:none;border:0}
.sw::after{content:"";position:absolute;top:2px;inset-inline-start:2px;width:27px;height:27px;border-radius:50%;background:var(--sw-knob);
  box-shadow:var(--sw-knob-shadow);transition:inset-inline-start .25s cubic-bezier(.32,.72,.35,1)}
.sw.on{background:var(--green)}
.sw.on::after{inset-inline-start:22px}
/* What the notification switch actually sends, one line each. */
.pref-row{display:flex;align-items:center;gap:12px;margin-top:12px;padding-top:12px;border-top:1px solid var(--hair);min-height:44px;cursor:pointer}
.pref-row.first{margin-top:0;padding-top:0;border-top:0}
.pref-txt{flex:1;min-width:0;font-size:17px;font-weight:400;color:var(--ink)}
.pref-txt span{display:block;font-weight:400;font-size:13px;color:var(--muted);margin-top:2px}
/* The app updates itself; the number is a quiet line that still forces one. */
.ver{text-align:center;font-size:12px;color:var(--faint);padding:8px 0 16px;cursor:pointer}
.ghost{border:0;border-radius:12px;padding:0 14px;font-size:17px;color:var(--accent);width:100%;text-align:center;margin-top:8px;min-height:44px;background:var(--card2)}
.ghost:active{background:var(--fill2)}
.empty{display:flex;flex-direction:column;align-items:center;gap:12px;color:var(--muted);font-size:15px;padding:40px 0;text-align:center;line-height:1.5}
.empty svg{width:40px;height:40px;stroke-width:1.3;color:var(--empty-ic)}

/* the owner watching the whole team from the technician app */
.team-list{margin-top:14px}
.team-row{display:flex;align-items:center;gap:10px;padding:12px 0;min-height:44px}
.team-row + .team-row{border-top:1px solid var(--hair)}
.tm-mid{flex:1;min-width:0}
.tm-name{display:flex;align-items:center;gap:8px;font-weight:600;font-size:17px}
.tm-dot{width:9px;height:9px;border-radius:50%;background:var(--faint);flex:none}
.tm-dot.on{background:var(--green);box-shadow:0 0 0 3px var(--green-halo)}
.tm-sub{font-size:13px;color:var(--muted);margin-top:3px}
.tm-sub b{color:var(--ink);font-weight:600;font-variant-numeric:tabular-nums}
.tm-open{flex:none;font-size:13px;font-weight:600;color:var(--accent-ink);background:var(--accent-soft);border-radius:999px;padding:4px 10px}

/* The microphone check: every step in front of whoever is holding the phone,
   so a report comes back as a fact instead of «ما يشتغل». */
.mic-log{margin-top:10px;display:flex;flex-direction:column;gap:6px}
.mic-step{display:flex;flex-direction:column;gap:2px;padding:8px 10px;border-radius:10px;background:var(--card2);border:1px solid var(--hair)}
.mic-step b{font-size:15px;font-weight:600}
.mic-step span{font-size:13px;color:var(--muted);word-break:break-word;direction:ltr;text-align:start}
.mic-step.ok b{color:var(--ok)}
.mic-step.bad b{color:var(--red)}
.mic-step.warn b{color:var(--amber-ink)}
.mic-step.run b{color:var(--muted)}
.mic-step.run{border-style:dashed}
.mic-play{width:100%;margin-top:10px}

/* tab bar: a glass capsule floating over the content, five equal tabs, the
   selected one filled and tinted, a red badge for what needs him */
.tabs:empty{display:none}
.tabs{position:fixed;bottom:calc(12px + env(safe-area-inset-bottom,0px));inset-inline:16px;max-width:528px;margin:0 auto;height:var(--tab-h);
  border-radius:999px;background:var(--tabs-bg);backdrop-filter:blur(24px) saturate(1.4);-webkit-backdrop-filter:blur(24px) saturate(1.4);
  box-shadow:0 8px 32px rgba(0,0,0,.14),inset 0 0 0 .5px var(--glass-edge);display:flex;z-index:40;padding:0 4px}
.tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;color:var(--muted);font-size:10px;font-weight:500;position:relative;min-height:44px;transition:color .18s;border-radius:999px}
.tab svg{width:26px;height:26px;stroke-width:1.6;transition:transform .18s}
.tab.on{color:var(--accent);font-weight:600}
.tab .tbadge{position:absolute;top:7px;inset-inline-start:calc(50% + 6px);min-width:18px;height:18px;border-radius:9px;
  background:var(--red);color:var(--on-red);font-size:11px;font-weight:600;display:grid;place-items:center;padding:0 5px;font-variant-numeric:tabular-nums}

/* login */
.login{min-height:calc(100dvh - 80px);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:24px;text-align:center}
/* The Omixus mark itself, drawn in the accent. */
.login-logo{width:88px;height:88px;display:grid;place-items:center;color:var(--accent);margin-bottom:8px}
.login-logo svg{width:100%;height:100%}
.login-title{font-size:28px;font-weight:700;color:var(--ink);letter-spacing:-.3px}
/* Balanced lines: no last word left alone on a line of its own. */
.login-sub{font-size:15px;color:var(--muted);line-height:1.5;white-space:nowrap}
.login-in{width:min(78vw,300px);background:var(--card);color:var(--ink);border:1px solid var(--hair);border-radius:12px;padding:13px 16px;
  font-size:17px;text-align:center;outline:none;direction:ltr;margin-top:8px;min-height:50px}
.login-in::placeholder{color:var(--faint)}
.login-in:focus{border-color:var(--accent)}
.login-in.code{font-size:26px;letter-spacing:8px;font-variant-numeric:tabular-nums}
.login-go{width:min(78vw,300px);background:var(--accent);color:var(--on-accent);border-radius:12px;
  padding:0 16px;font-size:17px;font-weight:600;min-height:50px}
.login-go:disabled{opacity:.5}
.login-alt{font-size:15px;color:var(--accent);font-weight:400;padding:8px;min-height:44px}
.login-demo{margin-top:22px;font-size:13px;color:var(--muted);padding:8px;min-height:44px}

/* call-style appointment alarm, drawn like a system alert on glass */
.alarm{position:fixed;inset:0;z-index:90;display:none;background:var(--alarm-scrim);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.alarm.on{display:grid;place-items:center}
.alarm-card{width:min(86vw,300px);background:var(--card);border-radius:24px;padding:24px 20px 16px;text-align:center;
  box-shadow:var(--shadow-lg);animation:rise .3s cubic-bezier(.32,.72,.35,1)}
.alarm-pulse{width:64px;height:64px;border-radius:50%;margin:0 auto 14px;display:grid;place-items:center;color:var(--on-accent);
  background:var(--accent);animation:alarmpulse 1.4s infinite}
.alarm-pulse svg{width:30px;height:30px;stroke:var(--on-accent)}
@keyframes alarmpulse{0%,100%{box-shadow:0 0 0 0 var(--accent-glow-wide)}50%{box-shadow:0 0 0 16px transparent}}
.alarm-title{font-size:13px;font-weight:600;color:var(--accent-ink);margin-bottom:4px}
.alarm-name{font-size:20px;font-weight:700;color:var(--ink)}
.alarm-meta{font-size:13px;color:var(--muted);margin-top:4px}
.alarm-time{font-size:34px;font-weight:700;color:var(--ink);margin:10px 0 18px;font-variant-numeric:tabular-nums;letter-spacing:-.5px;direction:ltr}
.alarm-btns{display:flex;gap:10px}
.ab{flex:1;border-radius:12px;padding:0 12px;font-size:17px;font-weight:600;min-height:50px}
.ab.ok{background:var(--fill);color:var(--accent)}
.ab.go{background:var(--accent);color:var(--on-accent)}

/* the iOS alert: 270 wide, glass, one question, two buttons */
.dialog-wrap{position:fixed;inset:0;z-index:95;display:none}
.dialog-wrap.on{display:grid;place-items:center}
.dialog-wrap .scrim{position:absolute;inset:0;background:var(--scrim)}
.alert{position:relative;width:270px;background:var(--glass);backdrop-filter:blur(30px) saturate(1.4);-webkit-backdrop-filter:blur(30px) saturate(1.4);
  border-radius:14px;text-align:center;overflow:hidden;box-shadow:var(--shadow-lg);animation:rise .2s cubic-bezier(.32,.72,.35,1)}
.al-title{font-size:17px;font-weight:600;padding:19px 16px 4px}
.al-body{font-size:13px;color:var(--muted);padding:0 16px 16px;line-height:1.4}
.al-btns{display:flex;border-top:1px solid var(--hair)}
.al-b{flex:1;min-height:44px;font-size:17px;color:var(--accent)}
.al-b + .al-b{border-inline-start:1px solid var(--hair)}
.al-b.primary{font-weight:600}
.al-b.danger{color:var(--red);font-weight:600}
.ghost.small{min-height:36px;font-size:15px;margin-top:10px}

/* sheet */
.sheet-wrap{position:fixed;inset:0;z-index:60;display:none}
.sheet-wrap.on{display:block}
.scrim{position:absolute;inset:0;background:var(--scrim)}
.sheet{position:absolute;bottom:0;inset-inline:0;max-width:560px;margin:0 auto;background:var(--card);border:0;touch-action:none;
  border-radius:20px 20px 0 0;padding:8px 16px calc(env(safe-area-inset-bottom,0px) + 16px);
  animation:up .3s cubic-bezier(.32,.72,.35,1);box-shadow:var(--sheet-shadow)}
.sheet::before{content:"";display:block;width:36px;height:5px;border-radius:3px;background:var(--sheet-grip);margin:2px auto 14px}
@keyframes up{from{transform:translateY(45%)}to{transform:none}}
.sheet h3{font-size:17px;font-weight:600;margin-bottom:16px;text-align:center}
/* the row's menu: an iOS action sheet — a head, a list of choices, cancel apart */
.as-head{text-align:center;padding:2px 8px 12px}
.as-head b{display:block;font-size:15px;font-weight:600}
.as-head span{display:block;font-size:13px;color:var(--muted);margin-top:2px}
.as-list{background:var(--card2);border-radius:14px;overflow:hidden}
.as-btn{display:flex;align-items:center;gap:12px;width:100%;min-height:52px;padding:0 16px;font-size:17px;color:var(--accent);text-align:start}
.as-btn + .as-btn{border-top:1px solid var(--hair)}
.as-btn svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.8;flex:none;transform:none}
.as-btn:active{background:var(--fill)}
.as-cancel{display:block;width:100%;min-height:52px;margin-top:10px;border-radius:14px;background:var(--card2);color:var(--accent);font-size:17px;font-weight:600}
.field{margin-bottom:12px}
.field label{display:block;font-size:13px;color:var(--muted);margin-bottom:6px}
.field input,.field select{width:100%;background:var(--card2);border:0;border-radius:10px;padding:12px 14px;color:var(--ink);outline:none;min-height:44px;font-size:17px}
.field input::placeholder{color:var(--faint)}
.field input:focus{box-shadow:0 0 0 2px var(--accent-soft)}
.sheet .go{width:100%;background:var(--accent);color:var(--on-accent);border-radius:12px;padding:0 16px;font-weight:600;font-size:17px;margin-top:8px;min-height:50px}
.toast{position:fixed;bottom:calc(var(--tab-h) + 32px + env(safe-area-inset-bottom,0px));left:50%;transform:translateX(-50%) translateY(16px);
  background:var(--toast-bg);color:var(--toast-ink);padding:10px 20px;border-radius:999px;font-size:15px;font-weight:600;z-index:80;opacity:0;pointer-events:none;transition:.25s;white-space:nowrap;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.toast.show{opacity:1;transform:translateX(-50%)}

/* the thread's «المزيد»: two groups, the final ones red */
.as-list + .as-list{margin-top:10px}
.as-btn.danger{color:var(--red)}
/* The customer's card: head, contact, the job, his history with this technician. */
.cs{max-height:calc(88vh - 48px);overflow-y:auto;overscroll-behavior:contain;touch-action:pan-y;-webkit-overflow-scrolling:touch;margin:0 -4px;padding:0 4px 4px}
.cs-head{display:flex;flex-direction:column;align-items:center;gap:3px;padding:0 0 14px;text-align:center}
.cs-head .avatar{width:64px;height:64px;font-size:17px;margin-bottom:5px}
.cs-name{font-size:20px;font-weight:700}
.cs-sub{font-size:13px;color:var(--muted)}
.cs-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;margin-top:8px}
.cs-title{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:13px;font-weight:600;color:var(--muted);padding:16px 12px 6px}
.cs-total{font-variant-numeric:tabular-nums;color:var(--ok)}
.cs-total.neg{color:var(--red)}
.cs-group{background:var(--card2);border-radius:14px;overflow:hidden}
.cs-row{display:flex;align-items:center;gap:12px;width:100%;min-height:50px;padding:0 14px;font-size:16px;color:var(--ink);text-align:start;text-decoration:none}
.cs-row + .cs-row{border-top:1px solid var(--hair)}
.cs-row svg,.cs-hit svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.8;color:var(--accent);flex:none;transform:none}
.cs-row > svg:last-child:not(:first-child){width:16px;height:16px;color:var(--faint);stroke-width:2.2}
.cs-row .k{color:var(--muted);font-size:15px;flex:none}
.cs-row .v{flex:1;min-width:0;text-align:end;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cs-row .v.num{font-variant-numeric:tabular-nums;direction:ltr;font-weight:600;color:var(--accent)}
.cs-row .v.start{text-align:start;color:var(--muted);font-size:14px;white-space:normal;padding:12px 0}
.cs-row.dim{color:var(--muted)}
.cs-row.dim svg{color:var(--faint)}
.cs-hit{display:flex;align-items:center;gap:12px;flex:1;min-width:0;min-height:50px;text-align:start;font-size:16px;color:var(--ink)}
.cs-copy{width:36px;height:36px;border-radius:50%;background:var(--fill);display:grid;place-items:center;flex:none;color:var(--accent)}
.cs-copy svg{width:18px;height:18px}
.cs-copy:active,.cs-row:active,.cs-hit:active{opacity:.6}
.cs-row.job{padding-block:8px}
.cs-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cs-t{font-size:16px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cs-row .sub{font-size:12px;color:var(--muted)}
.cs-amt{flex:none;font-weight:600;font-variant-numeric:tabular-nums;color:var(--ok);font-size:15px}
.cs-amt.zero{color:var(--faint);font-weight:400}
.cs-amt.neg{color:var(--red)}
.cs-amt.open{color:var(--accent)}

/* «انزل لاخر مسج»: a round button over the thread, on only when he is a screen up */
.to-end{position:absolute;inset-inline-start:16px;bottom:140px;width:40px;height:40px;border-radius:50%;background:var(--card);color:var(--accent);
  box-shadow:0 2px 10px rgba(0,0,0,.18),0 0 0 1px var(--hair);display:none;place-items:center;z-index:3}
.to-end.on{display:grid;animation:pop .18s cubic-bezier(.32,.72,.35,1)}
@keyframes pop{from{transform:scale(.6);opacity:0}to{transform:none;opacity:1}}
.to-end svg{width:22px;height:22px;stroke:currentColor;fill:none}
.to-end .n{position:absolute;top:-6px;inset-inline-end:-6px;min-width:20px;height:20px;padding:0 6px;border-radius:10px;background:var(--accent);color:var(--on-accent);font-size:12px;font-weight:700;display:none;place-items:center;font-variant-numeric:tabular-nums}
.to-end .n.on{display:grid}
/* the picture viewer: black, over everything; a tap or a pull down closes it, a double tap zooms */
.viewer{position:fixed;inset:0;z-index:80;background:#000;display:none}
.viewer.on{display:block;animation:vwfade .16s}
@keyframes vwfade{from{opacity:0}to{opacity:1}}
.vw-body{position:absolute;inset:0;overflow:auto;display:flex;align-items:center;justify-content:center;touch-action:pan-x pan-y;-webkit-overflow-scrolling:touch}
.vw-body img{max-width:100%;max-height:100%;object-fit:contain;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.viewer.zoom .vw-body{display:block}
.viewer.zoom .vw-body img{max-width:none;max-height:none;width:220%}
.vw-x{position:absolute;z-index:2;top:calc(10px + env(safe-area-inset-top,0px));inset-inline-start:12px;width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.16);color:#fff;display:grid;place-items:center}
.vw-x svg{width:20px;height:20px;stroke:currentColor;fill:none}
