/* ============================================================================
   Design system applied to the app.
   Tenant-agnostic design tokens + visual
   language onto the app's existing EJS/CSS class names. Flat, high-contrast,
   8-pt grid, hairline cards (no shadows), Archivo display + Inter body.
   Self-hosted fonts (no CSP change). Molecule mark is the one signature device.
   ============================================================================ */

/* ---- Self-hosted fonts (latin + latin-ext) ---- */
@font-face{font-family:'Archivo';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/archivo-700-latinext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Archivo';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/archivo-700-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Archivo';font-style:normal;font-weight:800;font-display:swap;src:url('/fonts/archivo-800-latinext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Archivo';font-style:normal;font-weight:800;font-display:swap;src:url('/fonts/archivo-800-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/inter-400-latinext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/inter-400-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/inter-500-latinext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/inter-500-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/inter-600-latinext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/inter-600-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}

/* ---- Tokens (locked; from the design system) ---- */
:root{
  --magenta:#1f2937; --magenta-hover:#111827; --magenta-press:#0b0f16;
  --azure:#1CA7DF; --azure-deep:#178FC0; --azure-tint:#E9F6FC;
  --navy:#1f2937; --navy-hover:#111827; --navy-press:#0b0f16;
  --ink:#16191D; --ink-60:#5B626B; --ground:#FFFFFF; --soft:#F6F8FA; --hairline:#E2E8EF;
  --status-error:#C0322B; --status-error-bg:#FBEDEC;
  --font-display:'Archivo','Segoe UI',system-ui,sans-serif;
  --font-body:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --radius-sm:4px; --radius-md:8px; --radius-lg:12px; --radius-pill:999px;
  /* FOCUS RING - two-tone, and it has to be. Backlog item 12.
     The previous value was rgba(28,167,223,.45). Measured properly, that alpha over white
     RENDERS as #99d7f1 = 1.57:1, not the 2.75:1 the solid colour suggests. It failed on
     every focusable control in the app, and 1.57:1 is not a focus indicator.
     A single solid tone does not fix it either: --azure-deep is 3.67:1 on white but 1.49:1
     on a magenta button, 2.22:1 on navy and 1.37:1 on the green badge - it would vanish on
     exactly the primary actions that matter most.
     TWO-TONE: inner --ground + outer --azure-deep. On a light surface the outer ring carries
     the contrast; on a dark control the inner one does.
     Do not collapse to one tone. Do not reintroduce alpha. Matches tokens.css exactly. */
  --focus:0 0 0 2px var(--ground), 0 0 0 4px var(--azure-deep);
}

/* ---- Base / reset ---- */
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:var(--font-body);font-size:16px;line-height:1.5;color:var(--ink);background:var(--soft);-webkit-font-smoothing:antialiased;}
a{color:var(--navy);text-decoration:none;}
/* SCOPED, deliberately. This was a bare `a:hover{color:...}`, specificity (0,1,1),
   which out-specifies every component class that sets its own colour at (0,1,0).
   It leaked into any link-shaped component with its own background and produced
   two invisible-text bugs at once: sidebar nav labels at 1.10:1 contrast, and a
   navy pill button whose text and background resolved to the SAME value (1.00:1
   — the "Download PDF" control rendered completely blank). Restricting it to
   links that are not components fixes both without touching either component. */
a:not([class]):hover,
a.link:hover{color:var(--navy-hover);}

/* ---- Typography ---- */
h1{font-family:var(--font-display);font-weight:800;font-size:2rem;line-height:1.15;letter-spacing:-.01em;color:var(--navy);}
h2{font-family:var(--font-display);font-weight:700;font-size:1.25rem;line-height:1.2;letter-spacing:-.01em;color:var(--navy);margin-bottom:12px;}
h3{font-family:var(--font-display);font-weight:700;font-size:1.05rem;color:var(--navy);margin-bottom:8px;}
.subtitle{color:var(--ink-60);font-size:.9rem;}
.brand-eyebrow{font-family:var(--font-body);font-weight:600;font-size: .75rem;letter-spacing:.06em;text-transform:uppercase;color:var(--magenta);}

/* ---- Layout ---- */
.page-wrap{max-width:680px;margin:0 auto;padding:16px;}
/* Wider variant for the owner dashboard (wide tables like the customer list). */
.page-wrap.page-wide{max-width:980px;}

/* ---- Cards (flat: white on soft, hairline border, NO shadow) ---- */
.card{background:var(--ground);border:1px solid var(--hairline);border-radius:var(--radius-lg);padding:20px;margin-bottom:16px;box-shadow:none;}

/* ---- Snapshot / stat boxes ---- */
.snapshot-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.stat-box{background:var(--soft);border:1px solid var(--hairline);border-radius:var(--radius-md);padding:14px;text-align:center;}
/* Never wrap a figure — scale it to the box instead (see home.css .kpi-value).
   `overflow-wrap:anywhere` here split "AED 19,876.50" into "AED 19,876.5"
   and "0" on Aged Receivables. The clamp was also keyed to VIEWPORT width
   (4.6vw), which says nothing about how wide the box actually is. */
.stat-box{container-type:inline-size;}
.stat-box .val{font-family:var(--font-display);font-weight:800;font-size:clamp(.95rem,11cqi,1.6rem);color:var(--navy);letter-spacing:-.01em;white-space:nowrap;}
.stat-box .lbl{font-family:var(--font-body);font-weight:600;font-size:.7rem;letter-spacing:.05em;color:var(--ink-60);margin-top:2px;text-transform:uppercase;}
@media (min-width:540px){ .snapshot-grid{grid-template-columns:repeat(4,1fr);} }

/* ---- Tables ---- */
.outstanding-table,.customer-table,.orders-table{width:100%;border-collapse:collapse;font-size:.85rem;font-family:var(--font-body);}
.outstanding-table th,.customer-table th,.orders-table th{text-align:left;padding:8px 6px;color:var(--ink-60);font-size: .75rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;border-bottom:1px solid var(--hairline);}
.outstanding-table td,.customer-table td,.orders-table td{padding:10px 6px;border-bottom:1px solid var(--hairline);vertical-align:top;}
.outstanding-table tr:last-child td,.customer-table tr:last-child td,.orders-table tr:last-child td{border-bottom:none;}
.cust-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--ink-60);}

/* ---- Badges (flat pills). Severity kept functional but muted/in-family. ---- */
.badge-green,.badge-amber,.badge-red{display:inline-block;padding:2px 9px;border-radius:var(--radius-pill);font-size: .75rem;font-weight:600;}
.badge-green{background:var(--azure-tint);color:var(--navy);}
.badge-amber{background:#FFF4D6;color:#8A5A00;}
.badge-red{background:var(--status-error-bg);color:var(--status-error);}
.cust-test-badge{background:var(--azure-tint);color:var(--navy);border-radius:var(--radius-pill);padding:1px 7px;font-size:.7rem;font-weight:600;}

/* ---- Buttons ---- */
.btn{display:inline-block;font-family:var(--font-body);font-weight:600;font-size:.9rem;border:1px solid transparent;border-radius:var(--radius-pill);padding:9px 18px;cursor:pointer;background:var(--magenta);color:#fff;transition:background .12s ease,box-shadow .1s ease,transform .08s ease;line-height:1.2;text-align:center;-webkit-tap-highlight-color:rgba(199,31,110,.28);}
.btn:hover{background:var(--magenta-hover);}
/* Clear pressed feedback on ALL buttons (touch + mouse): scales in with an inset shadow. */
.btn:active{background:var(--magenta-press);transform:translateY(1px) scale(.97);box-shadow:inset 0 2px 6px rgba(0,0,0,.22);}
.btn-sm{padding:6px 14px;font-size:.85rem;}
.btn-xs{padding:3px 10px;font-size:.75rem;border-radius:var(--radius-pill);}
.btn-primary{background:var(--magenta);color:#fff;}
.btn-primary:hover{background:var(--magenta-hover);}
.btn-full{width:100%;display:block;}
/* Navy (secondary/structural) buttons. Colour comes from the tenant via
   brand-vars.ejs; the values here are neutral defaults, NOT a brand. */
.btn-navy{background:var(--navy);color:#fff;}
/* Every :hover that changes a background also states its foreground. The blank
   navy pill happened because this rule set only the background while a bare
   a:hover set the text to the SAME value — 1.00:1, invisible. */
.btn-navy:hover{background:var(--navy-hover);color:#fff;}
/* Neutral/outline (used inline as background:#f3f4f6) */
.btn-ghost{background:var(--ground);color:var(--navy);border:1px solid var(--hairline);}
.btn-ghost:hover{background:var(--soft);color:var(--navy);}
:focus-visible{outline:none;box-shadow:var(--focus);border-radius:var(--radius-sm);}

/* ---- Forms ---- */
label{display:block;font-family:var(--font-body);font-weight:600;font-size:.85rem;color:var(--ink);margin-bottom:4px;}
input,select,textarea{font-family:var(--font-body);font-size:.9rem;border:1px solid var(--hairline);border-radius:var(--radius-md);padding:8px 10px;color:var(--ink);background:var(--ground);}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--navy);box-shadow:var(--focus);}
.form-group{margin-bottom:16px;}

/* ---- Order status text ---- */
.status-pending{color:#8A5A00;font-weight:600;}
.status-confirmed{color:var(--navy);font-weight:600;}
.status-delivered{color:#1B7A54;font-weight:600;}
.status-cancelled{color:var(--ink-60);font-weight:600;}

/* ---- Misc app classes ---- */
.system-row{display:flex;justify-content:space-between;align-items:center;padding:8px 0;border-bottom:1px solid var(--hairline);font-size:.9rem;}
.alert{padding:12px 16px;border-radius:var(--radius-md);margin-bottom:16px;font-size:.9rem;}
.alert-error{background:var(--status-error-bg);color:var(--status-error);border:1px solid #F3C9C6;}
.alert-success{background:var(--azure-tint);color:var(--navy);border:1px solid #C7E8F6;}
.alert-info{background:var(--azure-tint);color:var(--navy);border:1px solid #C7E8F6;}

/* ---- Molecule as a quiet brand device ---- */
.brand-bullet{display:inline-block;width:1em;height:1em;background:url('/images/brand/molecule.png') center/contain no-repeat;vertical-align:-.15em;}

/* ---- Brand lockup (molecule + wordmark) — fluid; never overflows on mobile ---- */
.brand-lock{display:inline-flex;align-items:center;gap:10px;max-width:100%;}
.brand-lock .brand-lock-mark{height:clamp(34px,10vw,46px);width:auto;flex:0 0 auto;}
.brand-lock .brand-lock-wordmark{height:auto;max-height:clamp(23px,6.6vw,31px);max-width:100%;width:auto;min-width:0;flex:0 1 auto;object-fit:contain;}
/* A supplied logo with no separate wordmark is shown alone and large enough to
   read the name inside it (brand-lock.ejs). The company name as text is the
   fallback only when the tenant has supplied nothing. */
.brand-lock--logo{display:flex;justify-content:center;}
.brand-lock .brand-lock-logo{display:block;width:auto;height:auto;max-width:min(260px,100%);max-height:150px;object-fit:contain;}
.brand-lock .brand-lock-name{font-weight:700;font-size:clamp(1.05rem,4.6vw,1.3rem);letter-spacing:-0.01em;color:var(--brand-primary,#1f2937);text-align:left;line-height:1.15;}
/* Standalone wordmark (e.g. stacked over a date) that must shrink within its column */
.brand-wm-fluid{height:auto;max-height:clamp(22px,6vw,29px);max-width:100%;width:auto;object-fit:contain;}


/* ══════════════════════════════════════════════════════════════════════════
   HIT TARGETS
   ══════════════════════════════════════════════════════════════════════════
   DSH-A1 specifies "44pt minimum touch targets ... with 8dp spacing".
   tokens.css is now global (UX-1, shell-start.ejs). Every interactive element
   meets 44px on its own bounding box — no pseudo-element expansion needed.

   Small targets punish exactly the user this product is built for: a
   non-technical operator working quickly, often on a laptop trackpad or a
   tablet. So controls get a real minimum height, and the ones that must stay
   visually small get an INVISIBLE expanded hit area instead — that keeps the
   density the design intends while making the target honest.
   ────────────────────────────────────────────────────────────────────────── */
:root {
  --hit-min: 44px;          /* WCAG 2.5.5 target size */
  --hit-comfortable: 44px;  /* was 40px — raised so every control meets 44px on its own element, not just via a pseudo-element expansion */
}

/* Primary controls get real height. */
.btn,
button:not(.btn-sm):not(.btn-xs):not(.nav-item),
select,
textarea,
input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]) {
  min-height: var(--hit-comfortable);
}

/* Dense controls now meet 44px on the element itself so measurement harnesses
   report 44px, not just the pseudo-element clickable area. */
.btn-sm, .btn-xs {
  min-height: var(--hit-min);
}

/* Inline action links inside tables and action rows — "Statement →",
   "View all orders →" measured 17-20px tall. Now 44px on the element itself. */
.w-table a,
.row-actions a,
.action-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--hit-min);
}

/* General interactive links inside shell content that aren't in tables. Covers
   card action links, breadcrumbs, "View all →" links, etc. Scoped to
   .shell-main so sidebar nav items and the topbar (handled separately) are
   unaffected. */
.shell-main a[href]:not(.btn):not(.nav-item):not(.topbar-user):not(.topbar-logout) {
  min-height: var(--hit-min);
  display: inline-flex;
  align-items: center;
}

/* Checkboxes and radios were 13x13 — the smallest target in the product and the
   one used for bulk actions, where a mis-click selects the wrong record. */
input[type="checkbox"], input[type="radio"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
  /* Without this a checkbox inside a flex label SHRINKS below its declared
     width — the "Test customer" box measured 14.2px against a declared 18px,
     because the label is a flex container and the input was a shrinkable item.
     A declared size on a form control is not honoured until shrinking is off. */
  flex: 0 0 auto;
}
/* In a table the checkbox has no label to extend its target, so the cell itself
   carries the padding that makes the row's select area reach the minimum. */
.w-table td:has(> input[type="checkbox"]),
.w-table th:has(> input[type="checkbox"]),
.w-table .col-select {
  padding-top: 13px;
  padding-bottom: 13px;
}

/* A visible focus ring on everything keyboard-reachable. Operators who work
   fast use Tab, and an invisible focus state makes that impossible to follow. */
.btn:focus-visible,
button:focus-visible,
a:focus-visible,
select:focus-visible,
input:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
  border-radius: var(--radius-sm, 4px);
}

/* Visually hidden, still announced — for header cells like "Actions" that a
   screen reader needs but a sighted reader does not. Global, because a page
   that uses the class without loading its stylesheet prints the label as
   visible text. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
