/* =====================================================================
   The one stylesheet for this system.
   =====================================================================

   Before this file the styling lived in two <style> blocks - one in
   templates/base.html and one in templates/admin/base_site.html - and the
   navigation bar was written out twice, once as `header` and once as
   `.rets-nav`. Two copies of the same bar meant every change had to be made
   in both places and one of them was always a version behind.

   The file is read by two different kinds of page, which is why it is in
   three parts:

     1. TOKENS   the colours and the direction. Everything reads these.
     2. THE BAR  .rets-nav - the shared navigation. Both kinds of page.
     3. THE APP  the report screens, held inside `body.rets-app`.

   Part 3 is scoped on purpose. The admin loads this same file, and its own
   tables, headings and body rules are not ours to restyle - an unscoped
   `table th { background: … }` here would repaint every data entry screen
   in the admin. base.html puts `class="rets-app"` on its body; the admin
   does not, so part 3 simply never applies there.

   This step moved the rules and changed none of them. The colours below
   are the same values that were written inline before, now named. The new
   palette in DESIGN.md arrives with the screens it belongs to, not here.
   ===================================================================== */


/* ---------------------------------------------------------------------
   1. TOKENS
   --------------------------------------------------------------------- */

:root {
  /* --- this system is a light one, and says so ------------------------
     Chrome on Android has a setting that darkens any page that has not
     said which schemes it supports: it inverts the whole thing itself,
     guessing at the colours. That is why the system came out black on
     some phones and normal on every Windows machine - it was the phone
     doing it, not the page. "only light" is the one value that tells a
     browser not to try, and it is on :root so it covers the reports and
     the data entry screens alike. */
  color-scheme: only light;

  /* --- the new identity, from DESIGN.md ------------------------------
     In use by the side menu and the top bar. The screens underneath are
     still on the older palette below and change in their own steps, so
     for now the two sit side by side on purpose. */
  --brand: #3C0008;          /* the menu, darkest end of the scale */
  --brand-deep: #1F0004;     /* the foot of the menu gradient */
  --brand-mid: #8E1526;      /* buttons */
  --brand-edge: #5A0E1B;     /* the edge of the highlighted card */
  --brand-data: #A31226;     /* lines and bars in charts, never #3C0008 */
  --second: #1D6FA8;         /* the second thing in a chart, the open item */
  --second-pale: #E4EEF6;

  --menu-label: #A8818F;     /* the small heading over a group of links */
  --menu-ink: #EFE2E4;       /* a link at rest */

  --surface-page: #F2EAE9;
  --surface-card: #FBF6F5;
  --surface-soft: #F6EDEC;
  --surface-head: #FAF7F6;   /* the strip a table's column names sit on */
  --edge: #E7D8D7;
  --edge-soft: #F0E5E4;
  --text: #251114;
  --text-2: #6A5457;
  --text-3: #9B8688;

  /* reserved for state, and for nothing else */
  --ok: #12805A;      --ok-pale: #E2F0EA;
  --warn: #D89400;    --warn-pale: #FAF0DC;
  --bad: #B3261E;     --bad-pale: #F8E7E5;

  /* the identity, as it stands today */
  --navy: #1f3864;
  --line: #e3e6ec;
  --grey: #f7f8fa;

  /* named from the values that were already inline, so a colour is
     written once and read everywhere */
  --ink: #1a1a1a;
  --ink-soft: #666;
  --ink-muted: #777;
  --ink-label: #555;
  --paper: #fff;
  --alarm: #c62828;
  --alarm-hover: #a01c1c;
  --row-alt: #eef1f6;
  --row-warn: #fff3f3;
  --row-on: #e8f0fb;
  --box-line: #d0d7e2;
  --box-fill: #f7f9fc;

  /* logical direction, so nothing has to name left or right */
  --start: left;
  --end: right;
}

html[dir="rtl"] { --start: right; --end: left; }


/* ---------------------------------------------------------------------
   1b. THE FONT
   ---------------------------------------------------------------------
   Served from this server rather than fetched from Google at run time: a
   font loaded from outside ties how fast the factory's screens open to a
   network nobody here controls, and it disappears entirely behind a block.

   Declared but not yet switched on. Changing the face changes the width of
   every figure and every column with it, so it is turned on with the
   screens that were designed around it rather than underneath the screens
   that were not. Until then this costs nothing: a face nobody asks for is
   a face the browser never downloads.
   --------------------------------------------------------------------- */

@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-arabic-arabic-400.4fa3d81d41ab.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891,
                 U+0898-08E1, U+08E3-08FF, U+FB50-FDFF, U+FE70-FEFF;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-arabic-latin-400.4767e1197706.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-arabic-arabic-600.64891a810259.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891,
                 U+0898-08E1, U+08E3-08FF, U+FB50-FDFF, U+FE70-FEFF;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-arabic-latin-600.f417eeb0d15e.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-arabic-arabic-700.a4390abc98c2.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891,
                 U+0898-08E1, U+08E3-08FF, U+FB50-FDFF, U+FE70-FEFF;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-arabic-latin-700.8d04403cf599.woff2") format("woff2");
}

/* One line, read everywhere. The faces after the first are what a browser
   falls back to while the file is still arriving, or if it never does. */
:root {
  --font: 14px/1.7 "IBM Plex Sans Arabic", "Segoe UI", "Noto Naskh Arabic",
          "Dubai", Tahoma, Arial, sans-serif;
}


/* ---------------------------------------------------------------------
   2. THE SIDE MENU AND THE TOP BAR
   ---------------------------------------------------------------------
   templates/_nav.html and templates/_topbar.html, included by base.html
   and by the admin both, so data entry keeps the same menu as everything
   else instead of stranding whoever walks into it.

   Seventeen links used to sit in one strip across the top, in the order
   they happened to be written, and finding one meant reading all of them.
   They are the same seventeen links asking the same seventeen permission
   questions - they are just grouped now by the job somebody came to do.

   The font is restated on both because the admin loads its own stylesheet
   first and would otherwise set the menu in a different face from the page
   underneath it.
   --------------------------------------------------------------------- */

/* 218px was the width in DESIGN.md. Narrowed at the owner's request: the
   order table is a dozen columns wide and every millimetre the menu gives
   back is a column that stops running off the side of the screen. The
   longest label still fits on one line at this width. */
:root { --side: 182px; --topbar: 58px; }

/* --- the side menu ------------------------------------------------- */

.rets-side {
  position: fixed;
  inset-block: 0;
  inset-inline-start: 0;
  width: var(--side);
  z-index: 30;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--brand) 0%, var(--brand-deep) 100%);
  color: var(--menu-ink);
  font: var(--font);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Seventeen links, five headings and the two ends of the menu have to
     live inside the shortest screen anyone here works on. They do fit at
     the sizes below; the scrollbar is hidden rather than shown because on
     the rare screen where they do not, a bar down the middle of the menu
     is worse than a menu that scrolls quietly. */
  scrollbar-width: none;
}
.rets-side::-webkit-scrollbar { width: 0; height: 0; }

/* The admin underlines every link on its pages, with a rule written as
   a:not([role="button"], #header a, #nav-sidebar a, #content-main.app-list a,
   .object-tools a). A :not() takes the weight of its heaviest argument, so
   that rule counts as one id, one class and two elements - and the menu came
   out underlined on data entry screens and nowhere else. The id and both
   classes below are what it takes to answer it without an !important. */
#rets-menu.rets-side a.brand,
#rets-menu.rets-side a.item,
#rets-menu.rets-side a.count { text-decoration: none; }

/* Top-aligned, not centred: centring put the mark halfway down the block
   the moment a company name ran to a second line. */
.rets-side .brand {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 15px;
  color: inherit;
  text-decoration: none;
}
/* min-width:0 is what lets a flex child be trimmed at all */
.rets-side .brand .who { flex: 1; min-width: 0; }
.rets-side .brand b {
  display: block;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.35;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rets-side .brand .co {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 9.5px;
  line-height: 1.35;
  color: var(--menu-label);
}
.rets-side .brand .mark {
  width: 31px;
  height: 31px;
  border-radius: 9px;
  background: var(--brand-mid);
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.rets-side .group {
  margin: 7px 0 1px;
  padding: 0 15px;
  font-size: 9.5px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: .12em;
  color: var(--menu-label);
}

/* a link and, where there is one, the count that belongs beside it */
.rets-side .row { display: flex; align-items: center; }

.rets-side .item {
  flex: 1;
  min-width: 0;
  display: block;
  padding: 4px 15px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--menu-ink);
  text-decoration: none;
  border-inline-start: 3px solid transparent;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rets-side .item:hover { background: rgba(0, 0, 0, .18); }
.rets-side .item.on {
  background: rgba(0, 0, 0, .25);
  border-inline-start-color: var(--second);
  font-weight: 700;
  color: #fff;
}

/* A count is a link of its own, not decoration: the whole point of it is
   to land on the filtered list rather than the whole one. */
.rets-side .count {
  flex: none;
  margin-inline-end: 12px;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: 10px;
  background: var(--bad);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 19px;
  text-align: center;
  text-decoration: none;
}
.rets-side .count.odoo { background: var(--second); }
/* an order sent back: decided, but still not put right */
.rets-side .count.sent-back { background: var(--warn); color: #3C0008; }
.rets-side .count:hover { filter: brightness(1.15); }

.rets-side .foot { margin-top: auto; padding: 8px 15px 11px; }
.rets-side .foot .who { font-size: 10.5px; color: var(--menu-label); line-height: 1.45; }
.rets-side .foot .who b { color: var(--menu-ink); font-weight: 600; }

/* --- the top bar ---------------------------------------------------- */

.rets-top {
  position: sticky;
  top: 0;
  z-index: 20;
  height: var(--topbar);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 18px;
  background: var(--surface-card);
  border-bottom: 1px solid var(--edge);
  font: var(--font);
  color: var(--text);
}
/* the name of the screen, where it stays put instead of scrolling away */
.rets-top .screen { min-width: 0; }
.rets-top .screen b {
  display: block;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rets-top .screen span {
  display: block;
  font-size: 10.5px;
  line-height: 1.3;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rets-top .tools { margin-inline-start: auto; display: flex; align-items: center; gap: 12px; }
.rets-top form.inline { display: inline; margin: 0; }
.rets-top select { padding: 4px 7px; font: inherit; font-size: 12px; }

.rets-top .signout {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
  text-decoration: underline;
}
.rets-top .signout:hover { color: var(--brand-mid); }

/* the initials standing in for a photograph nobody has uploaded */
.rets-top .avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  flex: none;
  background: var(--surface-soft);
  border: 1px solid var(--edge);
  color: var(--text-2);
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Shown only on a narrow screen, where the menu is folded away. It is a
   real button so that it is reachable from the keyboard. */
.rets-top .menu-toggle {
  display: none;
  background: none;
  border: 1px solid var(--edge);
  border-radius: 8px;
  width: 34px;
  height: 32px;
  font-size: 15px;
  line-height: 1;
  color: var(--text-2);
  cursor: pointer;
}

.rets-backdrop { display: none; }

/* --- making room for the menu --------------------------------------- */
/* The menu is fixed, so the page beside it has to be told to start after
   it. base.html does that on its own body; the admin has a container of
   its own and is told separately. */

body.rets-app.has-menu { padding-inline-start: var(--side); }

/* A wide table scrolls inside the page rather than taking the page with
   it. These tables run to a dozen columns, and on a narrow screen the
   whole document used to slide sideways - so the menu, the heading and the
   filters all left the screen just to read the last column of figures. */
/* No cap on the width. It was held to 1200px, which on a wide screen left
   a band of empty page down one side while the order table was still
   running off the other. A wide table wants the whole window. */
body.rets-app main { padding-top: 18px; overflow-x: auto; }

/* The admin, which brings its own page furniture. The room is made on the
   body and not on the admin's #container: that container is sized in
   content-box with an explicit width, so padding is added to its width
   rather than taken out of it - it grew 218px wider than the window and
   pushed its own contents off the edge. The body has no width of its own,
   so padding there does what it is meant to.

   Its sign-in page is left out for the same reason as ours: there is no
   menu on it to make room for. */
body:not(.rets-app):not(.login) { padding-inline-start: var(--side); }

/* --- folded away on a narrow screen --------------------------------- */

@media (max-width: 900px) {
  /* Taken out of the page rather than parked off the edge of it. A fixed
     menu pushed sideways still counts as part of the document, and in a
     right-to-left page that put 218px of nothing past the right edge - so
     the whole screen scrolled sideways and the table ran off the side. */
  .rets-side { display: none; }
  html.menu-open .rets-side { display: flex; }

  body.rets-app.has-menu,
  body:not(.rets-app):not(.login) { padding-inline-start: 0; }

  .rets-top .menu-toggle { display: block; }

  html.menu-open .rets-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 25;
    background: rgba(31, 0, 4, .45);
    border: 0;
    width: 100%;
  }
}


/* ---------------------------------------------------------------------
   3. THE APP
   ---------------------------------------------------------------------
   The report screens. Everything below is held inside `body.rets-app` so
   that none of it reaches the admin, which loads this same file.
   --------------------------------------------------------------------- */

body.rets-app * { box-sizing: border-box; }

/* Paper rather than white, ink rather than black. A screen read all day
   under factory lighting is easier on the eye a shade off the extremes,
   and the cards only read as raised if the page behind them is darker. */
body.rets-app {
  margin: 0;
  color: var(--text);
  background: var(--surface-page);
  font: var(--font);
}
html[dir="rtl"] body.rets-app { font-size: 15px; }

body.rets-app main { padding: 12px; }
body.rets-app h1 { font-size: 20px; margin: 0 0 18px; }
body.rets-app h2 { font-size: 15px; margin: 26px 0 10px; color: var(--text); }
body.rets-app h1 .period {
  font-size: 14px; font-weight: 400; color: var(--text-3);
  margin-inline-start: 8px;
}
body.rets-app h2 .muted { font-size: 11px; font-weight: 400; }

/* --- the figure cards along the top of a report --- */
body.rets-app .cards { display: flex; gap: 12px; flex-wrap: wrap; }
body.rets-app .card {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 13px;
  padding: 14px 17px;
  min-width: 150px;
}
body.rets-app .card .k { font-size: 11px; color: var(--text-2); }
body.rets-app .card .v {
  font-size: 22px;
  font-weight: 700;
  margin-top: 4px;
  letter-spacing: -.4px;
  font-variant-numeric: tabular-nums;
}

/* --- tables ---
   The heading strip used to be a solid band of navy left over from the old
   palette, loud enough to read before the figures did. It is a heading, not
   the subject: quiet ground, small type, and the numbers carry the page. */
body.rets-app table {
  border-collapse: collapse;
  width: 100%;
  margin-top: 8px;
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 11px;
  overflow: hidden;
}
body.rets-app th {
  /* Maroon band, white lettering, at the owner's request. It reads as the
     top of the table from across the room, which a pale strip did not. */
  background: var(--brand);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 7px 4px;
  text-align: var(--start);
  border-bottom: 1px solid var(--edge);
}
/* a long table printed on two sheets needs its headings on both of them */
body.rets-app thead { display: table-header-group; }
/* Tight on purpose. The order list is fourteen columns wide, and at the
   roomier spacing a customer name wrapped onto three lines and half the
   columns were off the side of the screen - so the way to read one order
   was to scroll sideways and lose the order number doing it. */
body.rets-app td {
  border-bottom: 1px solid var(--edge-soft);
  padding: 6px 4px;
  font-size: 14px;
}
/* The two columns that hold somebody else's words - a customer's name and
   the name of a print - have no natural length and were setting the width
   of the whole table between them. They are given a ceiling and the rest
   is on the tooltip; every other column then fits on the screen. */
body.rets-app td.clip, body.rets-app th.clip { max-width: 62px; }
body.rets-app td.clip {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  unicode-bidi: plaintext;
}
/* A customer's name is the column people read the row by, and 62px cut it
   down to "350 - ..." on every line - which is a number, not a name. The
   room comes off the two date columns beside it: a date is ten characters
   and will never be more, so they are given exactly what they need and the
   headings above them wrap instead of setting the width. */
body.rets-app td.clip.name, body.rets-app th.clip.name { max-width: 150px; }
body.rets-app td.daycol, body.rets-app th.daycol {
  width: 76px;
  min-width: 76px;
  white-space: nowrap;
}
body.rets-app tr:nth-child(even) td { background: #FCFAF9; }
body.rets-app tfoot td { font-weight: 700; background: var(--surface-soft) !important; }
body.rets-app tr.on td { background: var(--warn-pale) !important; font-weight: 700; }
body.rets-app .warn td { background: var(--bad-pale) !important; }
body.rets-app td a { color: var(--brand-mid); text-decoration: none; }
body.rets-app td a:hover { text-decoration: underline; }

/* figures line up under each other only if they are all the same width */
body.rets-app .num {
  text-align: var(--end);
  font-variant-numeric: tabular-nums;
  direction: ltr;
}
html[dir="rtl"] body.rets-app .num { text-align: left; }

body.rets-app .muted { color: var(--text-2); font-size: 12.5px; }
body.rets-app form.inline { display: inline; }
body.rets-app select,
body.rets-app button,
body.rets-app input { padding: 6px 9px; font: inherit; }

/* --- the filter strip --- */
body.rets-app .filters {
  display: flex;
  gap: 14px;
  align-items: center;
  flex-wrap: wrap;
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: 10px 14px;
  margin-bottom: 14px;
}
body.rets-app .filters label { font-size: 12px; color: var(--text-2); }
body.rets-app .filters select { margin-inline-start: 6px; }
body.rets-app .filters .clear { font-size: 12px; color: var(--brand-mid); }
/* a search box needs room that a drop-down does not */
body.rets-app .filters label.wide input { min-width: 230px; }

/* the download sits folded away: it is wanted now and then, and open by
   default it would push the figures below the fold on every visit */
body.rets-app .report-box {
  margin: 12px 0;
  padding: 10px 14px;
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--surface-card);
}
body.rets-app .report-box summary { cursor: pointer; font-weight: 600; color: var(--brand-mid); }
body.rets-app .report-box .filters { margin-top: 10px; }

/* the download sits just under the heading on every report screen */
body.rets-app .download-line { margin: 0 0 14px; }
body.rets-app .download-line a {
  color: var(--brand-mid);
  font-weight: 600;
  text-decoration: none;
  border: 1px solid var(--edge);
  background: var(--surface-card);
  border-radius: 6px;
  padding: 5px 12px;
}
body.rets-app .download-line a:hover { background: var(--surface-soft); }
body.rets-app .download-line .muted { margin-inline-start: 10px; font-size: 12px; }

/* A button dressed as a link, for the actions that have to be a POST.
   The bar has its own copy of this above; this one is for the buttons on
   the page itself - the retry and skip buttons on the Odoo queue, which
   set their own colour inline over the white below. The white and the
   fading are kept exactly as they were: this step moves rules, it does
   not decide that any of them were wrong. */
body.rets-app .linklike {
  background: none;
  border: 0;
  padding: 0;
  color: var(--paper);
  cursor: pointer;
  font: inherit;
  opacity: .85;
}
body.rets-app .linklike:hover { opacity: 1; border-bottom: 2px solid var(--paper); }


/* ---------------------------------------------------------------------
   4. THE FIGURES AND THE CHARTS
   ---------------------------------------------------------------------
   The dashboard used to be ten identical boxes in a row. Ten things all
   the same size is the same as no order at all - the eye has nowhere to
   land, so the number the factory is actually run on was as loud as the
   number nobody reads. Nothing was taken away here; the same figures are
   ranked, so that the one that matters is the one you see first.

   Every chart is hand-written SVG or a div with a percentage width. No
   library: this server has two cores and 3.7GB, and a charting bundle is
   paid for by every screen on every load, on machines on the factory
   floor that are not new.
   --------------------------------------------------------------------- */

/* --- the ranked figures --------------------------------------------- */

body.rets-app .kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(184px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

body.rets-app .kpi {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 13px;
  padding: 13px 16px;
  min-width: 0;
}
body.rets-app .kpi .k { font-size: 11px; color: var(--text-2); }
body.rets-app .kpi .v {
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -.6px;
  line-height: 1.25;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  direction: ltr;
  text-align: var(--start);
}
body.rets-app .kpi .v .unit {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-3);
  letter-spacing: 0;
  margin-inline-start: 4px;
}
body.rets-app .kpi .note { font-size: 10.5px; color: var(--text-3); margin-top: 2px; }

/* The one figure the business is judged on. It is the only thing on the
   page with a filled background, which is the whole reason it reads first. */
body.rets-app .kpi.lead {
  background: linear-gradient(135deg, var(--brand-mid) 0%, var(--brand-edge) 100%);
  border-color: var(--brand-edge);
  color: #fff;
}
body.rets-app .kpi.lead .k,
body.rets-app .kpi.lead .note { color: rgba(255, 255, 255, .82); }
body.rets-app .kpi.lead .v .unit { color: rgba(255, 255, 255, .72); }

/* the second rank: still figures, half the weight */
body.rets-app .kpis.minor { grid-template-columns: repeat(auto-fit, minmax(136px, 1fr)); }
/* A card in the second row that carries a line of explanation needs the
   width to hold it; 136px would turn one sentence into six lines and take
   the whole row down with it. Only the cards asking for it are widened, so
   the rest of the row keeps its shape. */
body.rets-app .kpis.minor .kpi.wide { grid-column: span 2; }
body.rets-app .kpis.minor .kpi .note { font-size: 9.5px; line-height: 1.5; }
body.rets-app .kpis.minor .kpi { padding: 9px 13px; border-radius: 10px; }
body.rets-app .kpis.minor .kpi .k { font-size: 10px; }
body.rets-app .kpis.minor .kpi .v { font-size: 16px; letter-spacing: -.2px; }

/* --- the cards a chart lives in -------------------------------------- */

body.rets-app .panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 12px;
  margin: 12px 0;
}
body.rets-app .panel {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 13px;
  padding: 14px 17px;
  min-width: 0;
}
body.rets-app .panel h3 {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}
body.rets-app .panel .sub { font-size: 10.5px; color: var(--text-3); margin-bottom: 10px; }
/* Every chart says its point in words underneath. A picture that leaves
   the reader to work out what it means has not finished the job. */
body.rets-app .panel .says {
  margin: 10px 0 0;
  padding-top: 9px;
  border-top: 1px solid var(--edge-soft);
  font-size: 10.5px;
  color: var(--text-2);
  line-height: 1.6;
}
body.rets-app .panel .says b { color: var(--text); }

/* --- the trend over time --------------------------------------------- */

body.rets-app .trend { width: 100%; height: 190px; display: block; }
body.rets-app .trend .fill { fill: var(--brand-data); opacity: .13; }
body.rets-app .trend .line {
  fill: none;
  stroke: var(--brand-data);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
body.rets-app .trend .dot { fill: var(--brand-data); }
/* the month the screen is filtered to, so it can be picked out */
body.rets-app .trend .dot.chosen { fill: var(--brand); }
/* the grid is background, not a character in the story */
body.rets-app .trend .grid { stroke: var(--edge-soft); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* SVG coordinates do not turn round in an Arabic page, so the chart and
   the months under it are both pinned left-to-right. Left to itself the
   label row reversed and January captioned September. */
body.rets-app .trend-wrap { position: relative; direction: ltr; }
body.rets-app .trend-x {
  display: flex;
  justify-content: space-between;
  direction: ltr;
  font-size: 9.5px;
  color: var(--text-3);
  margin-top: 2px;
}
/* --- a point you can ask ---------------------------------------------
   The written figure can only sit on one point. Every other point on the
   line is a height the reader has to estimate, which is not reading a
   number - so each one carries an invisible target with its own figure
   inside it, shown when the mouse is on it.

   The target is deliberately bigger than the dot it covers. A 0.7-unit
   circle in a chart this wide is a few pixels across, and a label nobody
   can hit is a label that is not there. */

body.rets-app .tpoint {
  position: absolute;
  width: 26px;
  height: 26px;
  margin: 0 0 -13px -13px;      /* centred on the point it belongs to */
  border-radius: 50%;
  cursor: default;
}
body.rets-app .tpoint::after {
  /* the dot under the mouse, brought forward while it is being read */
  content: "";
  position: absolute;
  inset: 9px;
  border-radius: 50%;
  background: var(--brand);
  opacity: 0;
  transition: opacity .1s;
}
body.rets-app .tpoint:hover::after { opacity: 1; }
body.rets-app .tpoint i {
  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  display: none;
  background: var(--brand);
  color: #fff;
  font-size: 10.5px;
  font-style: normal;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 9px;
  white-space: nowrap;
  pointer-events: none;
  z-index: 3;
}
body.rets-app .tpoint:hover i { display: block; }

/* the figure, on the best month and on no other */
body.rets-app .peakpin {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  background: var(--brand-data);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 9px;
  white-space: nowrap;
}

/* --- a part of a whole: one bar, cut up ------------------------------ */

body.rets-app .split {
  display: flex;
  height: 21px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--surface-soft);
}
body.rets-app .split span { display: block; height: 100%; }
body.rets-app .split .done { background: var(--ok); }
body.rets-app .split .part { background: var(--warn); }
body.rets-app .split .none { background: var(--bad); }

/* the words beside the colours, because a colour on its own says nothing */
body.rets-app .legend { margin-top: 10px; }
body.rets-app .legend div {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  padding: 3px 0;
}
body.rets-app .legend i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  flex: none;
  display: inline-block;
}
body.rets-app .legend .n {
  margin-inline-start: auto;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* --- one number against a limit -------------------------------------- */

body.rets-app .gauge {
  height: 9px;
  border-radius: 5px;
  background: var(--surface-soft);
  overflow: hidden;
  margin-top: 5px;
}
body.rets-app .gauge span {
  display: block;
  height: 100%;
  border-radius: 5px;
  background: linear-gradient(90deg, var(--brand-data), var(--brand));
}

/* --- ranked sizes: horizontal bars ----------------------------------- */

body.rets-app .ranked { margin: 0; }
body.rets-app .ranked .row {
  display: grid;
  grid-template-columns: minmax(72px, 34%) 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 3px 0;
  font-size: 11.5px;
}
body.rets-app .ranked .name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--text-2);
  /* Customer names are whatever the customer is called - "AL ABEER
     FASHION" sits inside an Arabic page and was being trimmed from its
     first letter instead of its last. plaintext lets each name keep its
     own direction, so the dots land at the end of the name either way. */
  unicode-bidi: plaintext;
}
body.rets-app .ranked .track { background: var(--surface-soft); border-radius: 5px; height: 15px; }
body.rets-app .ranked .track span { display: block; height: 100%; border-radius: 5px; }
body.rets-app .ranked .n { font-weight: 700; font-variant-numeric: tabular-nums; }

/* The magnitude ramp: bigger is darker, always. Never a different colour
   for things that differ only in size. */
body.rets-app .g1 { background: #F7E6E7; }
body.rets-app .g2 { background: #EDC7CA; }
body.rets-app .g3 { background: #DDA0A6; }
body.rets-app .g4 { background: #C77680; }
body.rets-app .g5 { background: #A94E5B; }
body.rets-app .g6 { background: #832B39; }
body.rets-app .g7 { background: #3C0008; }


/* ---------------------------------------------------------------------
   5. PAPER
   ---------------------------------------------------------------------
   The menu, the top bar and the room made for them belong to the screen
   and not to the document. Each printable page used to switch off the old
   top strip by name in its own <style> block, and when the strip became a
   side menu with a different class those six rules quietly stopped
   matching - so the menu printed down the side of every invoice and the
   page was pushed sideways by the space kept for it.

   The scroll container is the other half of it, and the worse half: a box
   with overflow set prints what fits inside the box and nothing else, so
   the order sheet came out of the printer as four almost empty sheets.

   Written once, here, for every page that prints.
   --------------------------------------------------------------------- */

@media print {
  .rets-side,
  .rets-top,
  .rets-backdrop { display: none !important; }

  body.rets-app.has-menu,
  body:not(.rets-app):not(.login) { padding-inline-start: 0 !important; }

  /* paper is white; the page tint is for a screen */
  body.rets-app { background: #fff; }

  body.rets-app main {
    overflow: visible !important;
    padding: 0 !important;
    max-width: none !important;
  }
}


/* ---------------------------------------------------------------------
   6. THE LIST SCREENS
   ---------------------------------------------------------------------
   The parts every list screen shares: how a state is shown, how a filter
   reads, and how a proportion is drawn in a cell.
   --------------------------------------------------------------------- */

/* --- a state, as a pill ---------------------------------------------
   The colour never carries the meaning on its own. The word is inside the
   pill every time, so the screen still works for somebody who cannot tell
   the green from the amber - and on a photocopy of it. */

body.rets-app .pill {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 20px;
  white-space: nowrap;
  line-height: 1.6;
}
body.rets-app .pill.ok   { color: var(--ok);   background: var(--ok-pale); }
body.rets-app .pill.warn { color: var(--warn); background: var(--warn-pale); }
body.rets-app .pill.bad  { color: var(--bad);  background: var(--bad-pale); }
body.rets-app .pill.flat { color: var(--text-2); background: var(--surface-soft); }

/* --- a filter, as a chip --------------------------------------------
   The filters were a row of bare drop-downs, each one the same weight as
   the next, so reading what the screen was narrowed to meant reading all
   of them. The name of the filter is small and quiet; the value it is set
   to is the part that is bold, because that is the part that changes. */

body.rets-app .filters {
  background: transparent;
  border: 0;
  padding: 0;
  gap: 7px;
  margin-bottom: 12px;
}
body.rets-app .filters label {
  display: inline-flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  min-height: 34px;
  padding: 2px 9px;
  background: var(--surface-soft);
  border: 1px solid var(--edge);
  border-radius: 8px;
  font-size: 9.5px;
  line-height: 1.3;
  color: var(--text-3);
}
body.rets-app .filters label select,
body.rets-app .filters label input {
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text);
  max-width: 100%;
}
body.rets-app .filters label select:focus,
body.rets-app .filters label input:focus { outline: none; }
body.rets-app .filters label.wide input { min-width: 200px; }
body.rets-app .filters button {
  align-self: center;
  min-height: 34px;
  padding: 0 15px;
  border: 0;
  border-radius: 8px;
  background: var(--brand-mid);
  color: #fff;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
body.rets-app .filters button:hover { background: var(--brand-edge); }
body.rets-app .filters .clear { align-self: center; }

/* --- a proportion, in a cell ----------------------------------------
   The completion figure was a bare percentage, and a column of bare
   percentages is a column nobody scans. The bar is read before the number
   is, and the number is still there for whoever wants it. */

body.rets-app .with-bar { min-width: 78px; }
body.rets-app .cell-bar {
  height: 5px;
  margin-top: 3px;
  border-radius: 3px;
  background: var(--surface-soft);
  overflow: hidden;
}
body.rets-app .cell-bar span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--brand-data);
}
body.rets-app .cell-bar.done span { background: var(--ok); }
body.rets-app .cell-bar.none span { background: var(--bad); }


/* ---------------------------------------------------------------------
   7. DATA ENTRY
   ---------------------------------------------------------------------
   The admin, dressed to match the rest of the system. Style only: not one
   form, fieldset or field is touched here, and the screens list exactly
   the fields they listed before, in the order they listed them.

   Everything is scoped to a body without .rets-app, which is what the admin
   is, so none of it can reach the report screens - and nothing here is
   written twice, because part 3 of this file cannot see these pages
   either.

   The admin's own stylesheet is loaded before this one and leans on ids in
   places, so a few rules below carry an id of their own to answer it. That
   is the reason for #content and #container appearing, not decoration.
   --------------------------------------------------------------------- */

body:not(.rets-app) {
  background: var(--surface-page);
  color: var(--text);
  font-family: "IBM Plex Sans Arabic", "Segoe UI", "Noto Naskh Arabic",
               "Dubai", Tahoma, Arial, sans-serif;
}

/* --- the sheet the form sits on -------------------------------------- */

body:not(.rets-app) #content {
  background: transparent;
}
body:not(.rets-app) .module,
body:not(.rets-app) fieldset.module {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 13px;
  overflow: hidden;
}

/* The long screens - an order has fifty fields on it - are read as a set
   of named groups. The admin already puts them in groups; they just did
   not look like the start of anything. */
body:not(.rets-app) .module h2,
body:not(.rets-app) fieldset.module h2,
body:not(.rets-app) caption {
  background: var(--surface-head);
  color: var(--brand-mid);
  border-bottom: 1px solid var(--edge);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 10px 14px;
  text-transform: none;
}
body:not(.rets-app) .form-row {
  border-bottom: 1px solid var(--edge-soft);
  padding: 9px 14px;
}
body:not(.rets-app) .form-row:last-child { border-bottom: 0; }
body:not(.rets-app) .help,
body:not(.rets-app) .help-tooltip,
body:not(.rets-app) div.help { color: var(--text-3); font-size: 11px; }
body:not(.rets-app) label { color: var(--text-2); font-weight: 600; }

/* --- what you type into ---------------------------------------------- */

body:not(.rets-app) input[type=text],
body:not(.rets-app) input[type=password],
body:not(.rets-app) input[type=email],
body:not(.rets-app) input[type=url],
body:not(.rets-app) input[type=number],
body:not(.rets-app) input[type=tel],
body:not(.rets-app) input[type=date],
body:not(.rets-app) input[type=time],
body:not(.rets-app) textarea,
body:not(.rets-app) select,
body:not(.rets-app) .vTextField {
  background: #fff;
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: 6px 9px;
  color: var(--text);
  font-family: inherit;
}
body:not(.rets-app) input:focus,
body:not(.rets-app) textarea:focus,
body:not(.rets-app) select:focus {
  border-color: var(--brand-mid);
  outline: 1px solid var(--brand-mid);
  outline-offset: -1px;
}

/* --- buttons ---------------------------------------------------------
   One primary action per screen, in the identity colour; everything else
   quiet, so the eye lands on the one that saves. */

body:not(.rets-app) .button,
body:not(.rets-app) input[type=submit],
body:not(.rets-app) input[type=button],
body:not(.rets-app) .submit-row input[type=submit],
body:not(.rets-app) .object-tools a {
  background: var(--brand-mid);
  color: #fff;
  border: 0;
  border-radius: 8px;
  padding: 8px 15px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
}
body:not(.rets-app) .button:hover,
body:not(.rets-app) input[type=submit]:hover,
body:not(.rets-app) .object-tools a:hover { background: var(--brand-edge); }

body:not(.rets-app) .button.default,
body:not(.rets-app) input[type=submit].default,
body:not(.rets-app) .submit-row input.default {
  background: var(--brand-mid);
}
body:not(.rets-app) .button.default:hover,
body:not(.rets-app) input[type=submit].default:hover { background: var(--brand-edge); }

/* the second-rank buttons: present, but not competing */
body:not(.rets-app) .submit-row a.closelink,
body:not(.rets-app) .cancel-link,
body:not(.rets-app) .button.cancel-link {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  color: var(--text-2);
  border-radius: 8px;
}
body:not(.rets-app) .submit-row {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 13px;
  padding: 11px 14px;
}
/* deleting is not the same kind of act as saving, and should not look it */
body:not(.rets-app) .submit-row a.deletelink,
body:not(.rets-app) .deletelink {
  background: var(--bad-pale);
  color: var(--bad);
  border: 1px solid var(--bad);
  border-radius: 8px;
  padding: 8px 15px;
}

/* --- the lists ------------------------------------------------------- */

body:not(.rets-app) #changelist table thead th,
body:not(.rets-app) #changelist-filter h2,
body:not(.rets-app) #changelist-filter h3 {
  background: var(--brand);
  color: #fff;
  font-size: 11px;
}
body:not(.rets-app) #changelist table thead th a,
body:not(.rets-app) #changelist table thead th a:link,
body:not(.rets-app) #changelist table thead th a:visited { color: #fff; }
body:not(.rets-app) #changelist table tbody td,
body:not(.rets-app) #changelist table tbody th {
  border-bottom: 1px solid var(--edge-soft);
  padding: 7px 9px;
  font-size: 12px;
}
body:not(.rets-app) #changelist-filter {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 13px;
}
body:not(.rets-app) #toolbar {
  background: var(--surface-card);
  border: 1px solid var(--edge);
  border-radius: 10px;
  padding: 8px 10px;
}
body:not(.rets-app) .paginator {
  background: transparent;
  border-top: 1px solid var(--edge);
  color: var(--text-2);
}

/* --- the shelf of models on the front page --------------------------- */

body:not(.rets-app) .dashboard #content-main .module,
body:not(.rets-app) #nav-sidebar .module { border-radius: 11px; }
body:not(.rets-app) #nav-sidebar { background: transparent; }
/* The heading of a group in the admin's own model list is written white,
   for the dark band it used to sit on. The band is pale now, so the white
   was white on near-white and the heading could not be read at all. */
body:not(.rets-app) #nav-sidebar caption a,
body:not(.rets-app) #nav-sidebar caption a:link,
body:not(.rets-app) #nav-sidebar caption a:visited,
body:not(.rets-app) #nav-sidebar .section,
body:not(.rets-app) #nav-sidebar .section:link,
body:not(.rets-app) #nav-sidebar .section:visited,
body:not(.rets-app) #content-main .module caption a,
body:not(.rets-app) #content-main .module caption a:link,
body:not(.rets-app) #content-main .module caption a:visited {
  color: var(--brand-mid);
  text-decoration: none;
}
body:not(.rets-app) .breadcrumbs {
  background: var(--surface-soft);
  border-bottom: 1px solid var(--edge);
  color: var(--text-2);
  padding: 9px 14px;
}
body:not(.rets-app) .breadcrumbs a { color: var(--brand-mid); }

/* the messages the admin puts at the top of a screen */
body:not(.rets-app) ul.messagelist li {
  border-radius: 9px;
  background: var(--ok-pale);
  color: var(--ok);
  border: 1px solid var(--ok);
}
body:not(.rets-app) ul.messagelist li.warning {
  background: var(--warn-pale); color: var(--warn); border-color: var(--warn);
}
body:not(.rets-app) ul.messagelist li.error {
  background: var(--bad-pale); color: var(--bad); border-color: var(--bad);
}


/* The browser paints tick boxes, radios and sliders in its own blue unless
   it is told the page's colour. This is the only way to reach them. */
body.rets-app,
body:not(.rets-app) { accent-color: var(--brand-mid); }


/* The admin colours every link from these three properties. Setting them
   here turns the last of the old blue maroon in one place, rather than by
   hunting down each selector it uses. */
body:not(.rets-app) {
  --link-fg: var(--brand-mid);
  --link-hover-color: var(--brand);
  --link-selected-fg: var(--brand-edge);
}

/* --- ranked bars that carry a badge ----------------------------------
   CHARTS.md rule seven: bars in one chart share one track. The badge gets
   a column of its own, the same width on every row whether it holds
   anything or not - hung on the end of the bar instead, it would shorten
   exactly the bars that have something to say and the comparison would be
   a lie told by the layout. */
body.rets-app .ranked.owing .row {
  /* Every column here is a fixed width, and that is the point. Each row is
     its own grid, so an `auto` column is measured per row - the figures are
     different lengths, so the bars started at a different place on every
     line and the chart compared them against different scales. Rule seven
     in CHARTS.md is exactly this. */
  grid-template-columns: 62px 96px 1fr minmax(84px, 22%);
}
body.rets-app .ranked.owing .n { text-align: var(--end); }
body.rets-app .ranked.owing .flag { min-width: 62px; }
body.rets-app .ranked .track span.late { background: var(--bad); }
