/*
 * Brytix -- corporate light theme.
 *
 * Replaces the original dark glassmorphism. Three reasons it changed, all of them
 * practical rather than cosmetic:
 *
 *  1. Sunlight. A phone or laptop outdoors fights the sun by raising brightness, and a
 *     dark screen has almost no brightness to raise -- the panel ends up reflecting more
 *     sky than it emits. Light backgrounds with near-black text stay readable on a site
 *     at midday. This is the single biggest usability change here.
 *  2. The office. This is accounting and payroll software used at a desk all day.
 *     Blur, glow and translucency cost legibility and read as consumer, not corporate.
 *  3. Print. Half these screens are printed -- invoices, payslips, petty cash slips.
 *     A light UI and its printed form now look like the same document.
 *
 * Every class name from the previous theme is kept, so all 51 views render unchanged;
 * only the visual language moved. Palette follows the Masroofi family (light neutral
 * ground, one strong accent, generous whitespace) and Masroofi's own teal and sand
 * tokens, read out of the live masroofi.ae stylesheet so the two products read as
 * one family rather than as two unrelated apps that happen to share an owner.
 */
:root{
  /* Ground and ink, straight from Masroofi's neutral ramp: n-50 / n-0 / n-100 for the
     surfaces, n-900 / n-600 / n-400 for the ink. Brytix was already on #f6f7f8, so the
     two products were closer than they looked -- the chrome was the part that differed. */
  --bg:#f6f7f8;--surface:#ffffff;--surface-2:#f0f2f4;
  --text:#24282c;--muted:#5f666c;--faint:#9aa1a8;

  /* Deep teal carries the chrome (sidebar, avatars); a darker teal is the interactive
     accent. Two different jobs -- a navigation bar and a "save" button must not compete.
     The variables are still called --navy because 51 views reference them; renaming
     would be churn for no visual gain. The values are Masroofi's --ms-deep-1/2.

     Note which teal does the interactive work: Masroofi's brand teal (--ms-primary-500,
     #0faeba) is only about 2.4:1 against white, so white text on it fails WCAG AA badly
     -- outdoors on a site, unreadably so. It is kept for tints, borders and hovers, and
     buttons use primary-700/800 instead, which clear 4.5:1. This is the same sunlight
     constraint that drove the move off the dark theme. */
  --navy:#04353d;--navy-2:#044e58;--accent:#067a86;--accent-ink:#ffffff;
  --accent-50:#eefafb;--accent-500:#0faeba;--accent-600:#0c9fac;--accent-800:#056470;

  /* Status colours are Masroofi's success / accent / danger ramps. Its "accent" sand is
     doing warning duty here, which is what it already does on masroofi.ae. */
  --ok:#1a7a49;--warn:#a9761a;--bad:#bd3825;
  --ok-bg:#e4f6ec;--warn-bg:#fdf3e3;--bad-bg:#fdeeeb;
  --ok-line:#b9e2ca;--warn-line:#f0cd8a;--bad-line:#f2c6bc;

  --border:#e3e6ea;--border-strong:#cfd4d9;
  --radius:10px;--radius-lg:14px;
  --shadow:0 1px 2px rgba(4,53,61,.06),0 1px 3px rgba(4,53,61,.10);
  --shadow-lg:0 4px 14px rgba(4,53,61,.09);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;min-height:100%}
body{background:var(--bg);color:var(--text);font-size:14.5px;line-height:1.55;position:relative}
a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}
h1,h2,h3{margin:0 0 .5rem;font-weight:650;letter-spacing:-.01em;color:var(--text)}
h1{font-size:1.5rem}h2{font-size:1.1rem}
h3{font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;font-weight:700}
p{margin:.3rem 0}
.muted{color:var(--muted)}.small{font-size:.8rem}.right{text-align:end}.center{text-align:center}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.85em}

/* Surfaces. The class is still called .glass so every view keeps working, but there is
   no glass left in it -- a white card with a hairline border and a shadow you can barely
   see. Renaming it would mean touching all 51 views for no visual gain. */
.glass{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow)}
.card{padding:1.15rem 1.3rem;margin-bottom:1.1rem}
.card-title{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-bottom:.9rem;padding-bottom:.7rem;border-bottom:1px solid var(--border)}

/* app shell */
.shell{display:grid;grid-template-columns:248px 1fr;min-height:100vh}
.sidebar{padding:1rem .75rem;position:sticky;top:0;height:100vh;overflow-y:auto;background:var(--navy);border-inline-end:1px solid var(--navy)}
.brand{display:flex;align-items:center;gap:.6rem;padding:.5rem .6rem 1.1rem;font-weight:700;font-size:1.15rem;letter-spacing:.01em;color:#fff}
.brand .logo{width:30px;height:30px;display:inline-grid;place-items:center;flex:none;color:var(--accent)}
.brand .logo svg{width:100%;height:100%;display:block}
.brand .logo .dot{fill:var(--warn)}
.sidebar .brand .logo{color:#ffffff}
.sidebar .brand .logo .dot{fill:#f0cd8a}
.nav a{display:flex;align-items:center;gap:.6rem;padding:.5rem .7rem;border-radius:7px;color:#a9cfd4;margin:.08rem 0;font-weight:500;font-size:.88rem}
.nav a:hover{background:rgba(255,255,255,.08);color:#fff;text-decoration:none}
.nav a.active{background:var(--accent);color:#fff;font-weight:600}
.nav .sec{margin:1.1rem .7rem .35rem;font-size:.66rem;letter-spacing:.11em;text-transform:uppercase;color:#6f9aa1;font-weight:700}
.nav .badge{margin-inline-start:auto}

/* Icons. Sized here rather than on the element so one icon() call works in a nav item, a
   button and a <summary> alike. Slightly dimmed in the sidebar so the label leads and the
   icon supports; full strength on the active row. */
.ico{width:1.05em;height:1.05em;flex:none;vertical-align:-.16em}
.nav a .ico{width:17px;height:17px;opacity:.75}
.nav a:hover .ico,.nav a.active .ico{opacity:1}
summary .ico,.btn .ico,a .ico{opacity:.8}
summary:hover .ico,.btn:hover .ico{opacity:1}
.main{padding:1.4rem 1.8rem 3rem;max-width:1400px;width:100%}
.topbar{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:.6rem 1rem;margin-bottom:1.3rem;padding-bottom:.9rem;border-bottom:1px solid var(--border)}
.topbar>div:first-child{min-width:0;flex:1 1 auto}
.topbar h1{overflow-wrap:anywhere}
.topbar .who{display:flex;align-items:center;gap:.8rem;min-width:0}
/* The name must not be squeezed by the page title next to it: the avatar keeps its circle,
   and a long name ends in an ellipsis rather than wrapping mid-word or spilling out. */
.topbar .who>div:last-child{min-width:0}
.topbar .who>div:last-child>div{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:42vw}
.avatar{width:34px;height:34px;border-radius:50%;background:var(--navy-2);color:#fff;display:grid;place-items:center;font-weight:700;font-size:.9rem;flex:none}
.tenant-pill{padding:.3rem .75rem;border-radius:999px;background:var(--surface-2);border:1px solid var(--border);font-size:.8rem;color:var(--muted)}

/* KPI grid -- the numbers are the point, so they get weight and the labels recede. */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:1rem;margin-bottom:1.1rem}
.kpi{padding:1rem 1.2rem}
.kpi .label{color:var(--muted);font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
.kpi .value{font-size:1.65rem;font-weight:700;margin-top:.25rem;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.kpi .value.ok{color:var(--ok)}.kpi .value.bad{color:var(--bad)}.kpi .value.warn{color:var(--warn)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:1.1rem}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:1.1rem}
@media (max-width:1000px){.grid2,.grid3{grid-template-columns:1fr}.shell{grid-template-columns:1fr}.sidebar{position:relative;height:auto}}


/* Tables. Tighter than before: this app shows registers of hundreds of rows, and every
   pixel of row height is a row you cannot see without scrolling. */
.table-wrap{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:.875rem}
th{text-align:start;color:var(--muted);font-weight:700;font-size:.7rem;text-transform:uppercase;letter-spacing:.07em;padding:.5rem .6rem;border-bottom:2px solid var(--border-strong);background:var(--surface-2);white-space:nowrap}
td{padding:.5rem .6rem;border-bottom:1px solid var(--border);vertical-align:top}
tr:hover td{background:var(--accent-50)}
td.num,th.num{text-align:end;font-variant-numeric:tabular-nums}
.empty{padding:1.8rem;text-align:center;color:var(--muted)}

/* badges */
.badge{display:inline-block;padding:.12rem .55rem;border-radius:999px;font-size:.71rem;font-weight:600;text-transform:capitalize;border:1px solid transparent}
.badge-ok{background:var(--ok-bg);color:var(--ok);border-color:var(--ok-line)}
.badge-warn{background:var(--warn-bg);color:var(--warn);border-color:var(--warn-line)}
.badge-bad{background:var(--bad-bg);color:var(--bad);border-color:var(--bad-line)}
.badge-neutral{background:var(--surface-2);color:var(--muted);border-color:var(--border)}

/* forms */
form{margin:0}
.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:.8rem 1rem}
.form-grid .full{grid-column:1/-1}
label{display:block;font-size:.76rem;color:var(--muted);margin-bottom:.25rem;font-weight:600}
input,select,textarea{width:100%;padding:.5rem .7rem;border-radius:var(--radius);border:1px solid var(--border-strong);background:var(--surface);color:var(--text);font:inherit;outline:none;transition:border .15s,box-shadow .15s}
input:focus,select:focus,textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(15,174,186,.22)}
input::placeholder,textarea::placeholder{color:var(--faint)}
textarea{min-height:80px;resize:vertical}
input[type=file]{padding:.35rem}
input[type=checkbox]{width:auto;accent-color:var(--accent)}
.inline{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}
.inline input,.inline select{width:auto;min-width:120px}
.actions{display:flex;gap:.6rem;flex-wrap:wrap;margin-top:.9rem;align-items:center}
.btn{display:inline-flex;align-items:center;gap:.4rem;padding:.48rem .9rem;border-radius:var(--radius);border:1px solid var(--border-strong);background:var(--surface);color:var(--text);font:inherit;font-weight:600;font-size:.86rem;cursor:pointer;transition:background .15s,border-color .15s;text-decoration:none!important}
.btn:hover{background:var(--surface-2);border-color:var(--faint)}
.btn-primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.btn-primary:hover{background:var(--accent-800);border-color:var(--accent-800)}
.btn-danger{background:var(--surface);border-color:var(--bad-line);color:var(--bad)}
.btn-danger:hover{background:var(--bad-bg);border-color:var(--bad)}
.btn-sm{padding:.26rem .6rem;font-size:.78rem;border-radius:7px}
.btn-block{width:100%;justify-content:center}
details.glass{margin-bottom:1.1rem}
details.glass summary{list-style:none;cursor:pointer;padding:.85rem 1.3rem;font-weight:600;display:flex;justify-content:space-between;align-items:center}
details.glass summary::-webkit-details-marker{display:none}
details.glass summary::after{content:"+";font-size:1.25rem;color:var(--muted);font-weight:400}
details[open].glass summary::after{content:"-"}
details[open].glass summary{border-bottom:1px solid var(--border)}
details.glass .body{padding:1rem 1.3rem 1.2rem}

/* flash -- a left rule rather than a full tinted panel; it reads as a note, not an alarm */
.flash{padding:.75rem 1.05rem;border-radius:var(--radius);margin-bottom:1rem;border:1px solid;border-inline-start-width:4px}
.flash-success{background:var(--ok-bg);border-color:var(--ok-line);border-inline-start-color:var(--ok);color:#12603a}
.flash-error{background:var(--bad-bg);border-color:var(--bad-line);border-inline-start-color:var(--bad);color:#8c2718}
.flash ul{margin:.3rem 0 0 1rem;padding:0}

/* auth */
.auth-wrap{min-height:100vh;display:grid;place-items:center;padding:1.5rem;background:linear-gradient(160deg,#f8fbfc,#eefafb 55%,#e0f2f4)}
.auth-card{width:100%;max-width:420px;padding:2rem;box-shadow:var(--shadow-lg)}
.auth-card .brand{justify-content:center;padding-bottom:1.4rem;color:var(--text)}

/* chat */
.chat{display:grid;grid-template-columns:280px 1fr;gap:1rem;min-height:70vh}
.threads a{display:block;padding:.65rem .85rem;border-radius:var(--radius);color:var(--text)}
.threads a:hover,.threads a.active{background:var(--surface-2);text-decoration:none}
.msgs{display:flex;flex-direction:column;gap:.5rem;padding:1rem;overflow-y:auto;max-height:60vh}
.msg{max-width:70%;padding:.55rem .85rem;border-radius:14px;font-size:.9rem}
.msg.out{align-self:flex-end;background:var(--accent);color:#fff}
.msg.in{align-self:flex-start;background:var(--surface-2);border:1px solid var(--border)}
.msg .meta{font-size:.68rem;opacity:.75;margin-top:.2rem}

/* kanban */
.kanban{display:grid;grid-template-columns:repeat(7,minmax(170px,1fr));gap:.7rem;overflow-x:auto}
.kanban .col{padding:.7rem;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius)}
.kanban .col h3{margin-bottom:.5rem}
.lead-card{display:block;padding:.55rem .7rem;border-radius:8px;background:var(--surface);border:1px solid var(--border);margin-bottom:.5rem;color:var(--text);font-size:.85rem}
.lead-card:hover{text-decoration:none;border-color:var(--accent);box-shadow:var(--shadow)}

/* aging bars */
.bar{height:10px;border-radius:999px;background:var(--surface-2);overflow:hidden;display:flex;border:1px solid var(--border)}
.bar span{display:block;height:100%}
.legend{display:flex;gap:1rem;flex-wrap:wrap;font-size:.78rem;color:var(--muted);margin-top:.4rem}
.dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-inline-end:.3rem;vertical-align:middle}

/* document */
.doc-head{display:flex;justify-content:space-between;gap:2rem;flex-wrap:wrap;margin-bottom:1.2rem;padding-bottom:1rem;border-bottom:2px solid var(--text)}
.totals{margin-inline-start:auto;width:320px}
.totals td{padding:.3rem .6rem}
.totals tr:last-child td{font-weight:700;font-size:1.05rem;border-top:1px solid var(--border-strong)}
.totals tr:hover td{background:transparent}

/* legal */
.prose{max-width:820px;margin:0 auto;padding:2rem}
.prose h2{margin-top:1.4rem}
.prose li{margin:.25rem 0}

/* The screen is already light, so printing mostly means removing chrome rather than
   inverting colours -- which is the point of having moved to a light theme. */
/* ---- charts ----
 * Rendered server-side as inline SVG by App\Services\Chart (the CSP forbids CDN chart
 * libraries). Sizing lives here rather than on the element so one service serves the
 * dashboard, reports and the print stylesheet without knowing about any of them. */
.chart{display:block;width:100%;height:auto;margin:.35rem 0 .2rem;overflow:visible}
.chart-donut{max-width:180px;margin-inline:auto}
.chart-data{margin-top:.6rem;font-size:.82rem}
.chart-data summary{cursor:pointer;color:var(--muted);padding:.25rem 0;list-style:none}
.chart-data summary::-webkit-details-marker{display:none}
.chart-data summary::before{content:"\25B8 ";color:var(--faint)}
.chart-data[open] summary::before{content:"\25BE "}
.chart-data summary:hover{color:var(--accent)}
.chart-data table{margin-top:.35rem}

/* ---- signature pad ----
 * Touch-action none so a finger draws instead of scrolling the page; without it the pad is
 * unusable on the phone it is meant to be signed on. */
.sig-pad{border:1px dashed var(--border);border-radius:var(--radius);background:var(--surface);padding:.5rem;max-width:620px}
.sig-pad canvas{display:block;width:100%;height:180px;touch-action:none;cursor:crosshair;background:var(--surface)}
.sig-pad .btn{margin-top:.4rem}
@media print{.sig-pad{display:none}}

@media print{
  /* A chart is a summary; on paper the figures are the point, so the collapsed table is
     forced open and printed underneath its chart. */
  .chart-data[open] summary,.chart-data summary{color:#333}
  .chart-data > div{display:block!important}
  .chart-data{display:block!important}
  details.chart-data > .table-wrap{display:block!important}
}
@media print{
  body{background:#fff}
  .brand .logo{color:#24282c}.brand .logo .dot{fill:#24282c}
  .glass{border:1px solid #ddd;box-shadow:none}
  .no-print{display:none!important}
  th{color:#333;background:#f4f4f4}td{border-color:#eee}
  tr:hover td{background:transparent}
}

/* ---- Finance documents: amount in words, QR block, P&L rules ---- */
.totals.words{width:100%;margin:.6rem 0 0}
.totals.words th{text-align:start;color:var(--muted);font-weight:600;vertical-align:top;padding:.3rem .6rem;background:transparent;border-bottom:0;text-transform:none;letter-spacing:0;font-size:.8rem}
.totals.words tr:last-child td{font-weight:400;font-size:inherit;border-top:0}
.qr-block{display:flex;gap:1rem;align-items:center;margin-top:1rem}
.qr-block svg{border:1px solid var(--border);border-radius:8px;background:#fff}
.grid4{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:1rem;margin-bottom:1.1rem}
tr.rule td{border-top:1px solid var(--border-strong)}
.ok{color:var(--ok)}.warn{color:var(--warn)}.bad{color:var(--bad)}
@media print{.qr-block svg{border-color:#ddd}}
/* Phones. The topbar stops being one row: the page title takes the first line and the
   person's name and role the second, at full width, so neither is crushed by the other.
   Everything else just gets its side padding back -- 1.8rem each side on a 375px screen is
   a fifth of the display spent on nothing. */
@media (max-width:640px){
  .main{padding:1rem .9rem 2.5rem}
  h1{font-size:1.25rem}
  .topbar{align-items:flex-start}
  .topbar .who{width:100%;justify-content:flex-start;flex-wrap:wrap}
  .topbar .who>div:last-child>div{max-width:none;white-space:normal}
  .topbar .who .inline{flex-wrap:wrap;gap:.4rem}
  .tenant-pill{max-width:100%;overflow-wrap:anywhere}
  .kpis{grid-template-columns:1fr;gap:.7rem}
  .kpi{padding:.8rem .9rem}
  .kpi .value{font-size:1.4rem}
  .card{padding:1rem .9rem}
  .form-grid{grid-template-columns:1fr}
}

/* Language switch in the top bar. Two words, the current one plain and the other a link --
   a <select> would need a submit button or JavaScript, and this is one tap either way. */
.lang-switch{display:flex;align-items:center;gap:.35rem;font-size:.8rem}
.lang-switch .lang-on{color:var(--muted);font-weight:700}
.lang-switch .lang-off{background:none;border:0;padding:.15rem .35rem;font:inherit;color:var(--accent);cursor:pointer;border-radius:6px}
.lang-switch .lang-off:hover{background:var(--accent-50);text-decoration:underline}

/* Arabic.
   Almost nothing is needed here: the layout is flex and grid, and the directional
   properties above are logical (inline-start/end), so the whole shell mirrors itself when
   dir="rtl" is set on <html>. What remains is the handful of places where mirroring is
   wrong or where Latin text is deliberately kept left-to-right. */
[dir="rtl"] body{
  /* Noto Naskh and Dubai are the two faces most likely to be installed on a UAE machine;
     Tahoma is the universal fallback that has covered Arabic on Windows for two decades. */
  font-family:"Noto Naskh Arabic","Dubai",Tahoma,-apple-system,BlinkMacSystemFont,"Segoe UI",Arial,sans-serif;
}
/* Numbers, money, IBANs, plate numbers, TRNs and e-mail addresses stay left-to-right even
   inside an Arabic sentence. Without this an IBAN renders with its country code at the
   wrong end and looks like a different account -- the kind of error that misdirects a
   salary payment. */
[dir="rtl"] .mono,[dir="rtl"] .num,[dir="rtl"] td.num,[dir="rtl"] .kpi .value,
[dir="rtl"] input[type="email"],[dir="rtl"] input[type="tel"],[dir="rtl"] input[type="date"],
[dir="rtl"] input[type="month"],[dir="rtl"] input[type="number"],[dir="rtl"] input[type="datetime-local"]{
  direction:ltr;text-align:start;unicode-bidi:isolate;
}
[dir="rtl"] td.num,[dir="rtl"] th.num{text-align:end}
/* The arrows in "Chase them first →" point the wrong way when the text runs the other way. */
[dir="rtl"] .arrow-flip{display:inline-block;transform:scaleX(-1)}

/* ---- Navigation: drill-down groups, one unmistakable active row ----------------------
   A heading is a <summary>: tap it to open or close the group. No JavaScript, it keeps
   working with the CSP as it stands, and the browser remembers nothing -- the group that
   contains the page you are on is rendered already open, which is the only state that
   matters on arrival. */
.nav-group{margin:.5rem 0 .15rem}
.nav-group>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:.4rem;
  margin:0 .7rem .3rem;padding:.25rem 0;font-size:.66rem;letter-spacing:.11em;
  text-transform:uppercase;color:#6f9aa1;font-weight:700;user-select:none}
.nav-group>summary::-webkit-details-marker{display:none}
.nav-group>summary::after{content:"";margin-inline-start:auto;width:0;height:0;
  border-inline-start:4px solid currentColor;border-top:4px solid transparent;border-bottom:4px solid transparent;
  transition:transform .15s}
.nav-group[open]>summary::after{transform:rotate(90deg)}
[dir="rtl"] .nav-group[open]>summary::after{transform:rotate(-90deg)}
.nav-group>summary:hover{color:#a9cfd4}
/* A closed group holding the current page still says so, without opening. */
.nav-dot{width:6px;height:6px;border-radius:50%;background:var(--active);flex:none}
.nav-group[open] .nav-dot{display:none}

/* The active row.
   Ferrari red, as asked -- but #FF2800 exactly gives 3.8:1 against white, which fails
   WCAG AA for text this size. #E01B00 is the same red to the eye and clears 4.5:1, so the
   label is still readable to someone with low vision or on a sunlit phone. The pure
   Ferrari red is kept for the indicator bar and the dot, where nothing has to be read. */
:root{--active:#ff2800;--active-fill:#e01b00}
.nav a.active{background:var(--active-fill);color:#fff;font-weight:700;position:relative}
.nav a.active::before{content:"";position:absolute;inset-inline-start:0;top:6px;bottom:6px;
  width:3px;border-radius:0 3px 3px 0;background:var(--active)}
[dir="rtl"] .nav a.active::before{border-radius:3px 0 0 3px}
.nav a.active:hover{background:var(--active-fill);color:#fff}
.nav a.active .ico{opacity:1}

/* ---- Module switches ----------------------------------------------------------------
   Two shapes for the same idea. A matrix on the platform screen, because the question
   there is "which companies have Fleet" and that is a column you read down. A short list
   inside each user's row on the company screen, because the question there is "what does
   Ahmed see" and that is one person at a time. */
.module-matrix th{white-space:nowrap;font-weight:600}
.module-matrix td.tick{text-align:center;vertical-align:middle}
.module-matrix td.tick input{width:18px;height:18px;cursor:pointer;accent-color:var(--active-fill)}
/* The whole cell is the target, not just the 18px box -- this gets used on a phone. */
.boxlabel{display:block;padding:.45rem .2rem;cursor:pointer;border-radius:6px}
.boxlabel:hover{background:rgba(0,0,0,.04)}

.boxrow{display:inline-flex;align-items:center;gap:.35rem;margin-inline-end:.9rem;
  margin-block:.2rem;white-space:nowrap;cursor:pointer}
/* min-width:0 is not decoration. These rows are usually `class="inline small boxrow"`, and
   `.inline input` sets min-width:120px for text fields and selects — which a 16px checkbox
   also inherits, reserving 120px of nothing and pushing its own label a hand's width to the
   right. width:16px did not save it: min-width wins over width. */
.boxrow input{width:16px;height:16px;min-width:0;flex:none;accent-color:var(--active-fill);cursor:pointer}

details.modules>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;
  gap:.3rem;padding:.2rem .45rem;border:1px solid var(--line,rgba(0,0,0,.12));border-radius:6px}
details.modules>summary::-webkit-details-marker{display:none}
details.modules[open]>summary{margin-bottom:.5rem}
details.modules .ico{width:14px;height:14px}

/* ---------- Contracts ----------
   The bilingual pair. Two columns on a desktop, stacked on a phone: side-by-side clauses
   are the whole point of the layout, but two 40-character columns on a handset are worse
   than one readable one, so below 900px they stack rather than shrink. Each column carries
   its own dir attribute, so this rule sets no direction of its own -- an Arabic column must
   read right-to-left inside an English interface, and the reverse. */
.bilingual{display:flex;gap:1.2rem;align-items:flex-start}
.bilingual>.col{flex:1 1 0;min-width:0}
.bilingual textarea{width:100%;font-family:inherit;line-height:1.5}
.contract-body{white-space:pre-wrap;word-wrap:break-word;line-height:1.6}
@media (max-width:900px){.bilingual{flex-direction:column}}

.sig-row{display:flex;justify-content:space-between;gap:1rem;align-items:flex-start;
  padding:.7rem 0;border-block-end:1px solid var(--line,rgba(0,0,0,.12))}
.sig-row:last-child{border-block-end:none}
.sig-row .sig-img{max-height:60px;display:block;margin-top:.35rem;
  background:#fff;border:1px solid var(--line,rgba(0,0,0,.12));border-radius:4px}
.sig-actions details>summary{list-style:none;cursor:pointer}
.sig-actions details>summary::-webkit-details-marker{display:none}

/* Clause-by-clause sync panel. The tint is a warning that two columns have diverged, never
   a claim that a translation is wrong -- nothing in the app reads either language. */
.sync-panel{margin-top:1rem;padding-top:.8rem;border-top:1px solid var(--line,rgba(0,0,0,.12))}
.sync-table td{vertical-align:top}
.sync-table tr.state-en_moved td,
.sync-table tr.state-ar_moved td,
.sync-table tr.state-both_moved td,
.sync-table tr.state-missing td{background:var(--warn-bg)}
.sync-actions{display:flex;gap:.3rem;flex-wrap:wrap;margin-top:.3rem}
.sync-draft{margin-top:.8rem;padding:.7rem;border:1px solid var(--warn-line);
  background:var(--warn-bg);border-radius:8px}
.sync-draft textarea{width:100%;font-family:inherit;line-height:1.5}

/* Ask Brytix — the floating assistant.
   The first and only position:fixed element in this project. Two conventions it must respect:
   z-index stays in the same register as .site-head (20) rather than jumping to 9999, and every
   offset is logical (inset-inline-end) so the whole thing mirrors to the left in Arabic with
   no [dir="rtl"] rules at all. The one exception is noted below. */
.ask{position:fixed;inset-inline-end:1.25rem;bottom:1.25rem;z-index:30;display:flex;
     flex-direction:column;align-items:flex-end;gap:.6rem}
[dir="rtl"] .ask{align-items:flex-start}

/* --accent, not --accent-500: the launcher carries white text and #0faeba is ~2.4:1 on white,
   which fails AA. See the note by the colour tokens above. */
.ask-launch{display:inline-flex;align-items:center;gap:.5rem;padding:.6rem .95rem;
            background:var(--accent);color:var(--accent-ink);border:0;border-radius:999px;
            box-shadow:var(--shadow-lg);cursor:pointer;font:inherit;font-weight:600;font-size:.9rem}
.ask-launch:hover{background:var(--accent-800)}
.ask-launch:focus-visible{outline:3px solid var(--accent-500);outline-offset:2px}
.ask-logo{display:inline-flex;width:1.35rem;height:1.35rem}
.ask-logo svg{width:100%;height:100%}
/* --warn-line is #f0cd8a, the same sand the sidebar mark uses on navy. Named token rather
   than a literal, and NOT an invented one: --sand does not exist, and a var() nobody defined
   silently takes its fallback forever. */
.ask-logo .dot{fill:var(--warn-line)}

.ask-panel{width:min(23rem,calc(100vw - 2.5rem));max-height:min(30rem,70vh);
           display:flex;flex-direction:column;overflow:hidden;box-shadow:var(--shadow-lg)}
/* The panel ships with the `hidden` attribute so it starts closed. That attribute works by a
   user-agent rule of `display:none`, which ANY class rule setting display beats on specificity
   -- so the line above silently un-hid it and the widget opened itself on every page load.
   Scoped to this component rather than a global [hidden]{display:none!important}: a blanket
   !important reset would be the wider fix, and would also be a change in behaviour for every
   other element in an app that has been shipping without one. */
.ask-panel[hidden]{display:none}
.ask-head{display:flex;align-items:center;gap:.5rem;padding:.7rem .9rem;
          border-block-end:1px solid var(--border);background:var(--surface-2)}
.ask-x{margin-inline-start:auto;background:none;border:0;font-size:1.4rem;line-height:1;
       color:var(--muted);cursor:pointer;padding:0 .2rem}
.ask-x:hover{color:var(--text)}

.ask-log{flex:1;overflow-y:auto;padding:.9rem;display:flex;flex-direction:column;gap:.55rem}
/* flex-end / flex-start are direction-aware, so the same rules mirror correctly. */
.ask-msg{max-width:88%;padding:.5rem .75rem;border-radius:var(--radius);font-size:.88rem;line-height:1.5}
.ask-out{align-self:flex-end;background:var(--accent);color:var(--accent-ink)}
.ask-in{align-self:flex-start;background:var(--surface-2);border:1px solid var(--border)}
.ask-in strong{display:block;margin-block-end:.2rem}
.ask-in a{display:inline-block;margin-block-start:.35rem;font-size:.83rem}
.ask-wait{align-self:flex-start;color:var(--muted);font-size:.85rem;padding:.2rem .3rem}

.ask-form{display:flex;gap:.4rem;padding:.7rem .9rem;border-block-start:1px solid var(--border)}
.ask-form input{flex:1;min-width:0}
.ask-foot{margin:0;padding:0 .9rem .8rem;font-size:.74rem;color:var(--faint);line-height:1.45}

/* On a phone the launcher text doubles the width of the bubble for no benefit, and the panel
   wants the full width it can get. */
@media (max-width:640px){
  .ask{inset-inline-end:.75rem;bottom:.75rem}
  .ask-launch-text{display:none}
  .ask-launch{padding:.7rem;border-radius:50%}
  .ask-panel{width:calc(100vw - 1.5rem);max-height:75vh}
}

/* Small utilities used by the project screens. Added rather than reached for inline, because
   a colour that means "this is bad" should mean it in one place. */
.bad-text{color:var(--bad)}
.warn-text{color:var(--warn)}
.warn-row{background:var(--warn-bg)}

/* The programme chart. HTML and CSS only: script-src is 'self', a vendored library would put
   hundreds of kilobytes of third-party code into a zero-dependency project to draw rectangles,
   and — the part that actually decides it — a JavaScript chart prints as a blank space, which
   is exactly where this one matters most, in a proposal handed to a client.
   Every offset is logical (inset-inline-start), so the whole chart mirrors under dir="rtl"
   with no separate rules. */
.gantt{margin:.6rem 0;font-size:.82rem}
.gantt-ruler{position:relative;height:1.3rem;margin-inline-start:13rem;margin-inline-end:3rem;
             border-block-end:1px solid var(--border);margin-block-end:.35rem}
.gantt-month{position:absolute;top:0;color:var(--faint);font-size:.72rem;
             border-inline-start:1px solid var(--border);padding-inline-start:.25rem;
             white-space:nowrap;overflow:hidden}
.gantt-row{display:flex;align-items:center;gap:.5rem;margin-block-end:.28rem}
.gantt-label{width:13rem;flex:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--text)}
.gantt-track{position:relative;flex:1;height:1.15rem;background:var(--surface-2);
             border-radius:3px;overflow:hidden}
.gantt-pct{width:3rem;flex:none;text-align:end;color:var(--muted);font-size:.75rem}
.gantt-bar{position:absolute;top:2px;bottom:2px;border-radius:3px;background:var(--accent-800);opacity:.35}
/* The fill is what was actually reported done, laid over the planned bar. A bar four-fifths
   along the calendar with a third filled in reads as late without anybody reading a number. */
.gantt-fill{position:absolute;inset-block:0;inset-inline-start:0;background:var(--accent);
            border-radius:3px;display:block}
.gantt-bar.gantt-late{outline:1px solid var(--bad)}
.gantt-bar.gantt-late .gantt-fill{background:var(--bad)}
.gantt-bar.gantt-done .gantt-fill{background:var(--ok)}
.gantt-approval{background:var(--warn)}
.gantt-handover{background:var(--navy-2)}
.gantt-today{position:absolute;inset-block:0;width:2px;background:var(--bad);opacity:.55;z-index:1}
@media (max-width:640px){
  .gantt-label{width:7rem}
  .gantt-ruler{margin-inline-start:7rem}
}
