:root{
  --bg:#F5F6F8; --surface:#FFFFFF; --surface-2:#F5F6F8; --line:#E3E6EB;
  --text:#0F1115; --dim:#5A6270; --faint:#68707E;   /* 36.3: was #8A93A1 — 3.1:1 on white, which is not text */
  --brand:#1A67D2; --brand-2:#0F4FA8; --on-brand:#FFFFFF; --brand-soft:#E5EFFC;
  --accent:#C0450F; --accent-solid:#E65420; --accent-soft:#FFF1E6;
  --ok:#127A4B; --ok-soft:#E4F5EC;
  --warn:#A85806; --warn-soft:#FFF2E2;   /* 36.3: was #B25E09 — 4.24:1 on its own tint */
  --bad:#C4331D; --bad-soft:#FDEAE6;
  --info:#1A67D2; --info-soft:#E8F0FD;
  --shadow:0 1px 2px rgba(15,17,21,.05), 0 10px 26px -18px rgba(15,17,21,.45);
  --r:14px;
}
/*
   36.3 — why there is no dark palette here.

   The portal is a light portal, and 34.9.3 said so to every browser:
   `color-scheme: only light` in shell.css, with the two colours stated
   outright for the engines that half-honour it.

   This file went on contradicting that declaration. Three blocks here still
   swapped in a dark palette whenever the PHONE was set to dark — and because
   the declaration stops the page itself from being darkened, the result was
   the worst of both: a page whose surfaces stayed light while its tokens
   painted for a dark one. Tony's screenshots are exactly that. "My reports"
   set in #E1ECFA, a colour meant for a black page, on the white page the
   declaration guarantees. A card painted #171B22 with navy letters on it.

   A half-kept promise about colour is worse than either answer. So the dark
   palette is gone and the portal reads the same on every device: the one it
   already told every browser it was. test/contrast363.js keeps it that way.

   If a real dark mode is wanted, it is its own piece of work: every token
   here, every hardcoded colour in the views, and the declaration in
   shell.css changed together — not a palette that fires on its own.
 */
*{box-sizing:border-box}
html,body{margin:0;padding:0;min-height:100%}
body{background:var(--bg);color:var(--text);font-size:15px;line-height:1.5;
  font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;-webkit-font-smoothing:antialiased}
h1,h2,h3{font-family:Poppins,Inter,sans-serif;margin:0;letter-spacing:-.02em;text-wrap:balance}
a{color:var(--brand-2)}
img{max-width:100%}
.mono{font-family:"IBM Plex Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums}
button,input,select,textarea{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:4px}

/* header */
.topbar{position:sticky;top:0;z-index:30;background:var(--surface);color:var(--text);
  display:flex;align-items:center;gap:14px;padding:8px 16px;flex-wrap:nowrap;
  border-bottom:1px solid var(--line)}
.topbar .mark{width:32px;height:32px;flex:none;object-fit:contain}
.topbar h1{font-family:Poppins,sans-serif;font-size:14.5px;font-weight:600;line-height:1.15}
.topbar .sub{font-size:9.5px;color:var(--faint);letter-spacing:.09em;text-transform:uppercase;font-weight:500;margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topgrow{flex:0 1 auto;min-width:0;margin-right:auto}
.topbar nav{display:flex;gap:1px;flex-wrap:nowrap;order:0;min-width:0;overflow-x:auto;
  scrollbar-width:none;-ms-overflow-style:none;
  background:var(--surface-2);border:1px solid var(--line);border-radius:999px;padding:3px}
.topbar nav::-webkit-scrollbar{display:none}
.topbar nav a{color:var(--dim);text-decoration:none;font-size:12.5px;font-weight:500;
  font-family:Inter,sans-serif;padding:6px 11px;border-radius:999px;white-space:nowrap}
.topbar nav a:hover{color:var(--text)}
.topbar nav a.on{background:var(--surface);color:var(--brand);font-weight:600;
  box-shadow:0 1px 2px rgba(15,17,21,.10)}
@media(max-width:700px){
  .topbar{flex-wrap:wrap;gap:8px}
  .topbar nav{order:3;width:100%}
  .topbar .sub{display:none}
}
.who{display:flex;align-items:center;gap:7px;flex:none;background:var(--surface-2);border:1px solid var(--line);
  border-radius:999px;padding:4px 12px 4px 5px;font-size:12px;font-weight:600;color:var(--text);text-decoration:none}
.who:hover{border-color:var(--brand)}
.who.cta{background:var(--brand);border-color:var(--brand);color:#fff;padding:8px 18px;font-family:Poppins,sans-serif}
.who.cta:hover{background:#1456B4;border-color:#1456B4}
.avatar{width:22px;height:22px;border-radius:999px;background:var(--brand);color:#fff;
  display:grid;place-items:center;font-size:10px;font-weight:700;font-family:Poppins,sans-serif}

/* The name opens a small panel: account, language, and the way out. */
.whomenu{position:relative;flex:none}
.whomenu>summary{list-style:none;cursor:pointer}
.whomenu>summary::-webkit-details-marker{display:none}
.whomenu .caret{font-size:9px;color:var(--faint)}
.whomenu[open]>summary{border-color:var(--brand)}
.whodrop{position:absolute;right:0;top:calc(100% + 6px);z-index:60;min-width:214px;
  background:var(--surface);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 12px 32px rgba(15,32,56,.16);padding:6px;display:flex;flex-direction:column;gap:2px}
.whohead{padding:9px 10px 8px;border-bottom:1px solid var(--line);margin-bottom:4px;
  display:flex;flex-direction:column;gap:2px}
.whohead strong{font-size:13.5px}
.whohead span{font-size:11.5px;color:var(--dim)}
.whodrop a,.whodrop button{display:block;width:100%;text-align:left;padding:9px 10px;border-radius:8px;
  font-size:13.5px;color:var(--text);text-decoration:none;background:none;border:0;cursor:pointer;font-weight:500}
.whodrop a:hover,.whodrop button:hover{background:var(--surface-2)}
.whodrop .signout{color:var(--bad);font-weight:600}
.wholangs{display:flex;align-items:center;gap:4px;padding:6px 10px;border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);margin:4px 0}
.wholangs .lab{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--faint);
  font-weight:600;margin-right:auto}
.wholangs button,.langpick button{padding:4px 8px;border-radius:7px;border:1px solid var(--line);
  background:var(--surface-2);font-size:11px;font-weight:700;letter-spacing:.04em;color:var(--dim);
  cursor:pointer;width:auto;min-height:0}
.wholangs button.on,.langpick button.on{background:var(--brand);border-color:var(--brand);color:#fff}
.langpick{display:flex;gap:4px}

main{max-width:900px;margin:0 auto;padding:18px 16px 60px}
main.wide{max-width:1180px}
.stack{display:flex;flex-direction:column;gap:14px}
.row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.spread{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.eyebrow{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);font-weight:600}
.h2{font-size:22px;font-weight:700}
.hint{font-size:12.5px;color:var(--faint)}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow)}
.card-pad{padding:15px}
.note{background:var(--surface-2);border:1px solid var(--line);border-left:3px solid var(--brand);
  border-radius:8px;padding:11px 13px;font-size:13px;color:var(--dim)}
/* 33.2 — the same box, for something that is not guidance.
   A `.note` is an explanation of the page and is folded away behind the "?"
   next to the title. A document's own facts — the sales order number, what
   this invoice no longer matches — must not disappear with the help text, so
   they wear this instead. */
.docnote{background:var(--surface-2);border:1px solid var(--line);border-left:3px solid var(--brand);
  border-radius:8px;padding:11px 13px;font-size:13px;color:var(--dim)}

/* The period picker. One row naming the window with a step either side, and
   one row of the five lengths. Both are links rather than a form: the period
   belongs in the address, so a chosen window can be bookmarked, sent to
   somebody, and reloaded into the same figures. */
/* Compact by design. This is a control, not a headline: it has to say which
   period is being looked at and let it be changed, and every pixel it takes is
   a pixel of figures pushed off the first screen. It ended up a little over a
   third shorter than it began, and stays full width on a phone — where each of
   the five segments is about seventy pixels across, so the target is wide even
   though it is not tall. */
.period{display:flex;flex-direction:column;gap:4px}
.periodbar{display:flex;align-items:stretch;gap:4px}
.periodbar .pstep{flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  min-width:32px;background:var(--surface);border:1px solid var(--line);border-radius:9px;
  text-decoration:none;color:var(--dim);font-size:16px;line-height:1;font-family:Poppins,sans-serif}
.periodbar .pstep:hover{border-color:var(--brand);color:var(--brand)}
.periodbar .pnow{flex:1 1 auto;display:flex;align-items:center;justify-content:center;gap:8px;
  flex-wrap:wrap;background:var(--surface);border:1px solid var(--line);border-radius:9px;
  padding:3px 10px;text-align:center}
.periodbar .plabel{font-family:Poppins,sans-serif;font-weight:600;font-size:12px;
  line-height:1.3;letter-spacing:-.01em}
.periodbar .pback{font-size:10px;font-weight:600;text-decoration:none;color:var(--brand);
  background:var(--brand-soft);border-radius:999px;padding:1px 7px;white-space:nowrap}
/* The segmented row. Shared with the Reports links below the summary, which
   are the same thing in kind — a short row of one-word choices — and which
   read as a different idea altogether when they were buttons floated beside a
   paragraph in a card. */
.pkinds{display:flex;gap:4px;background:var(--surface);border:1px solid var(--line);
  border-radius:9px;padding:2px}
.pkinds .pkind{flex:1 1 0;text-align:center;padding:4px;border-radius:6px;
  text-decoration:none;color:var(--dim);font-size:11.5px;line-height:1.3;
  font-weight:600;white-space:nowrap}
.pkinds .pkind:hover{background:var(--surface-2);color:var(--text)}
.pkinds .pkind.on{background:var(--brand);color:var(--on-brand)}
.pkinds .pkind:focus-visible,.periodbar .pstep:focus-visible,.periodbar .pback:focus-visible{
  outline:2px solid var(--brand);outline-offset:2px}
/* A row with more than five choices in it — the HR menu, a staff file's tabs —
   wraps rather than running off the side of a phone. Seven segments at 390px
   made the whole page scroll sideways, which is the one thing a layout must
   never do to somebody holding it in one hand. */
.pkinds.many{flex-wrap:wrap}
.pkinds.many .pkind{flex:1 1 auto;min-width:74px}

/* The arrows get a little more width on a phone — they are the one part of
   this that is narrow rather than wide, and a thumb needs somewhere to land. */
@media(max-width:620px){ .periodbar .pstep{min-width:36px} }
.kpis{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
@media(min-width:620px){.kpis{grid-template-columns:repeat(4,1fr)}}
.kpi{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:12px;display:flex;flex-direction:column;gap:3px}
.kpi .label{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);font-weight:600}
.kpi .val{font-family:Poppins,sans-serif;font-weight:700;font-size:24px;line-height:1.1;font-variant-numeric:tabular-nums}
.kpi .foot{font-size:11.5px;color:var(--dim)}
/* Two figures in one tile — requested and approved, each its own link to the
   records behind it. Label above value rather than beside it: a tile is a
   quarter of the row on a phone, and "Requested  AED 1,240.00 · USD 90.00"
   side by side wraps into nonsense the moment a second currency appears. */
.kpi .figs{display:flex;flex-direction:column;gap:2px;margin:2px 0 1px}
.kpi .fig{display:block;text-decoration:none;color:inherit;
  padding:3px 6px;margin:0 -6px;border-radius:9px;transition:background .12s}
.kpi .fig:hover{background:var(--surface-2)}
.kpi .fig:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.kpi .fig .k{display:block;font-size:10.5px;font-weight:600;color:var(--dim);
  text-transform:uppercase;letter-spacing:.05em}
.kpi .fig .v{display:block;font-family:Poppins,sans-serif;font-weight:700;
  font-size:17px;line-height:1.25;font-variant-numeric:tabular-nums}
.kpi .fig.ok .v{color:var(--ok)}
/* A counted figure is a name and a number on one line — "Collection   3" —
   rather than the stacked label-over-value a currency needs. Two of them read
   as a pair to be compared, which is the whole reason they share a box. */
.kpi .fig.count{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.kpi .fig.count .k{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:600}
.kpi .fig.count .v{font-size:22px}
/* The lead tile is a blue gradient, so its figures take their own ink and a
   light wash on hover; the grey ones would vanish into it. */
.kpi.lead .fig{color:#fff}
.kpi.lead .fig .k{color:rgba(255,255,255,.8)}
.kpi.lead .fig:hover{background:rgba(255,255,255,.16)}
.kpi.lead .fig:focus-visible{outline-color:rgba(255,255,255,.9)}
.kpi.lead{background:linear-gradient(140deg,#1A67D2,#3B86E8);border-color:transparent;color:#fff}
.kpi.lead .label,.kpi.lead .foot{color:rgba(255,255,255,.75)}

/* buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;background:var(--surface);
  border:1px solid var(--line);border-radius:10px;padding:10px 18px;font-size:14px;font-weight:600;
  font-family:Poppins,Inter,sans-serif;letter-spacing:.005em;
  min-height:44px;cursor:pointer;text-decoration:none;color:var(--text);transition:background .15s,border-color .15s}
.btn:hover{border-color:var(--brand)}
.btn.primary{background:var(--brand);border-color:var(--brand);color:var(--on-brand);font-weight:600}
.btn.primary:hover{background:#1456B4;border-color:#1456B4}
.btn.blue{background:var(--brand-2);border-color:var(--brand-2);color:#fff;font-weight:600}
.btn.orange{background:var(--accent-solid);border-color:var(--accent-solid);color:#fff;font-weight:600}
.btn.gold{background:var(--accent-solid);border-color:var(--accent-solid);color:#3A1C06;font-weight:600}
.btn.ok{background:var(--ok-soft);border-color:transparent;color:var(--ok);font-weight:600}
.btn.bad{background:var(--bad-soft);border-color:transparent;color:var(--bad);font-weight:600}
.btn.sm{min-height:34px;padding:6px 11px;font-size:12.5px}
.btn.block{width:100%}

/* forms */
.field{display:flex;flex-direction:column;gap:5px;min-width:0;margin-bottom:12px}
.field>label{font-size:11.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--faint)}
.field input,.field select,.field textarea{background:var(--surface-2);border:1px solid var(--line);
  border-radius:9px;padding:10px 11px;font-size:16px;width:100%;min-height:44px}
.field textarea{min-height:90px;resize:vertical}
/* Every form control in the portal used to say outline:none here, which beat
   the global :focus-visible rule and left someone working by keyboard with
   nothing but a pale wash they could not see — and could not see at all in
   dark mode. The ring stays for the mouse, and a real outline comes back for
   the keyboard. */
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(37,99,235,.22)}
.field input:focus-visible,.field select:focus-visible,.field textarea:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.grid2{display:grid;grid-template-columns:1fr;gap:0 12px}
@media(min-width:560px){.grid2{grid-template-columns:1fr 1fr}}
.check{display:flex;align-items:center;gap:9px;font-size:14px;margin-bottom:12px}
.check input{width:20px;height:20px;flex:none;accent-color:var(--brand)}

/*
 * 33.5 — a row you pick by tapping it.
 *
 * A checkbox beside a line of text is a twelve-pixel target held in one hand
 * in a corridor. The whole row is the target here: it is a <label>, so the tap
 * reaches the box the browser is already keeping for us, and the square drawn
 * on the left is only there to say what state the row is in. The real input is
 * still in the form, still posts, and is still what a keyboard tabs to.
 */
.pickrow{display:flex;align-items:flex-start;gap:11px;padding:11px 12px;margin:0;
  border:1px solid var(--line);border-radius:10px;background:var(--surface);cursor:pointer;
  text-transform:none;letter-spacing:0;font-size:14px;transition:background .12s,border-color .12s}
.pickrow:hover{background:var(--surface-2);border-color:var(--brand)}
.pickrow input{position:absolute;opacity:0;width:1px;height:1px;margin:0}
.pickbox{flex:none;width:20px;height:20px;margin-top:1px;border-radius:5px;
  border:2px solid var(--line);background:var(--surface);position:relative}
.pickbox::after{content:"";position:absolute;left:5px;top:1px;width:5px;height:10px;
  border:solid #fff;border-width:0 2.5px 2.5px 0;transform:rotate(42deg);opacity:0}
.pickrow:has(input:checked){background:var(--brand-soft,var(--surface-2));border-color:var(--brand)}
.pickrow:has(input:checked) .pickbox{background:var(--brand);border-color:var(--brand)}
.pickrow:has(input:checked) .pickbox::after{opacity:1}
.pickrow:has(input:focus-visible){outline:2px solid var(--brand);outline-offset:2px}
.pickbody{flex:1 1 auto;min-width:0}
.pickbody .chip{margin:3px 4px 0 0}

/* chips */
.chip{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;padding:3px 9px;border-radius:999px;background:var(--surface-2);color:var(--dim);border:1px solid var(--line)}
.chip.received{background:var(--info-soft);color:var(--info);border-color:transparent}
.chip.diagnosed{background:var(--brand-soft);color:var(--brand-2);border-color:transparent}
.chip.quote_sent{background:var(--warn-soft);color:var(--warn);border-color:transparent}
.chip.quote_approved,.chip.in_repair{background:var(--accent-soft);color:var(--accent);border-color:transparent}
.chip.quote_declined,.chip.refused{background:var(--bad-soft);color:var(--bad);border-color:transparent}
.chip.ready,.chip.ok,.chip.warranty,.chip.verified{background:var(--ok-soft);color:var(--ok);border-color:transparent}
.chip.closed{background:var(--surface-2);color:var(--dim)}
.chip.unverified{background:var(--warn-soft);color:var(--warn);border-color:transparent}

/* ticket rows */
.rec{display:grid;grid-template-columns:4px 1fr auto;gap:0 12px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r);overflow:hidden;text-decoration:none;color:var(--text)}
.rec+.rec{margin-top:8px}
.rec .stripe{align-self:stretch;background:var(--line)}
.rec.s-received .stripe{background:var(--info)} .rec.s-diagnosed .stripe{background:var(--brand-2)}
.rec.s-quote_sent .stripe{background:var(--warn)} .rec.s-quote_approved .stripe,.rec.s-in_repair .stripe{background:var(--accent-solid)}
.rec.s-quote_declined .stripe{background:var(--bad)} .rec.s-ready .stripe{background:var(--ok)}
.rec.s-closed .stripe{background:var(--faint)}
.rec .body{padding:11px 0;display:flex;flex-direction:column;gap:1px;min-width:0}
.rec .side{padding:11px 12px 11px 0;text-align:right;white-space:nowrap;display:flex;flex-direction:column;gap:4px;align-items:flex-end}
.rec .title{font-weight:600;font-size:14.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rec .meta{font-size:12.5px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rec .ref{font-size:11px;color:var(--faint)}
.amt{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums;font-weight:500;font-size:14px}

/* stage filter */
.stage{display:flex;gap:6px;overflow-x:auto;padding-bottom:4px}
.stage a{flex:none;border:1px solid var(--line);background:var(--surface);border-radius:999px;
  padding:6px 12px;font-size:12px;font-weight:500;color:var(--dim);white-space:nowrap;text-decoration:none}
.stage a.on{font-weight:600}
.stage a.on{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.stage a .n{opacity:.7;margin-left:5px}

/* steps */
.steps{display:flex;align-items:center;flex-wrap:wrap;gap:0;margin:6px 0}
.steps span{font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--faint)}
.steps span.on{color:var(--brand-2)} .steps span.done{color:var(--ok)}
.steps i{width:14px;height:1px;background:var(--line);margin:0 6px;font-style:normal}

/* tables */
.tblwrap{overflow-x:auto;background:var(--surface);border:1px solid var(--line);border-radius:var(--r)}
table{border-collapse:collapse;width:100%;font-size:13.5px}
th{text-align:left;font-size:10.5px;letter-spacing:.07em;text-transform:uppercase;color:var(--faint);
  font-weight:600;padding:8px 11px;border-bottom:1px solid var(--line);white-space:nowrap}
td{padding:9px 11px;border-bottom:1px solid var(--line);vertical-align:top}
tr:last-child td{border-bottom:0}
td.num,th.num{text-align:right;font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums}

/* misc */
.kv{display:grid;grid-template-columns:auto 1fr;gap:7px 16px;font-size:14px}
.kv dt{color:var(--faint);font-size:11px;letter-spacing:.05em;text-transform:uppercase;font-weight:600;padding-top:2px}
.kv dd{margin:0}
.flash{padding:11px 14px;border-radius:9px;font-size:14px;margin-bottom:14px;border:1px solid transparent}
.flash.ok{background:var(--ok-soft);color:var(--ok)}
.flash.warn{background:var(--warn-soft);color:var(--warn)}
.flash.bad{background:var(--bad-soft);color:var(--bad)}
.empty{text-align:center;padding:30px 16px;color:var(--dim)}
.money-lines{display:grid;grid-template-columns:1fr auto;gap:5px 14px;font-size:14px;padding:12px;
  background:var(--surface-2);border:1px solid var(--line);border-radius:10px}
.money-lines .t{font-weight:700;font-family:Poppins,sans-serif}
.money-lines .v{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums;text-align:right}
.ticketno{font-family:"IBM Plex Mono",monospace;font-size:26px;font-weight:500;color:var(--brand-2)}
/* ---- Projects ---- */
.grid3{display:grid;grid-template-columns:1fr;gap:0 12px}
@media(min-width:720px){.grid3{grid-template-columns:1fr 1fr 1fr}}
.rec.p-active .stripe{background:var(--brand)}
.rec.p-on_hold .stripe{background:var(--warn)}
.rec.p-delivered .stripe{background:var(--accent-solid)}
.rec.p-closed .stripe{background:var(--ok)}
.rec.p-cancelled .stripe{background:var(--bad)}
/* A row's edit form folds away until it is wanted, so the table stays readable. */
.rowedit>summary{cursor:pointer;font-size:12px;color:var(--brand);list-style:none;font-weight:600}
.rowedit>summary::-webkit-details-marker{display:none}
.rowedit[open]>summary{margin-bottom:4px}
.rowedit input,.rowedit select,.rowedit textarea{background:var(--surface-2);border:1px solid var(--line);
  border-radius:8px;padding:8px 10px;font-size:14px;width:100%;min-height:38px}
/* Setup notes are kept exactly as they were typed — addressing and config
   only make sense with their line breaks and columns intact. */
.notebody{white-space:pre-wrap;font-family:"IBM Plex Mono",monospace;font-size:12.5px;line-height:1.5;
  background:var(--surface-2);border-left:3px solid var(--brand);border-radius:0 9px 9px 0;
  padding:11px 13px;margin:0;overflow-x:auto}

/* How the email sign-off will look, shown while it is being edited. */
.sigpreview{border-left:3px solid var(--brand);background:var(--surface-2);border-radius:0 10px 10px 0;
  padding:11px 14px;font-size:13px;line-height:1.55;color:var(--ink)}
.sigpreview .first{font-weight:600;color:var(--brand-2)}
.thumbs{display:flex;gap:8px;flex-wrap:wrap}
.thumbs img{width:150px;border-radius:10px;border:1px solid var(--line);display:block}
.thumbs a{text-decoration:none;display:block}
/* A PDF or document cannot be drawn, so it gets a named tile the same size. */
.filetile{width:150px;min-height:104px;border-radius:10px;border:1px solid var(--line);
  background:var(--surface-2);display:flex;flex-direction:column;justify-content:center;
  align-items:center;gap:4px;padding:12px 10px;text-align:center;text-decoration:none}
.filetile b{font-family:Poppins,sans-serif;font-size:15px;letter-spacing:.04em;color:var(--brand)}
.filetile span{font-size:11.5px;color:var(--ink);line-height:1.3;word-break:break-word;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.filetile em{font-size:11px;color:var(--dim);font-style:normal}
a.filetile:hover{border-color:var(--brand)}
.match{border:1px solid var(--ok);background:var(--ok-soft);border-radius:10px;padding:11px 13px;font-size:13.5px;margin-bottom:8px}
.nomatch{border:1px solid var(--line);background:var(--warn-soft);color:var(--warn);border-radius:10px;padding:11px 13px;font-size:13.5px}
.auth{max-width:420px;margin:40px auto;padding:0 16px}
.auth .card-pad{padding:22px}
.brandline{display:flex;align-items:center;gap:12px;margin-bottom:18px}
.brandline img{width:44px}
.tabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.tabs a{padding:7px 13px;border-radius:9px;border:1px solid var(--line);background:var(--surface);
  text-decoration:none;color:var(--dim);font-size:13.5px;font-weight:500}
.tabs a.on{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}

/* two-column split on wide screens */
.two{display:grid;grid-template-columns:1fr;gap:20px}
@media(min-width:820px){.two{grid-template-columns:1fr 1fr}}

/* job statuses reuse the ticket stripe/chip system */
.chip.pending{background:var(--warn-soft);color:var(--warn);border-color:transparent}
.chip.reviewed{background:var(--info-soft);color:var(--info);border-color:transparent}
.chip.approved{background:var(--ok-soft);color:var(--ok);border-color:transparent}
.chip.rejected{background:var(--bad-soft);color:var(--bad);border-color:transparent}
/* The three statuses this release added had no colour of their own, so they
   rendered as the plain grey default while every other status beside them was
   coloured — which reads as "nothing set" rather than as a status. */
.chip.new{background:var(--info-soft);color:var(--info);border-color:transparent}
.chip.active{background:var(--info-soft);color:var(--info);border-color:transparent}
.chip.info{background:var(--warn-soft);color:var(--warn);border-color:transparent}
.chip.warn{background:var(--warn-soft);color:var(--warn);border-color:transparent}
.rec.s-new .stripe{background:var(--info)}
.rec.s-active .stripe{background:var(--info)}
.rec.s-info .stripe{background:var(--warn)}
.rec.s-pending .stripe{background:var(--warn)}
.rec.s-reviewed .stripe{background:var(--info)}
.rec.s-approved .stripe{background:var(--ok)}
.rec.s-rejected .stripe{background:var(--bad)}

/* type picker */
.typegrid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media(min-width:700px){.typegrid{grid-template-columns:repeat(3,1fr)}}
.typebtn{display:flex;flex-direction:column;gap:3px;text-align:left;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r);padding:15px;box-shadow:var(--shadow);
  min-height:92px;justify-content:center;text-decoration:none;color:var(--text)}
.typebtn:hover{border-color:var(--brand)}
.typebtn strong{font-family:Poppins,sans-serif;font-size:15.5px;font-weight:600}
.typebtn span{font-size:12px;color:var(--dim);line-height:1.35}
.typegrid.pairs{grid-template-columns:1fr 1fr}
.typegroup{grid-column:1/-1;cursor:default}
.typegroup:hover{border-color:var(--line)}
.typechoices{display:grid;grid-template-columns:1fr;gap:8px;margin-top:8px}
@media(min-width:700px){.typechoices{grid-template-columns:repeat(3,1fr)}}
.typechoice{display:flex;flex-direction:column;gap:2px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;
  background:var(--bg,transparent);color:inherit;text-decoration:none}
.typechoice:hover{border-color:var(--brand)}
.typechoice strong{font-size:14px}

/* item lines */
.itemrow{display:grid;grid-template-columns:1fr 1fr 70px;gap:8px;align-items:end;padding:11px;
  background:var(--surface-2);border:1px solid var(--line);border-radius:10px;margin-bottom:8px}
.itemrow .full{grid-column:1/3}
.itemrow .field{margin-bottom:0}
.itemrow .x{width:100%;height:44px;border-radius:8px;border:1px solid var(--line);
  background:var(--surface);color:var(--bad);font-size:17px;cursor:pointer}
/* 36.41 — the description is ten lines now, and resizable: ten is what a
   FortiAP's six facts need, and "and more" was the other half of the ask. */
.itemrow textarea[name="item_descr"]{width:100%;min-width:0;font:inherit;line-height:1.45;
  padding:8px 10px;resize:vertical;min-height:11em}
/* Quantity and price share a line of their own beneath it. `flex-direction`
   is stated, not assumed: .field above is a flex COLUMN, so a row that only
   says `display:flex` inherits column and stacks the two boxes with a gap
   between them — which is what the first photograph of this showed. */
.itemrow .numsrow{display:flex;flex-direction:row;gap:10px;flex-wrap:wrap;align-items:flex-start}
.itemrow .numsrow>div{flex:0 0 150px;max-width:150px}
.itemrow .numsrow label{display:block;margin-bottom:4px}
.itemrow .numsrow input{width:100%}
@media(max-width:560px){.itemrow .numsrow>div{flex:1 1 120px;max-width:none}}

/* ---- quotation lines — 33.9 ----
   A line of a quotation is often a paragraph, so the description is a box that
   grows with what is typed into it, and a description already written prints
   on screen with the breaks it was written with. */
.linetext{width:100%;min-width:0;font:inherit;line-height:1.4;padding:6px 8px;resize:vertical}
/* The boxes on a line are told how wide to be, or a number box asks for the
   width of twenty digits and pushes the Amount column off the page. */
tbody[data-lines] td{vertical-align:middle}
tbody[data-lines] input[type="number"]{width:100%;min-width:56px;padding:6px 8px}
tbody[data-lines] input[name="item_code"]{width:100%;min-width:72px;padding:6px 8px}
.linewords{white-space:pre-wrap}
.lineno{white-space:nowrap;color:var(--faint);font-size:12px}
.lineno [data-no]{display:inline-block;min-width:14px}
.linebtns{display:inline-flex;gap:3px;margin-left:5px;vertical-align:middle}
.linebtn{width:22px;height:22px;padding:0;line-height:1;border-radius:6px;cursor:pointer;
  border:1px solid var(--line);background:var(--surface);color:var(--dim);font-size:14px}
.linebtn:hover{border-color:var(--brand);color:var(--brand-2)}
.linebtn.bad:hover{border-color:var(--bad);color:var(--bad)}
.addlines{margin-top:-2px}


/* site footer */
.sitefoot{border-top:1px solid var(--line);margin-top:40px;padding:20px 16px 34px;text-align:center}
.sitefoot .inner{font-size:13.5px;color:var(--dim)}
.sitefoot .inner.small{font-size:12px;color:var(--faint);margin-top:5px}
.sitefoot a{color:var(--brand-2);text-decoration:none;font-weight:500}
.sitefoot a:hover{text-decoration:underline}
.sitefoot .sep{color:var(--faint);margin:0 8px}
.brandline img{width:46px;height:46px;object-fit:contain;flex:none}

/* send-by-email panel */
.mailbox{margin-top:14px}
.mailbox summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:7px;
  background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:10px 18px;
  font-family:Poppins,Inter,sans-serif;font-size:14px;font-weight:600;min-height:44px;box-sizing:border-box}
.mailbox summary::-webkit-details-marker{display:none}
.mailbox summary:hover{border-color:var(--brand)}
.mailbox[open] summary{border-color:var(--brand);color:var(--brand)}
.mailbox .card-pad{margin-top:10px}

/* settings: reference lists */
.listrow{display:flex;gap:10px;align-items:flex-start;padding:11px;background:var(--surface-2);
  border:1px solid var(--line);border-radius:10px}
.listrow.off{opacity:.55}
.listrow .movers{display:flex;flex-direction:column;gap:4px;flex:none;padding-top:19px}
.listrow .movers .btn{min-height:26px;padding:1px 8px;line-height:1}
.listform{display:grid;grid-template-columns:1fr;gap:10px;flex:1;min-width:0}
@media(min-width:720px){.listform{grid-template-columns:1fr 1fr auto;align-items:end}}
.listacts{display:flex;gap:6px;flex-wrap:wrap}
.listadd{display:grid;grid-template-columns:1fr;gap:10px;align-items:end;
  border-top:1px dashed var(--line);padding-top:14px}
@media(min-width:720px){.listadd{grid-template-columns:1fr 1fr auto}}

/* full brand lockup in the header */
.brand{display:flex;align-items:center;flex:none;text-decoration:none}
.fulllogo{height:60px;width:auto;display:block}
@media(max-width:700px){.fulllogo{height:40px}}

/* help toggle beside the page title */
.helpbtn{margin-left:9px;vertical-align:middle;width:23px;height:23px;border-radius:999px;
  border:1px solid var(--line);background:var(--surface);color:var(--faint);
  font-family:Inter,sans-serif;font-size:12px;font-weight:700;line-height:1;cursor:pointer;padding:0}
.helpbtn:hover{border-color:var(--brand);color:var(--brand)}
.helpbtn.on{background:var(--brand);border-color:var(--brand);color:#fff}

/* danger zone */
.danger{border-color:var(--bad)}
.danger .eyebrow{color:var(--bad)}
.purgerow{display:grid;grid-template-columns:1fr;gap:10px;align-items:end;
  padding:12px;background:var(--surface-2);border:1px solid var(--line);border-radius:10px;margin-bottom:8px}
@media(min-width:720px){.purgerow{grid-template-columns:1fr auto auto}}
.purgerow .what{min-width:0}
.purgerow .what strong{display:block;font-family:Poppins,sans-serif;font-size:14.5px}
.purgerow .what span{font-size:12.5px;color:var(--dim)}
.purgerow .count{font-family:"IBM Plex Mono",monospace;font-size:13px;color:var(--dim);white-space:nowrap}

/* barcode scanning */
.scanbtn{margin-top:6px;align-self:flex-start}
.scanner{position:fixed;inset:0;z-index:60;background:rgba(10,14,20,.82);
  display:grid;place-items:center;padding:20px}
.scanbox{background:var(--surface);border-radius:var(--r);padding:14px;width:min(460px,100%);
  display:flex;flex-direction:column;gap:10px;position:relative}
.scanbox video{width:100%;border-radius:10px;background:#000;aspect-ratio:4/3;object-fit:cover}
.scanbox p{margin:0;font-size:13px;color:var(--dim);text-align:center}
.scanline{position:absolute;left:24px;right:24px;top:52%;height:2px;background:var(--brand);
  box-shadow:0 0 10px var(--brand);opacity:.9}

/* contact line in the footer — one line, wrapping only when it must */
.sitefoot .contact{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;
  gap:4px 8px;font-size:13.5px;margin-bottom:10px}
.sitefoot .contact .lead{color:var(--faint);font-weight:600}
.sitefoot .contact .co{font-family:Poppins,Inter,sans-serif;font-weight:700;color:var(--text)}
.sitefoot .contact .bar{color:var(--line)}
.sitefoot .contact .mail{font-weight:600}
.sitefoot .contact .tag{color:var(--faint)}

/* ---- the conversation on a record ----
 * The working comments on the left, the managers' private note on the right,
 * stacked on a phone. The note is tinted and outlined so nobody mistakes one
 * for the other at a glance.
 */
.talk{display:grid;grid-template-columns:1fr;gap:14px}
@media(min-width:860px){.talk:has(.notes){grid-template-columns:1fr 1fr}}
.talkcol{min-width:0}
.talkcol.notes{background:var(--warn-soft);border:1px dashed var(--warn);border-radius:12px;padding:12px 13px}
.bubble{background:var(--surface-2);border:1px solid var(--line);border-radius:11px;
  padding:10px 12px;margin-top:8px}
.bubble.note{background:var(--surface);border-color:var(--warn)}
.bubble .who{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;margin-bottom:4px}
.bubble .who strong{font-size:13px}
.bubble .who span{font-size:11.5px;color:var(--faint)}
.bubble .say{white-space:pre-wrap;font-size:13.5px;line-height:1.5}
.talk textarea{background:var(--surface);border:1px solid var(--line);border-radius:10px;
  padding:10px 11px;font-size:15px;width:100%;min-height:52px;resize:vertical}
.talkcol.notes textarea{border-color:var(--warn)}
.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@media print{ .talk{display:none} }
/* A task's conversation and its team, folded under the row it belongs to. */
.taskrow>td{background:var(--surface-2);padding:0 12px}
.taskdrop>summary{cursor:pointer;font-size:12.5px;color:var(--brand);font-weight:600;
  padding:8px 0;list-style:none}
.taskdrop>summary::-webkit-details-marker{display:none}
.taskdrop>summary::before{content:'▸ ';font-size:11px}
.taskdrop[open]>summary::before{content:'▾ '}

/* ---- AI-ICSONE ---- */
.aibtn{display:inline-flex;align-items:center;gap:6px;flex:none;text-decoration:none;
  background:linear-gradient(135deg,#1A67D2,#6AA4F0);color:#fff;border-radius:999px;
  padding:6px 13px;font-family:Poppins,sans-serif;font-weight:600;font-size:12px;
  box-shadow:0 2px 8px rgba(26,103,210,.28)}
.aibtn:hover{filter:brightness(1.08)}
.aibtn.on{box-shadow:0 0 0 2px var(--brand-soft),0 2px 8px rgba(26,103,210,.28)}
.aisum p{margin:0 0 8px;font-size:14.5px;line-height:1.55}
.aisum p:last-child{margin-bottom:0}
.aisum{border-left:3px solid var(--brand)}
/* The answer Claude wrote, set slightly larger than the portal's own reading
   below it, so the eye lands on the sentence first. */
.ailive p{font-size:15.5px;line-height:1.6}
.ailive{background:linear-gradient(180deg,rgba(94,124,255,.07),transparent 70%)}
.ailive .hint{border-top:1px solid var(--line);padding-top:10px}
@media(max-width:700px){ .aibtn .lbl{display:none} .aibtn{padding:7px 11px;font-size:14px} }
/* ICSONE professional workspace — shared desktop and mobile components. */
:root{--bg:#F5F7FA;--text:#1F2937;--dim:#526174;--faint:#5D6B7D;--brand:#2563EB;--brand-2:#1D4ED8;--r:12px;--shadow:0 2px 8px #17324d0a}
h1,h2,h3,.h2{font-family:Inter,'Segoe UI',sans-serif;color:#17324D;font-weight:650;letter-spacing:-.025em}
.h2{font-size:26px;line-height:1.25}.card{box-shadow:var(--shadow)}
input,textarea,select{max-width:100%;min-width:0}input[type=date]{width:100%;min-width:0}
.grid2>* ,.grid3>* ,.two>* ,.spread>*{min-width:0}
main{max-width:1050px}main.wide{max-width:1360px}.card-pad{padding:20px}.stack{gap:18px}
.identity{display:flex;flex-direction:column;align-items:center}.direct-signout button{background:none;border:0;color:var(--brand);cursor:pointer;font-size:12px;padding:3px 8px}.team-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px}.team-grid label{display:flex;align-items:center;gap:8px;text-transform:none;letter-spacing:0}.team-grid input{width:auto}
.report-letterhead{display:none}.rec .side{flex:0 0 auto;max-width:40%}.rec .body{min-width:0}
.topbar nav a{border-radius:8px}.topbar .sub{font-size:11px;letter-spacing:.03em}.fulllogo{max-width:180px}
/* The prescribed navy navigation was only ever applied to the staff sidebar on
   a wide screen. A student, or anyone on a phone, got a pale grey bar instead —
   so most people never saw the company's own colour. */
.topbar nav{background:#17324D}
.topbar nav a{color:#DDE7F4}
.topbar nav a.on{background:#FFFFFF1F;color:#fff}
.topbar nav a:hover{background:#FFFFFF12;color:#fff}
/* The company logo at the head of the navy column, in place of the word
   ICSONE that used to be typed out here in CSS.
   Hidden everywhere by default, and shown again only inside the wide-screen
   block below — because that is the only layout where the navigation is a
   column. On a phone the navigation is a horizontal bar and the same logo is
   already in the header directly above it. This rule has to live OUTSIDE the
   media query: inside it, a phone gets no rule at all and the logo renders at
   its natural size, which is how it first came out the width of the screen. */
.navbrand{display:none}
@media(min-width:1100px){
.staff-shell{padding-left:228px}.staff-shell .topbar{position:sticky;min-height:84px;padding:12px 28px}
.staff-shell .topbar nav{position:fixed;top:0;left:0;bottom:0;width:228px;background:#17324D;border:0;border-radius:0;padding:22px 16px 20px;display:flex;flex-direction:column;gap:8px;overflow:auto}
.staff-shell .topbar nav .navbrand{display:block;padding:2px 8px 16px;margin:0 0 6px;
  border-bottom:1px solid #FFFFFF26;background:none}
.staff-shell .topbar nav .navbrand:hover{background:none}
.staff-shell .topbar nav .navbrand img{display:block;width:100%;max-width:170px;height:auto}
/* With the logo in the column, the one in the header is the same mark twice. */
.staff-shell .topbar .brand{display:none}
.staff-shell .topbar nav a{color:#DDE7F4;padding:12px 16px;font-size:14px}.staff-shell .topbar nav a.on{background:#FFFFFF1F;color:white;box-shadow:none}.staff-shell .topbar nav a:hover{background:#FFFFFF12;color:white}
.staff-shell main{padding:30px;max-width:1440px;margin:auto}.staff-shell .sitefoot{padding:20px}
}
@media(max-width:700px){
.topbar{padding:10px 14px}.topbar .fulllogo{width:130px}.topbar nav{border-radius:10px;flex-wrap:wrap;overflow:visible;justify-content:flex-start}.topbar nav a{font-size:12px;flex:1 0 auto;text-align:center;padding:8px}.topbar .aibtn{font-size:11px;padding:8px}.h2{font-size:23px}.card-pad{padding:16px}main,main.wide{padding:18px 14px}.grid2,.grid3,.two{grid-template-columns:1fr!important}.kpis{grid-template-columns:repeat(2,minmax(0,1fr))}.rec{flex-wrap:wrap}.rec .side{max-width:none;width:100%;display:flex;justify-content:space-between;padding-left:12px}.tabs{flex-wrap:wrap;overflow:visible}.tabs a{white-space:normal}.spread{flex-wrap:wrap}input,select,textarea{font-size:16px}.tblwrap{max-width:100%;overflow-x:auto}.team-grid{grid-template-columns:1fr}.talk{display:block}.talkcol{margin-bottom:16px}
}
/* 36.3 — a second dark palette lived here, and its pale heading colour is
   what made “My reports” invisible on a white page. See the note at the top. */
@media print{.topbar,.sitefoot,.help-widget,.noprint,form,.tabs,.mailbox,.btn{display:none!important}.staff-shell{padding:0}main,main.wide,.staff-shell main{padding:0;max-width:none;margin:0}.report-letterhead{display:block;border-bottom:2px solid #17324D;padding-bottom:10px}.card{box-shadow:none;break-inside:avoid}body{background:white;color:#111}thead{display:table-header-group}tr{break-inside:avoid}@page{size:A4;margin:14mm}}
.help-widget{position:fixed;right:20px;bottom:20px;z-index:60}.help-toggle{border:0;border-radius:28px;background:#2563EB;color:#fff;padding:13px 20px;box-shadow:0 4px 20px #17324d30;cursor:pointer}.help-panel{position:absolute;bottom:58px;right:0;width:370px;max-width:calc(100vw - 28px);max-height:70dvh;overflow:auto;background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:18px;box-shadow:0 8px 32px #17324d30}.help-panel[hidden]{display:none}.help-panel h3{font-size:17px}.help-close{float:right;background:transparent;border:0;font-size:20px;cursor:pointer}.help-topics{display:flex;flex-wrap:wrap;gap:7px;margin:12px 0}.help-topics button{font-size:12px;border:1px solid var(--line);background:var(--surface-2);border-radius:8px;padding:8px;cursor:pointer}.help-log{max-height:190px;overflow:auto;font-size:14px}.help-question{font-weight:600;color:var(--brand)}.help-panel form{display:flex;gap:6px}.help-panel input{min-width:0;width:100%;border:1px solid var(--line);padding:8px;border-radius:8px}.help-links{display:flex;gap:14px;flex-wrap:wrap;font-size:13px;margin-top:12px}

.task-filters select{display:block;width:100%;padding:10px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text);margin-top:6px}.task-filters label{font-size:13px} .task-files{display:flex;gap:8px;flex-wrap:wrap}
@media print{.notes,.internal-note{display:none!important}}

/* A radio option that is a whole card rather than a dot with a word beside it.
   Used where the choice changes what the portal does — the two kinds of
   report, where picking the wrong one produces a document with the wrong
   standing — so each option carries its own explanation. */
.pick{display:flex;gap:11px;align-items:flex-start;padding:11px 13px;margin-bottom:8px;
  border:1px solid var(--line);border-radius:10px;background:var(--surface-2);cursor:pointer}
.pick:hover{border-color:var(--brand)}
.pick input{margin-top:3px;flex:0 0 auto;width:17px;height:17px;accent-color:var(--brand)}
.pick>span{display:flex;flex-direction:column;gap:3px;min-width:0}
.pick strong{font-size:14px}
.pick .hint{font-size:12.5px;line-height:1.45}
.pick:has(input:checked){border-color:var(--brand);box-shadow:0 0 0 2px rgba(37,99,235,.18)}

/* The home page figures are links now — each opens the records it was counted
   from. They must still read as tiles, not as blue underlined text, so the
   link styling is undone and a press state put in its place. */
a.kpi{text-decoration:none;color:inherit;transition:border-color .12s, transform .08s}
a.kpi:hover{border-color:var(--brand)}
a.kpi:active{transform:scale(.985)}
a.kpi.lead:hover{border-color:rgba(255,255,255,.55)}
a.kpi:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* The field summary: six kinds of work, seven states, one number each.
   Numbers are the point, so they are tabular and right-aligned; a zero is
   shown as a dash so the eye goes straight to the cells that hold something.
   The colours are the portal's existing status tones, so a state means the
   same colour here as it does on the record itself. */
table.summary td.num, table.summary th.num{text-align:right;white-space:nowrap}
table.summary td{padding:7px 9px}
table.summary .zero{color:var(--faint)}
table.summary .cell{display:inline-block;min-width:30px;padding:2px 8px;border-radius:999px;
  font-variant-numeric:tabular-nums;font-weight:700;text-decoration:none;
  border:1px solid transparent}
table.summary .cell:hover{border-color:var(--brand)}
table.summary .cell.s-new{background:var(--surface-2);color:var(--text)}
table.summary .cell.s-active{background:rgba(37,99,235,.14);color:#1A67D2}
table.summary .cell.s-pending{background:rgba(201,162,39,.16);color:#8A6D12}
table.summary .cell.s-info{background:rgba(201,162,39,.16);color:#8A6D12}
table.summary .cell.s-awaiting{background:rgba(234,88,12,.15);color:#B4520E}
table.summary .cell.s-approved{background:rgba(22,140,90,.15);color:#127049}
table.summary .cell.s-rejected{background:rgba(190,45,45,.14);color:#A32626}
/* 36.3 — and the summary cells had their own dark palette, which lightened
   their text onto the light tinted backgrounds right above. See the top. */

/* The export toolbar: Print, Excel, PDF, Email. Small and to one side, because
   it is used now and then, and a list is read every day. The email form folds
   out of its own button rather than sitting open on every page. */
.exportbar{display:flex;flex-wrap:wrap;gap:6px;align-items:flex-start;justify-content:flex-end}
.exportbar .btn{font-size:12px;padding:6px 10px}
.exportbar details{position:relative}
.exportbar summary{list-style:none;cursor:pointer}
.exportbar summary::-webkit-details-marker{display:none}
.exportbar details[open] summary{border-color:var(--brand);color:var(--brand)}
.exportbar details form{position:absolute;right:0;top:calc(100% + 6px);z-index:30;
  background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:10px;
  box-shadow:var(--shadow);gap:6px;flex-wrap:wrap;width:min(420px,92vw)}
.exportbar details form input{flex:1 1 100%}
@media(max-width:620px){
  /* On a phone the Email button sits well to the right, and a form hung from
     it ran off the screen. Hung from the bar instead, it spans the width. */
  .exportbar{justify-content:flex-start;position:relative}
  .exportbar details{position:static}
  .exportbar details form{left:0;right:0;width:auto}
}
@media print{.exportbar{display:none}}
/*
 * 36.10 — the same email form, drawn open.
 *
 * On a list the form hangs out of its own button and is absolutely positioned
 * under it. In the report's Delivery panel it is rendered open instead, so it
 * needs the panel treatment rather than the pop-out one: the whole width of
 * the bar, under the three buttons, with its own border.
 */
.exportbar .exportmail.open{flex:1 1 100%;margin-top:6px}
.exportbar .exportmail.open form{display:flex;flex-wrap:wrap;gap:8px;background:var(--surface);
  border:1px solid var(--line);border-radius:12px;padding:12px}
.exportbar .exportmail.open form input,
.exportbar .exportmail.open form select{flex:1 1 100%}
.exportbar .exportmail.open form button{flex:1 1 100%;justify-content:center}
/* In the Delivery panel the bar reads top-to-bottom from the left, like
   everything else in that column, rather than hanging off its right edge. */
.rside .exportbar,.rp-del .exportbar{justify-content:flex-start}
/* 36.10 — the state of the report, at the head of the Delivery panel. */
.delstate .st{flex:0 0 auto}
.delstate strong{font-size:14px;line-height:1.4;color:var(--text)}
/* 28.6 — Field Desk record: one status line, one decision box, one action bar */
.jobstage{display:inline-flex;align-self:flex-start;align-items:center;gap:8px;padding:6px 12px;border-radius:999px;
  font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;background:var(--surface-2);color:var(--brand-2)}
.jobstage::before{content:"";width:8px;height:8px;border-radius:50%;background:currentColor}
.jobstage.ok{background:var(--ok-soft);color:var(--ok)}
.jobstage.bad{background:var(--bad-soft);color:var(--bad)}
.jobstage.warn{background:var(--warn-soft);color:var(--warn)}
.decidebox textarea{width:100%}
.decidebtns{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.decidebtns .btn{flex:1 1 140px}
.btn.warn{background:var(--warn-soft);border-color:transparent;color:var(--warn);font-weight:600}
.actionbar{display:flex;flex-wrap:wrap;gap:8px}
.actionbar .btn{flex:1 1 auto;white-space:nowrap}
details.nosum>summary{display:none}
details.nosum:not([open]){display:none}

/* 28.9 — support request intake on one screen; stage bar on a ticket */
.intake-find{padding-top:14px;padding-bottom:14px}
.intake-find input{width:100%}
.intake-form{display:flex;flex-direction:column;gap:6px}
.intake-form .eyebrow{margin-top:6px}
.igrid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px 12px}
.igrid .field{margin:0}
.igrid .span2{grid-column:span 2}
.igrid .span4{grid-column:1/-1}
.igrid textarea{min-height:58px}
@media(max-width:800px){.igrid{grid-template-columns:1fr 1fr}.igrid .span2,.igrid .span4{grid-column:1/-1}}
.stagebar{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.stagebar .field input,.stagebar .field select{width:100%}

/* 29.0 — repair ticket: work on the left, conversation and activity on the right */
.split.ticketview{grid-template-columns:minmax(0,1fr) 420px}
.tkside .talk{grid-template-columns:1fr!important}
.tkside .tblwrap td{font-size:12.5px;vertical-align:top}
.tkside .tblwrap td.mono{white-space:normal!important}
@media(max-width:1080px){.split.ticketview{grid-template-columns:1fr}}

/* 28.11 — office request: example for the chosen category */
.catexample{background:var(--surface-2);border:1px solid var(--line);border-left:3px solid var(--ok);border-radius:10px;padding:10px 14px;font-size:14px}
.catexample[hidden]{display:none}
details.examples summary{cursor:pointer;font-weight:600}

/* ------------------------------------------------------------------ *
 * 28.19 — the Field Desk board
 *
 * Five columns of equal width, side by side, each headed by its status and
 * the number of records in it. A card sits in the column its status names, so
 * approving or refusing a record moves its card. On a narrow screen the
 * columns stay side by side and the board scrolls sideways, because folding
 * them into one another would lose exactly the comparison the board is for.
 * ------------------------------------------------------------------ */
/*
 * 35.2 — how many columns a board has is written on the board.
 *
 * This said `repeat(3, …)`, because the first board in the portal had three.
 * The support desk has four — New, In progress, Need information, Closed —
 * and the fourth was dropping onto a line of its own underneath, which is
 * exactly the comparison a board exists to give you. 28.32 had already
 * decided the right answer and put it in the board partial; the desk board
 * and the field board were written by hand and never picked it up.
 *
 * So there is one way to say it now, and all three boards say it: `--cols` on
 * the element. Three stays the default, so a board that forgets still draws.
 */
.board{--cols:3;display:grid;grid-template-columns:repeat(var(--cols),minmax(0,1fr));gap:12px;align-items:start}
.board .bcard.s-waiting,.board .bcard.s-need_info{border-left-color:var(--warn)}
.board .bcard.s-resolved,.board .bcard.s-closed{border-left-color:var(--ok)}
.board .bcard.s-cancelled{border-left-color:var(--bad)}
.board .bcard.s-in_progress,.board .bcard.s-pending{border-left-color:var(--accent-solid)}
.board .bcol{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r);
  padding:12px;min-height:120px;display:flex;flex-direction:column;gap:10px}
.board .bhead{display:grid;grid-template-columns:1fr auto;gap:2px 8px;align-items:center}
.board .bhead h3{margin:0;font-size:14px;letter-spacing:.06em;text-transform:uppercase;color:var(--text)}
.board .bhead .n{justify-self:end;background:var(--surface);border:1px solid var(--line);border-radius:999px;
  min-width:26px;padding:1px 8px;text-align:center;font-weight:650;font-size:13px;color:var(--dim)}
.board .bhead p{grid-column:1/-1;margin:0;font-size:12px;line-height:1.45;color:var(--faint)}
.board .bcards{display:flex;flex-direction:column;gap:8px}
.board .bempty{margin:0;font-size:12px;color:var(--faint)}
.board .bcard{display:flex;flex-direction:column;gap:3px;background:var(--surface);border:1px solid var(--line);
  border-left:4px solid var(--line);border-radius:10px;padding:10px 11px;text-decoration:none;color:var(--text)}
.board .bcard:hover{border-color:var(--brand);box-shadow:var(--shadow)}
.board .bcard .ref{font-size:11px;color:var(--faint)}
/* Long subjects and notes are cut to a couple of lines so a card never grows
   past its column, whatever somebody typed in. */
.board .bcard .title{font-weight:640;font-size:14px;line-height:1.35;overflow-wrap:anywhere;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.board .bcard .meta{font-size:12px;color:var(--dim);line-height:1.4;overflow-wrap:anywhere;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.board .bcard .foot{display:flex;justify-content:space-between;gap:8px;align-items:baseline;font-size:11px;color:var(--faint);margin-top:2px}
.board .bcard .amt{color:var(--text);font-size:12px}
.board .bcard.s-new,.board .bcard.s-pending{border-left-color:var(--info)}
.board .bcard.s-active,.board .bcard.s-reviewed{border-left-color:var(--accent-solid)}
.board .bcard.s-info{border-left-color:var(--warn)}
.board .bcard.s-approved{border-left-color:var(--ok)}
.board .bcard.s-rejected{border-left-color:var(--bad)}
.board .b-approved{background:var(--ok-soft)}
.board .b-rejected{background:var(--bad-soft)}
.board .b-info{background:var(--warn-soft)}
/*
 * 35.2 — and where the columns stop fitting, they keep their width and the
 * board scrolls sideways rather than folding one into another.
 *
 * The threshold moved from 820 to 1200 when the desk gained its fourth
 * column. 1200 is where a four-column board's columns fall below about 200
 * points wide — narrow enough that a card stops being readable at a glance,
 * which is the only thing a board is for. Below it they hold 230 and the
 * board scrolls instead.
 *
 * A board of three is unaffected either way: at these widths
 * `minmax(230px, 1fr)` still fills the row, so it draws exactly as it did
 * and nothing scrolls.
 */
@media(max-width:1200px){
  .board{grid-auto-flow:column;grid-auto-columns:minmax(230px,1fr);grid-template-columns:none!important;
    overflow-x:auto;padding-bottom:6px;scroll-snap-type:x proximity}
  .board .bcol{scroll-snap-align:start}
}

/* 28.29 — the support desk's status chips: small, with their own icons. */
.deskchips .btn.sm .ic{width:14px;height:14px}
.deskchips .btn.sm .n{background:rgba(15,17,21,.06);border-radius:999px;padding:0 6px;font-size:11px;line-height:17px}
.deskchips .btn.sm.primary .n{background:rgba(255,255,255,.22)}

/* 32.3 — the signature pads on a quotation: a plain white box you draw in,
   the same size on a phone as on a laptop so a signature does not come out
   the size of a postage stamp. */
.sigpad{
  width:100%;height:92px;display:block;
  border:1px solid var(--line);border-radius:8px;background:#fff;
  touch-action:none;cursor:crosshair;
}

/* 32.8 — the camera and the microphone under a description box. */
.describe{margin-top:6px}
.describe .btn.sm.on{background:#B4232A;border-color:#B4232A;color:#fff}
.describe .hint{margin:0}
/* The attribute has to win: a display rule would otherwise show an empty
   frame before any photo has been taken. */
.describe-shot{display:flex;align-items:center;gap:10px;margin-top:8px}
.describe-shot[hidden]{display:none}
.describe-shot img{width:72px;height:72px;object-fit:cover;border-radius:8px;border:1px solid var(--line)}
.describe-shot .hint{margin:0}

/* 33.0 — the support assistant's near misses, offered as buttons. */
.help-also{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:2px 0 8px}
.help-also span{font-size:11.5px;color:#5C6C7B}
.help-also button{font:inherit;font-size:12px;padding:4px 9px;border:1px solid var(--line);
  background:#fff;color:#0B2A55;border-radius:999px;cursor:pointer}
.help-also button:hover{border-color:var(--brand);color:var(--brand)}
/* 36.48 — a link in the panel: the pages a web search read, and the way
   through to everything Alex found. Same chip as the buttons beside it, so
   the row reads as one row. */
.help-also a{font-size:12px;padding:4px 9px;border:1px solid var(--line);background:#fff;
  color:#0B2A55;border-radius:999px;text-decoration:none;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.help-also a:hover{border-color:var(--brand);color:var(--brand)}
/* Alex takes a second or two. Something has to be on the screen in the
   meantime, or the panel looks like it did not hear the question. */
.help-wait{color:var(--muted,#5c6b7a);font-size:18px;letter-spacing:3px;margin:2px 0}
/* The fifteen written answers, folded away while Alex has the typing box.
   Still in the page, still answering with no network — one tap down. */
.help-common{margin:10px 0 6px}
.help-common>summary{cursor:pointer;font-size:12.5px;color:var(--muted,#5c6b7a);list-style:none}
.help-common>summary::-webkit-details-marker{display:none}
.help-common>summary::before{content:'▸ '}
.help-common[open]>summary::before{content:'▾ '}
.help-common>summary:hover{color:var(--brand,#1A67D2)}
/* Alex's answers are sentences, not a one-line FAQ hit. The log gets the
   room the folded buttons gave back. */
.help-widget[data-alex] .help-log{max-height:320px}

/* ---- the figures across the top of My tasks — 34.3 ---- */
.figstrip{margin:4px 0 2px}
.figstrip .kpi{text-decoration:none;color:inherit;transition:border-color .12s ease}
.figstrip .kpi:hover{border-color:var(--brand)}
.figstrip .kpi.bad .val{color:var(--bad)}
/* ---- the library — 35.0 ----
   A whole card is the link, so the title, the description and the folder are
   all one target: on a phone a guide is opened with a thumb, not a tap on
   four words of blue text. */
.libcard{color:inherit;transition:border-color .12s ease,transform .12s ease}
.libcard:hover{border-color:var(--brand)}
.libcard strong{color:var(--brand-2)}
/* ---- adding a client from inside a form — 35.3 ----
   Quieter than a guide card, because it sits under a picker that is the right
   answer most of the time: it should be there when the list fails you and
   invisible when it does not. */
.newclient{border-color:var(--line);background:var(--surface-2);margin:6px 0 0}
.newclient summary{padding:10px 12px;font-size:13px;font-weight:600;color:var(--brand-2)}
.newclient summary:hover{color:var(--brand)}
.newclient > .stack{padding:0 12px 12px}
.newclient[open]{background:var(--surface);box-shadow:var(--shadow)}
/* ---- the statistics ---- */
.statgrid{display:grid;gap:12px;grid-template-columns:1fr}
/* Two tables of five columns each need real room before they sit side by
   side; below that they read better one under the other, full width. */
@media(min-width:1500px){.statgrid{grid-template-columns:1fr 1fr}}
.bar{display:block;height:6px;border-radius:999px;background:var(--surface-2);overflow:hidden;margin-top:4px}
.bar i{display:block;height:100%;background:var(--brand);border-radius:999px}
.bar.warn i{background:var(--warn)}
.bar.bad i{background:var(--bad)}

/*
 * 36.7 — every action on a report, on one row.
 *
 * Tony: "make all the icon on one align one line". The export bar used to
 * float to the right of its own card and the two red actions sat under it as
 * links of their own, so the foot of a report was three sizes at three
 * heights. One flex row holds all of them now.
 *
 * The two that open a panel are still <details>, which is what lets them work
 * with no script at all. Closed, a summary is a button beside the others;
 * open, the row gives it the whole width and its panel falls underneath,
 * instead of being squeezed into one button's worth of it.
 */
.reportbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;row-gap:10px}
.reportbar .exportbar{justify-content:flex-start;gap:8px;margin:0;flex:0 0 auto}
.reportbar > details{margin:0;flex:0 0 auto;border:0;background:none;padding:0}
.reportbar > details > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;
  gap:6px;font-size:12px;font-weight:600;padding:6px 10px;border:1px solid var(--line);
  border-radius:10px;background:var(--surface);white-space:nowrap}
.reportbar > details > summary::-webkit-details-marker{display:none}
.reportbar > details[open]{flex:1 0 100%}
.reportbar > details[open] > summary{border-color:var(--bad);margin-bottom:10px}
/* 36.8 — the sentence that stands where an Email button cannot be yet. */
.exportwhy{display:inline-flex;align-items:center;gap:6px;font-size:12px;padding:6px 10px;
  border:1px dashed var(--line);border-radius:10px;background:var(--surface-2);color:var(--dim)}
@media(max-width:620px){
  /* On a phone the row becomes a column of full-width buttons rather than a
     line of chips too small to hit. */
  .reportbar{flex-direction:column;align-items:stretch}
  .reportbar .exportbar{flex-wrap:wrap}
  .reportbar > details > summary{justify-content:center}
}

/*
 * 36.9 — the report page, in three sections.
 *
 * Tony: "i need redesign the page to look more clear understand / pratical of
 * doing the report". The page had grown a card at a time over twenty
 * releases, in the order the releases happened rather than the order the work
 * happens, so everything was there and nothing was anywhere in particular.
 *
 * Three headed sections now, in work order: the report, the evidence behind
 * it, delivering it. The heading is a band rather than a line, because the
 * thing it has to do is be findable while scrolling past at speed.
 */
.sechead{display:flex;align-items:center;gap:12px;margin:26px 0 2px;padding:0 2px}
.sechead h3{font-size:18px;color:var(--text);margin:0;letter-spacing:-.01em}
.sechead .hint{margin:1px 0 0}
.sechead .secnum{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:var(--brand);
  color:#fff;font-size:13px;font-weight:700;display:inline-flex;align-items:center;justify-content:center}
.sechead + *{margin-top:0}
@media print{.sechead{display:none}}

/* 36.9 — one short line, and the rest of it behind a question mark. */
.why{display:inline-block;margin-left:6px}
.why > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
  width:18px;height:18px;border-radius:50%;border:1px solid var(--line);background:var(--surface-2);
  color:var(--dim);font-size:11px;font-weight:700;vertical-align:text-bottom}
.why > summary::-webkit-details-marker{display:none}
.why[open] > summary{border-color:var(--brand);color:var(--brand)}
.why .whybody{display:block;margin:6px 0 0;padding:8px 10px;border-left:2px solid var(--line);
  color:var(--dim);font-size:13px;line-height:1.5}

/*
 * 36.10 — the report page as Tony drew it.
 *
 * Two columns on a desktop: the report and its evidence on the left, the
 * whole of sending it in a panel on the right that stays beside you while
 * you read. On a narrow screen the same three parts become three tabs,
 * because two columns on a phone is one column of crushed ones.
 *
 * The tabs are radio buttons and labels, so they work with no script at all.
 * The radios sit outside every form on the page and are never submitted.
 */
.rtab{position:absolute;opacity:0;pointer-events:none;width:0;height:0}
.rtabs{display:none;gap:6px;margin:14px 0 2px}
.rtabs label{flex:1 1 0;text-align:center;cursor:pointer;font-size:14px;font-weight:600;
  padding:10px 8px;border:1px solid var(--line);border-radius:10px;background:var(--surface);color:var(--dim)}
.rgrid{display:grid;grid-template-columns:minmax(0,1fr) 384px;gap:18px;align-items:start;margin-top:14px}
.rmain{display:flex;flex-direction:column;gap:14px;min-width:0}
.rside{min-width:0;position:sticky;top:74px}
.rside .sechead{margin-top:0}
.rp{display:flex;flex-direction:column;gap:12px;min-width:0}
@media(max-width:1000px){
  .rgrid{display:block}
  .rmain{display:block}
  .rtabs{display:flex}
  .rside{position:static}
  .rp{display:none}
  #rt1:checked ~ .rgrid .rp-report,
  #rt2:checked ~ .rgrid .rp-evi,
  #rt3:checked ~ .rgrid .rp-del{display:flex}
  #rt1:checked ~ .rtabs label[for=rt1],
  #rt2:checked ~ .rtabs label[for=rt2],
  #rt3:checked ~ .rtabs label[for=rt3]{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
}
@media print{
  .rtabs{display:none}
  .rgrid{display:block}
  .rp{display:block}
  .rside{position:static}
}

/*
 * 36.12 — the bar that offers to install the portal.
 *
 * It sits at the foot, above the home indicator on an iPhone, and it is the
 * only thing on the portal that is allowed to float over the page. It is
 * dismissed once and never comes back, so it does not have to earn its place
 * every day — but while it is there it must not cover a button, hence the
 * bottom inset and the room left under it.
 */
.installbar{position:fixed;left:12px;right:12px;z-index:61;
  bottom:calc(12px + env(safe-area-inset-bottom,0px));
  display:flex;align-items:center;gap:12px;padding:12px 14px;
  background:var(--brand-2);color:#fff;border-radius:16px;box-shadow:0 10px 30px rgba(8,22,45,.28)}
.installbar img{flex:0 0 auto;border-radius:9px}
.installbar .t{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.installbar strong{font-size:14px;font-weight:700;line-height:1.2}
.installbar span{font-size:12.5px;line-height:1.35;color:#D8E6FA}
.installbar .btn{flex:0 0 auto;background:#fff;border-color:#fff;color:var(--brand-2);font-weight:700}
.installbar .x{flex:0 0 auto;background:none;border:0;color:#B9CFEC;font-size:22px;line-height:1;
  padding:2px 4px;cursor:pointer}
.installbar .x:hover{color:#fff}
/* 36.12.2 — enough room at the foot for BOTH: the bar, and the assistant
   now standing above it. 104px cleared the bar alone. */
body.has-installbar{padding-bottom:168px}
@media(min-width:760px){
  .installbar{left:auto;right:18px;max-width:420px}
  body.has-installbar{padding-bottom:0}
}
@media print{.installbar{display:none}}

/*
 * 36.12.2 — the two things that float at the foot, not on top of each other.
 *
 * The support assistant has floated at bottom-right since 33.0. 36.12.0 put
 * the install bar at the foot as well, at the same z-index and later in the
 * page — so the bar won, and a tap at the centre of the support button
 * landed on the bar instead. Measured on a 393px phone: the button was
 * 180x40 at y=793, the bar 369x77 at y=763, and elementsFromPoint at the
 * button's own centre returned the bar's text. The assistant could not be
 * pressed at all, and the button covered the bar's dismiss cross in return.
 *
 * Neither needed a z-index war. They needed not to be in the same place: the
 * assistant steps up above the bar while the bar is there, and comes back
 * down the moment it is dismissed. The class is already on <body> for the
 * page padding, so there is nothing new to keep in step.
 *
 * And both now leave the iPhone's home indicator alone, which neither did.
 */
.help-widget{bottom:calc(20px + env(safe-area-inset-bottom,0px));
  right:calc(20px + env(safe-area-inset-right,0px))}
body.has-installbar .help-widget{bottom:calc(112px + env(safe-area-inset-bottom,0px))}


/* ===========================================================
 * 36.13 — a finger, not a mouse pointer.
 *
 * The portal is read standing in a server room, one-handed, on a phone.
 * A walk of 37 pages at 393px found 67 of them carrying controls under
 * 36px high: every small button at 34, every tab at 34, the ‹ › on the
 * reports at 28, the "?" folds at 23, and the boxes you tick at 13.
 *
 * Apple and Google both ask for 44px. The full-size .btn has always been
 * 44; it is everything SMALL that was never checked against a thumb. So
 * below 760px the small sizes stop being small. Nothing changes on a
 * desktop, where the pointer is a pixel wide and the compactness is the
 * point.
 * =========================================================== */
@media(max-width:760px){
  .btn.sm{min-height:44px;min-width:44px;padding:10px 14px;font-size:13.5px}
  .tabs a{padding:12px 15px;font-size:14px}
  .chip{font-size:11px;padding:5px 9px}
  /* The fold-out question mark from 36.9. Mine, and the smallest thing
     on the page. */
  .helpbtn{width:34px;height:34px;font-size:15px;margin-left:8px}
  /* What you tick. The browser default is 13px square, which is a third
     of a fingertip, and the label beside it was not part of the target
     either — it is now, with room around it. */
  input[type=checkbox],input[type=radio]{width:22px;height:22px}
  /*
   * Anything you tick, wherever it is. Naming the three classes that
   * happened to wrap a checkbox was how the working-days row on the
   * notifications page kept its 28px target: it wraps its box in a plain
   * .row and belongs to none of them. :has() asks the question that was
   * actually meant — is this label the thing somebody presses to tick a
   * box — and the named three stay as the answer for a browser without it.
   */
  .srcpick label,.talkpick label,.team-grid label.check,
  label.check,label.chk,
  label:has(> input[type=checkbox]),label:has(> input[type=radio]){
    min-height:44px;align-items:center;padding:7px 0;gap:11px;font-size:14.5px}
  .srcpick input,.talkpick input{margin:0}
  /* The export row and the pagination arrows live inside these. */
  .exportbar .btn{font-size:13px;padding:10px 13px;min-height:44px}
  /* The ‹ › that step a week or a month on the Workspace and the reports. */
  .periodbar .pstep{min-width:44px;min-height:44px}
  /* "all" and "none" over a column of permission ticks: 12x18 and 27x18,
     the two smallest things in the whole portal. */
  .linky{min-height:40px;min-width:40px;padding:8px 12px;display:inline-flex;
    align-items:center;justify-content:center}
  /*
   * A <summary> is a button: it opens and closes the panel under it.
   * "Correct this record" was 23px tall and the fold-outs on the settings
   * pages were 18.
   */
  summary{min-height:44px;display:flex;align-items:center;gap:8px}
  summary.btn,summary.btn.sm{display:inline-flex}
  /* Day / Week / Month / Quarter / Year on the Workspace: 23px. */
  .pkinds .pkind{padding:11px 4px;font-size:13.5px}
  /*
   * The notification matrix is a table of bare ticks — one per person per
   * kind of notice — with the label in the row heading rather than around
   * the box. There is nothing to make bigger except the box itself.
   */
  td input[type=checkbox],td input[type=radio]{width:24px;height:24px}
  /*
   * And the notification grid, which is not a table at all — one tick per
   * person per kind of notice, labelled by the row it is in. There is
   * nothing to enlarge but the box.
   */
  .notifygrid input[type=checkbox],.ngrid input[type=checkbox],
  .row > input[type=checkbox]{width:24px;height:24px}

  /*
   * 36.13 — and the row titles on the Workspace say which client.
   *
   * "Delivery — MLF Lycée Verdun" was arriving as "Delivery — MLF Lycée
   * Ver…", cut by up to 55px. The row has three lines and room for a
   * fourth; one line of them was a choice made for a desktop, where the
   * name fits. On a phone the title wraps to two lines instead of hiding
   * the half that says whose job it is.
   */
  .rec .title{white-space:normal;overflow:visible;text-overflow:clip;line-height:1.3}
}
/* 36.13 — and the fold-out question mark clears 36px, which is the floor
   the audit measures against. */
@media(max-width:760px){.helpbtn{width:36px;height:36px}}

/*
 * 36.13 — and a box you type into is the same height wherever it is.
 *
 * The audit found selects 21px tall on the Office request and the Team
 * queue — the browser's own default, because those two were written
 * without the class that gives every other control its height. A portal
 * where the same control is 44px on one page and 21px on the next does
 * not read as one product, and 21px is not a thumb target either.
 *
 * So the baseline is stated once, for every control that is not a tick
 * box, and the two deliberately compact widgets in the top bar say so
 * for themselves underneath.
 */
input:not([type=checkbox]):not([type=radio]):not([type=hidden]):not([type=file]),
select,textarea{min-height:40px}
@media(max-width:760px){
  input:not([type=checkbox]):not([type=radio]):not([type=hidden]):not([type=file]),
  select,textarea{min-height:44px}
}
.apptop select,.apptop input,.entitypick select,.toplang select{min-height:0}

/* ------------------------------------------------------------------ *
 * 36.35 — Connect Live
 *
 * Tony's panel, rebuilt on the portal's own tokens so it belongs here
 * rather than sitting inside the page in its own colour scheme. Each
 * card's accent is the vendor's colour, set inline from the server.
 * ------------------------------------------------------------------ */
.icsc-status{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;border-radius:999px;
  background:var(--card,#fff);border:1px solid var(--line,#e2e7ee);font-size:14px;font-weight:600}
.icsc-dot{width:10px;height:10px;border-radius:50%;background:#B8443C;flex:none}
.icsc-dot.on{background:#2E9E5B;animation:icscPulse 1.8s infinite}
@keyframes icscPulse{0%{box-shadow:0 0 0 0 rgba(46,158,91,.55)}70%{box-shadow:0 0 0 9px rgba(46,158,91,0)}100%{box-shadow:0 0 0 0 rgba(46,158,91,0)}}
@media(prefers-reduced-motion:reduce){.icsc-dot.on{animation:none}}

.icsc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px}
.icsc-card{background:var(--card,#fff);border:1px solid var(--line,#e2e7ee);border-radius:16px;padding:20px;
  display:flex;flex-direction:column;gap:12px;position:relative;overflow:hidden;
  transition:transform .15s,box-shadow .15s}
.icsc-card:hover{transform:translateY(-3px);box-shadow:0 10px 28px rgba(31,59,87,.14)}
.icsc-card::before{content:"";position:absolute;inset:0 0 auto 0;height:4px;background:var(--accent,#C8A651)}
.icsc-card.off{opacity:.55}
.icsc-card.off:hover{transform:none;box-shadow:none}
.icsc-ico{width:46px;height:46px;border-radius:12px;display:grid;place-items:center}
.icsc-ico .ic{width:24px;height:24px;color:#fff;fill:currentColor}
.icsc-card h3{margin:0;font-size:18px}
.icsc-card>p{margin:0;color:var(--muted,#5c6b7a);font-size:14px;line-height:1.45;flex:1}
.icsc-tag{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted,#5c6b7a)}
.icsc-btn{width:100%;justify-content:center}
.icsc-btn.primary{background:var(--accent,#1F3B57);border-color:var(--accent,#1F3B57)}
.icsc-links{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:13px}
.icsc-notyet{font-size:13px;color:var(--muted,#5c6b7a);border:1px dashed var(--line,#e2e7ee);
  border-radius:10px;padding:10px 12px}
.icsc-help summary{cursor:pointer;font-size:13px;color:var(--muted,#5c6b7a)}
.icsc-help ol{margin:8px 0 0;padding-left:20px;font-size:13px;line-height:1.55}
.icsc-idrow{display:flex;gap:8px;margin:0}
.icsc-idrow input{flex:1;min-width:0}
.icsc-foot{display:flex;flex-wrap:wrap;gap:8px 20px;justify-content:space-between;
  color:var(--muted,#5c6b7a);font-size:13px}
@media(max-width:520px){.icsc-idrow{flex-direction:column}}

/* 36.40 — choosing the person on the Teams and AnyDesk cards. The two
   buttons share the row equally: neither chatting nor calling is the
   lesser thing to want, so neither is the smaller button. */
.icsc-pick{display:flex;flex-direction:column;gap:8px;margin:0}
.icsc-pick select{width:100%}
.icsc-pickrow{display:flex;gap:8px}
.icsc-pickrow .btn{flex:1;width:auto}
/* Inside a chooser the number box gets its own line. Sharing a row with
   the button left it squeezed to "e.g. 123 45" in a four-card grid, which
   is a box that no longer says what goes in it. */
.icsc-pick .icsc-idrow{flex-direction:column}
.icsc-pick .icsc-idrow .btn{width:100%;justify-content:center}

/* 36.36 — the live chat */
.chatbox{display:flex;flex-direction:column}
.chatlog{display:flex;flex-direction:column;gap:8px;padding:16px;max-height:52vh;overflow:auto}
.chatline{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;max-width:80%}
.chatline.client{align-self:flex-start}
.chatline.agent{align-self:flex-end;flex-direction:row-reverse}
.chatline.system{align-self:center;max-width:100%}
.chatwho{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--muted,#5c6b7a)}
.chatbody{background:var(--bg,#f5f7fa);border:1px solid var(--line,#e2e7ee);border-radius:12px;
  padding:8px 12px;white-space:pre-wrap;word-break:break-word;font-size:14px;line-height:1.45}
.chatline.agent .chatbody{background:#1E8E5A14;border-color:#1E8E5A33}
.chatat{font-size:11px;color:var(--muted,#5c6b7a)}
.chatsys{font-size:12px;color:var(--muted,#5c6b7a);font-style:italic;text-align:center}
.chatsend{display:flex;gap:8px;align-items:flex-end;padding:12px 16px;border-top:1px solid var(--line,#e2e7ee)}
.chatsend textarea{flex:1;min-width:0}
@media(max-width:520px){.chatline{max-width:95%}}

/* 36.43 — the papers filed against a licence, on the row itself. Small and
   out of the way: they are there to be found, not to crowd out the serial. */
.licpapers{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
.licpapers .chip{display:inline-flex;align-items:center;gap:5px;font-size:12px;
  text-decoration:none;max-width:100%}
.licpapers .chip .mono{opacity:.75}
.licpapers .chip:hover{border-color:var(--accent,#1A67D2);color:var(--accent,#1A67D2)}

/* 36.45 — the configuration on the row, whole.
   It is a list, not a phrase: the lines it was typed on are the lines it
   reads on. Set apart from the description above it by a rule rather than a
   gap, so a long record still reads as one record. */
.licconf{margin-top:6px;padding-top:6px;border-top:1px dashed var(--line,#e2e7ee)}
.licconf .eyebrow{display:block;margin:0 0 2px}
.licconf span:last-child{font-size:13px}

/* 36.45 — Edit, opened.

   The button lives in the last and narrowest column of a wide table, hard
   against the right-hand edge of the window. Laid out in that cell, the form
   simply left the screen: the client, the file chooser and Save were all
   past the edge, with nothing to scroll because the page had not grown.

   Hanging it off the cell was not enough either. `.rwrap` carries
   overflow-x:auto so a wide table can be scrolled sideways, and a browser
   that clips one axis clips the other with it — so a panel taller than the
   card was cut off at the card's edge, Save with it. Nothing inside that box
   can be made to escape it.

   So the panel leaves the table altogether: a drawer fixed to the right of
   the window, from under the header to just above the bottom, scrolling
   inside itself. It cannot be clipped by anything, it is the same shape on
   every row, and on a narrow screen it simply takes the width it needs.
   Which record it belongs to stops being obvious once it no longer touches
   the row, so it says so across the top. */
.liccell{position:relative}
.liccell>details>summary{display:inline-block}
.licpop{position:fixed;right:18px;top:84px;bottom:18px;z-index:70;
  width:min(430px,calc(100vw - 36px));overflow:auto;
  text-align:left;padding:14px;border:1px solid var(--line,#e2e7ee);border-radius:14px;
  background:var(--surface,#fff);box-shadow:0 24px 60px rgba(9,22,45,.22)}
.licpop .field{margin:0}
/* `hidden` is a UA rule of no specificity at all, and half of what is in
   here is a .stack, whose display:flex beats it. The script marks the plain
   name and date hidden the moment it has written a line per file; without
   this they stay on screen, switched off, looking like fields that have
   stopped working. */
.licpop [hidden],.licrows[hidden]{display:none}
.licpophead{display:flex;flex-direction:row;align-items:flex-start;gap:10px;
  margin:0 0 10px;padding-bottom:10px;border-bottom:1px solid var(--line,#e2e7ee)}
.licpophead .licpopwho{flex:1;min-width:0}
.licpophead .licpopwho strong{display:block;font-size:13px;word-break:break-all}
.licpophead .licpopwho span{font-size:12px;color:var(--muted,#5c6b7a)}
@media(max-width:700px){
  .licpop{right:10px;left:10px;top:64px;bottom:10px;width:auto;padding:12px}
}

/* 36.45 — the first cell, on a phone.

   Every row of every table in the portal turns into a card below 760px, and
   each cell becomes a flex row so its label can sit opposite its value. The
   first cell has no label and is not one value: on a licence it is the
   serial, the cloud key, the description, the model, the configuration and
   the papers — six blocks, which that rule lays out side by side, each
   squeezed into a sixth of the screen. So this one table's first cell reads
   down the page instead, like the paragraph it is. Scoped to this table
   because every other one puts a single line there. */
@media(max-width:760px){
  .lictable td.first{display:block;text-align:left}
  .lictable td.first>*{text-align:left}
  .lictable td.first .licpapers .chip{max-width:100%}
}

/* 36.45 — one line per file being attached: what it is, and its own date. */
.licrows{display:flex;flex-direction:column;gap:8px;margin:2px 0 0}
.licrow{display:flex;flex-direction:column;gap:4px;padding:8px;border-radius:10px;
  background:var(--surface-2,#f5f6f8);border:1px solid var(--line,#e2e7ee)}
.licrowname{font-size:11px;color:var(--muted,#5c6b7a);word-break:break-all}
.licrowpair{display:flex;flex-direction:row;gap:6px;flex-wrap:wrap}
.licrowpair input[name=title]{flex:1 1 150px;min-width:0}
.licrowpair input[name=doc_date]{flex:0 0 auto}


/* ------------------------------------------------------------------ *
 * 36.50 — the shop's two editable tables, on a phone
 * ------------------------------------------------------------------ *
 *
 * Both are forms laid out as tables: five columns for a shop, two for a
 * product rule. Inside .tblwrap a wide table scrolls sideways, which is
 * right for a table you READ — you drag it across and the page stays
 * still. It is wrong for a table you FILL IN: the Secret and the On
 * switch sit off the right-hand edge, and somebody setting up a shop on
 * a phone has to drag the box to find out there was more of the row.
 *
 * So under 760px each row becomes a small stack of labelled lines. The
 * label comes from data-label rather than a repeated <span>, so the
 * heading is written once, in the <th>, and the phone layout cannot
 * drift away from the desktop one.
 */
@media(max-width:760px){
  .shoptable, .shoptable tbody, .shoptable tr, .shoptable td{display:block;width:auto}
  .shoptable thead{display:none}
  .shoptable tr{padding:10px 12px;border-bottom:1px solid var(--line)}
  .shoptable tr:last-child{border-bottom:0}
  .shoptable td{padding:5px 0;border:0}
  .shoptable td::before{content:attr(data-label);display:block;margin:0 0 3px;
    font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
    color:var(--muted,#6b7480)}
  .shoptable td input, .shoptable td select{width:100%;max-width:none}
}

/* ------------------------------------------------------------------ *
 * 36.53 — the ticket email list, on a phone
 * ------------------------------------------------------------------ *
 *
 * The 36.50 note above says a wide table you READ is fine inside
 * .tblwrap, because you drag it sideways and the page stays still. This
 * one is the exception that proves where that stops being true.
 *
 * The whole point of the page is the last two columns — what the portal
 * did with the message, and which ticket it became. At phone width the
 * first two, When and From, fill the box, so the page opens showing an
 * email arrived and not one word about what happened to it. A table
 * whose answer is off the edge is a table that gets dragged once and
 * then mistrusted.
 *
 * So the same stacking as the shop's tables: each row becomes a short
 * block of labelled lines, with the heading taken from data-label so it
 * is written once in the <th> and the two layouts cannot drift apart.
 * ------------------------------------------------------------------ */
@media(max-width:760px){
  .mailtable, .mailtable tbody, .mailtable tr, .mailtable td{display:block;width:auto}
  .mailtable thead{display:none}
  .mailtable tr{padding:10px 12px;border-bottom:1px solid var(--line)}
  .mailtable tr:last-child{border-bottom:0}
  .mailtable td{padding:4px 0;border:0}
  .mailtable td::before{content:attr(data-label);display:block;margin:0 0 2px;
    font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
    color:var(--muted,#6b7480)}
  /* The subject is the line you scan down, so it keeps its weight. */
  .mailtable td[data-subject]{font-weight:600}
}
