
  /* Light is the base; dark applies twice on purpose: once for the system preference when
     the person has NOT chosen (the :not guard keeps an explicit "light" from being overridden
     by a dark OS), and once for the explicit choice, which must win in both directions. */
  :root{--bg:#f4f5f7;--surface:#fff;--surface-2:#edeff2;--ink:#141821;--ink-2:#3c4356;--muted:#67708a;
    --line:#dde1ea;--accent:#1E4FA8;--accent-soft:#dde6f7;--green:#1F8A5D;--teal:#7CCFC4;
    --good:#1F8A5D;--warn:#a96c17;--crit:#a94238;
    --shadow:0 1px 2px rgba(20,24,33,.06),0 8px 24px rgba(20,24,33,.05);
    /* what the BROWSER draws for itself: date-field chrome, the calendar and its popup, <select>
       boxes and their dropdowns, scrollbars. Without this they follow the OS and not the page. */
    color-scheme:light}
  @media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#0f1319;--surface:#161c26;--surface-2:#1d2532;--ink:#e8ecf4;
    --ink-2:#c1c9da;--muted:#8a94ab;--line:#283243;--accent:#8fb0f2;--accent-soft:#1e2c4d;--green:#5cc196;--teal:#7CCFC4;
    --good:#5cc196;--warn:#d9a24e;--crit:#e0837a;--shadow:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.3);color-scheme:dark}}
  :root[data-theme="dark"]{--bg:#0f1319;--surface:#161c26;--surface-2:#1d2532;--ink:#e8ecf4;
    --ink-2:#c1c9da;--muted:#8a94ab;--line:#283243;--accent:#8fb0f2;--accent-soft:#1e2c4d;--green:#5cc196;--teal:#7CCFC4;
    --good:#5cc196;--warn:#d9a24e;--crit:#e0837a;--shadow:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.3);color-scheme:dark}
  /* the explicit LIGHT choice has to win over a dark OS here too, or the toggle leaves every
     native control dark on a light page */
  :root[data-theme="light"]{color-scheme:light}
  @font-face{font-family:'Noto Sans Georgian';src:url('/assets/noto-georgian.woff2') format('woff2');font-weight:400 700;font-display:swap}
  *{box-sizing:border-box}
  a{color:var(--accent);text-decoration-thickness:1px;text-underline-offset:2px;
    text-decoration-color:color-mix(in srgb,currentColor 32%,transparent)}
  a:visited{color:var(--accent)}
  a:hover{opacity:.85;text-decoration-color:currentColor}
  /* THE PRESS IS DRAWN IN THE FRAME IT HAPPENS IN. Measured 2026-09-24 on /feedback: 722 rules and
     not one :active, no tap highlight of the app's own, and 239–307 ms after a filter tap in which
     nothing on the screen moved (inbox.mjs has the numbers). These need no script: the shell's own
     .btab shows the press as the .on it will wear once chosen, a button darkens a step, and a tap
     anywhere is tinted with the accent instead of the browser's grey. The inbox's chip rails draw
     their press in INBOX_CSS, after their own :visited reset, which outranked it from here. iOS
     draws :active only on a page that listens to touchstart — inbox.mjs registers that listener. */
  a,button,label,summary,select,input{-webkit-tap-highlight-color:color-mix(in srgb,var(--accent) 20%,transparent)}
  .bchip{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;font-weight:560;white-space:nowrap}
  .bchip .av{border-radius:50%;color:#fff;display:inline-grid;place-items:center;font-weight:700;flex:none}
  .btabs{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
  .btab{display:inline-flex;align-items:center;gap:6px;padding:7px 13px;border:1px solid var(--line);border-radius:999px;
    text-decoration:none;font:inherit;font-size:13px;color:var(--ink-2);background:var(--surface);cursor:pointer}
  .btab.on{border-color:var(--accent);background:var(--accent-soft);color:var(--ink);font-weight:600}
  .btab:hover{opacity:1;background:var(--surface-2)}
  /* the press (see the tap-highlight note above) — after .btab:hover, which a pressed mouse also is.
     ONLY ON A CONTROL THAT DOES SOMETHING: /rating, /payroll and /earn draw the month they cannot go
     to as a bare <span class="btab"> (/rating adds aria-disabled), and a press that lit it answered a dead arrow
     like a live one. So: a link with an href, or a button that is not disabled. */
  a[href].btab:active,button.btab:not(:disabled):not([aria-disabled="true"]):active{border-color:var(--accent);
    background:var(--accent-soft);color:var(--ink)}
  /* ── .gox — "this leaves the card" ──────────────────────────────────────────────────────
     Twenty-four links at the foot of a card were bare <a>s. html.mjs sets only
     a{color:var(--accent)} and never removes the underline, so they fell through to the UA
     stylesheet: no box, no hit area, no hover — an ~18px target on pages where .ch-tap is
     46px and .ch-q is 58px. Nothing below is invented:
       13.5px/620, padding 8px vertical  → .ch-tap        (consultant-home.mjs:564)
       14px horizontal, radius 11px      → .ch-task :582 and .ch-best :596, the two blocks
                                           sitting directly above the circled footers
       1px var(--line) on var(--surface) → .ch-tap/.ch-task/.ch-best. A --surface-2 fill at
                                           11px radius would read as .ch-m, the one thing on
                                           that card that is deliberately NOT clickable.
     No box-shadow: .ch-task and .ec-rule>div carry none — a block inside a card is not a card.
     The "→" is kept, not replaced by an icon: .dtile .s, .mk-foot, .sev-tile .s, .abtn,
     a.hstat b, .ch-cta, .lgo and .qread all speak the literal glyph, and one SVG chevron
     among them would be two designs for one meaning. It lives in a muted slot and wakes on
     hover, which is exactly how those components carry theirs.
     „.gox:visited" is not decoration: the global a:visited{color:var(--accent)} near the top of this sheet is (0,1,1)
     and would otherwise beat „.gox" (0,1,0) on every link already opened, so a footer would
     show one grey chip beside one accent chip. „opacity:1" on hover defeats the global
     a:hover{opacity:.85}, the same way .btab:hover already has to. */
  .gox,.gox:visited{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;min-height:38px;
    border:1px solid var(--line);border-radius:11px;background:var(--surface);color:var(--ink-2);
    font:inherit;font-size:13.5px;font-weight:620;line-height:1.25;text-decoration:none;
    transition:border-color .12s,color .12s}
  .gox:hover,.gox:focus-visible{opacity:1;border-color:var(--accent);color:var(--ink)}
  /* nav a:hover .nv-ic{opacity:1} — the chrome's existing icon-wakes-on-hover contract */
  .gox>.gox-i{display:inline-flex;flex:none;opacity:.7;transition:opacity .12s}
  .gox:hover>.gox-i,.gox:focus-visible>.gox-i{opacity:1}
  .gox>.gox-i svg{display:block}
  /* the label wraps rather than pushing the page sideways — a 31-character Georgian phrase
     inside a 303px card interior at 375px has nowhere else to go */
  .gox>.gox-t{min-width:0;overflow-wrap:anywhere}
  .gox>.gox-a{font-style:normal;flex:none;opacity:.55;transition:opacity .12s,transform .12s}
  .gox:hover>.gox-a,.gox:focus-visible>.gox-a{opacity:1;transform:translateX(2px)}
  .gox.back>.gox-a{margin-inline:-1px 0}
  .gox.back:hover>.gox-a,.gox.back:focus-visible>.gox-a{transform:translateX(-2px)}

  /* ── the size that stands beside a button.small ────────────────────────────────────────
     button{border-radius:8px} + button.small{padding:4px 12px;font-size:12.5px} computes to
     ~27.4px, so 28px and radius 8 make the pair one row instead of two. This variant exists
     only for that neighbour rule — never inside a .cfoot — and the phone block below gives
     it 40px back, because /  , /tasks and /stock are all opened on a phone. */
  /* The dense variant does NOT wrap. The full-size chip must — a card footer carries phrases like
     „ყველა დავალება და მიმოწერა" and wrapping is what keeps it from pushing the page sideways.
     But .sm exists only for dense rows, where every label is a word or two („გახსნა", „11 დღე",
     „ნახვა"), and a narrow table column was folding „11 დღე" into two lines inside its own box.
     Tables here already live in .card.scroll, so the row scrolls instead of the page. */
  .gox.sm,.gox.sm:visited{padding:5px 12px;min-height:28px;border-radius:8px;gap:6px;
    font-size:12.5px;font-weight:600;white-space:nowrap}

  /* tone: 45% is the mix html.mjs already uses for .chip.k-warehouse / .chip.k-transfer */
  .gox.warn,.gox.warn:visited{color:var(--warn);border-color:color-mix(in srgb,var(--warn) 45%,transparent)}
  .gox.warn:hover,.gox.warn:focus-visible{color:var(--warn);border-color:var(--warn)}
  .gox.crit,.gox.crit:visited{color:var(--crit);border-color:color-mix(in srgb,var(--crit) 45%,transparent)}
  .gox.crit:hover,.gox.crit:focus-visible{color:var(--crit);border-color:var(--crit)}

  /* ── the model picker ─────────────────────────────────────────────────────────────────
     Type a few letters, see the real models WITH their photographs. It existed only inside the
     courier form — hard-coded ids, module globals, one per page — so every other field that asks
     which model somebody means got a bare <input list> over 900 products with no pictures. The
     feedback form has TWO on one screen, which a single-instance widget cannot serve at all.
     Geometry is .din's, because that is what it stands in a column with. */
  .mpw{position:relative}
  .msug{position:absolute;left:0;right:0;top:100%;z-index:30;margin-top:4px;max-height:302px;overflow-y:auto;
    background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow)}
  .msug-i{display:flex;align-items:center;gap:10px;width:100%;font:inherit;font-size:13.5px;text-align:left;
    padding:7px 10px;background:none;border:0;border-bottom:1px solid var(--line);color:var(--ink);cursor:pointer}
  .msug-i:last-child{border-bottom:0}
  .msug-i:hover,.msug-i.on{background:var(--surface-2)}
  .msug-i img,.msug-no{inline-size:38px;block-size:38px;border-radius:7px;background:var(--surface-2);flex:none}
  .msug-i img{object-fit:contain}
  .msug-no{display:grid;place-items:center;color:var(--muted);font-size:12px}
  .msug-t{flex:1;min-width:0;overflow-wrap:anywhere}
  .msug-t em{font-style:normal;color:var(--muted);margin-inline-start:6px;font-size:12px}
  .msug-i i{font-style:normal;font-size:11.5px;font-weight:640;white-space:nowrap;flex:none}
  .msug-i i.ok{color:var(--green)}
  .msug-i i.out{color:var(--muted)}
  /* ordered but not arrived — amber, because it is a live model, not a dead one */
  .msug-i i.soon{color:var(--warn)}
  /* the chosen model stays on screen: the whole point is that the picture answers „which one" */
  .mpick{display:flex;align-items:center;gap:10px;margin-top:7px;padding:7px 10px;font-size:13px;
    background:var(--surface-2);border:1px solid var(--line);border-radius:10px}
  .mpick[hidden]{display:none}
  .msug[hidden]{display:none}
  .mpick img{inline-size:40px;block-size:40px;object-fit:contain;border-radius:7px;background:var(--surface);flex:none}
  .mpick>span{flex:1;min-width:0;overflow-wrap:anywhere}
  .mpick em{font-style:normal;color:var(--muted);font-size:12px}
  .mpick-x{font:inherit;background:none;border:0;color:var(--muted);cursor:pointer;font-size:16px;line-height:1;padding:4px}
  .mpick-x:hover{color:var(--crit)}
  /* ── .cfoot — the card's seam ─────────────────────────────────────────────────────────
     The rule and both numbers are .ec-parts' (earn-page.mjs:174) — the seam already drawn
     INSIDE the .ec card whose footer was circled. .ch-mini (consultant-home.mjs:549) is the
     same idiom at 14/13. It needs no knowledge of its shell: .ch-card, .ec and .cc are
     <section>s and inherit the global section{gap:12px} of this sheet, and .lcard sets gap:12 itself,
     so 12+12 = an identical 24px above the hairline in all four — no per-page override, and
     nothing page-specific in this file. Inset, not bled: the hairline spans the content box,
     so each card's own side padding is respected for free. */
  .cfoot{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:12px;padding-top:12px;
    border-top:1px solid var(--line)}
  .cfoot-l{font-size:12.5px;color:var(--ink-2);line-height:1.45;overflow-wrap:anywhere}
  .cfoot-l b{color:var(--ink);font-weight:700}
  .cfoot-g{display:flex;gap:8px;flex-wrap:wrap;flex:1}
  /* the same chip outside a card: page toolbars, back links, breadcrumbs */
  .gorow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0}

  /* ── a whole-row file link ─ (named .frow, not .rrow: rating.mjs:208 already owns .rrow
     for a padding:4px 0 flex row, and a global rule of the same name would restyle that page
     without anyone touching it) ─────────────────────────────────────────────────────────────
     The report listing was a column of underlined accent filenames inside padded divs. It is
     a scan target, not a button bar, so the row keeps its 12/16 rhythm and its hairline and
     simply becomes the anchor — the same move a.hstat (its rules further down this sheet) already made for the
     KPI tile. Long filenames wrap instead of widening the card. */
  .frow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;
    border-bottom:1px solid var(--line);text-decoration:none;color:var(--ink);font-size:13.5px;
    overflow-wrap:anywhere}
  .frow:last-child{border-bottom:0}
  .frow:hover{opacity:1;background:var(--surface-2)}
  .frow i{font-style:normal;color:var(--muted);flex:none}

  /* ── the whole KPI tile is the link ────────────────────────────────────────────────────
     One tile in a 1px-hairline grid had an underlined anchor stuffed into its 12px sub-label
     slot. a.hstat (its rules further down this sheet) solved this exact need correctly one screen away; this
     is the same three declarations. The tile's height does not change, so the @640 two-column
     .kpis state is unaffected. */
  a.kpi{text-decoration:none;color:inherit}
  a.kpi:hover{opacity:1;background:var(--surface-2)}
  a.kpi .v{color:var(--accent)}

  /* ── links that are genuinely inside a sentence are NOT this component ─────────────────
     THE ROOT CAUSE, and the gap this stylesheet has always had: html.mjs styles .q and .hint
     but never their anchors, so every link dropped into muted prose punched back to
     accent + underline and the sentence read as two colours on one line. Mid-paragraph an
     underline IS the only affordance available, so it stays — but it stops being a colour
     change. Covers courier.mjs:1879, worktime.mjs:527, settings.mjs:297, ga.mjs's five
     numbered steps and every future one, with no markup churn.
     „:not(.gox)" so a chip parked in a .hint keeps its own colour; „.q:not(.smeta)" so
     search.mjs's own „.smeta a{color:inherit}" — the one place an anchor colour was already
     deliberately tamed — is left exactly as it was. */
  .q:not(.smeta) a:not(.gox),.hint a:not(.gox){color:var(--ink);font-weight:620;
    text-decoration-line:underline;text-decoration-thickness:1px;text-underline-offset:2px;
    text-decoration-color:color-mix(in srgb,var(--accent) 55%,transparent)}
  .q:not(.smeta) a:not(.gox):hover,.hint a:not(.gox):hover{opacity:1;color:var(--accent);
    text-decoration-color:var(--accent)}

  /* ── PHONE ────────────────────────────────────────────────────────────────────────────
     Same breakpoint and the same formula .ch-tap uses on the consultant home (:607,
     „flex:1;min-width:calc(50% - 4px)" at gap 8): one chip spans the card, two go side by
     side, a third stretches rather than hanging as an orphan. 46px is the tap floor the
     source chips right above it already keep, and .ch-tap's own comment is the law being
     applied — labels are one or two lines depending on the word, so pin the height.
     .gox.sm grows to 40px here as well: it is small on desktop to match a button.small, not
     because those screens are desktop-only — the dashboard KPI grid has its own @640
     two-column rule, so a manager reads /  , /tasks and /stock on a phone too. */
  @media(max-width:560px){
    /* .gorow .gox.sm sets flex:0 0 auto, so the chip will not shrink below its one-line
       max-content even once the text is allowed to wrap — max-width is what actually caps it */
    .gox{min-height:46px;padding:11px 14px;justify-content:center;text-align:center;max-width:100%}
    /* the base .gox lets its label wrap for exactly this reason; .sm then set nowrap back and
       took the page with it — „61 პროდუქტი, რომელსაც ფასი არ აქვს" is 318 px on one line */
    .gox.sm{min-height:40px;padding:9px 12px;font-size:13px;white-space:normal}
    .cfoot-l,.cfoot-g{width:100%}
    .cfoot .gox,.gorow .gox{flex:1 1 calc(50% - 4px)}
    .cfoot .gox.sm,.gorow .gox.sm{flex:0 0 auto}
  }
  /* /feedback locks html{overflow:hidden} while its popup is open. Without a reserved gutter the
     scrollbar vanishes and the whole page jumps sideways on open and back on close. */
  html{scrollbar-gutter:stable}
  body{margin:0;background:var(--bg);color:var(--ink);font-family:"Noto Sans Georgian","Segoe UI",system-ui,sans-serif;
    font-size:15px;line-height:1.55;font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased}
  .page{max-width:1040px;margin:0 auto;padding:18px 18px 64px;display:flex;flex-direction:column;gap:22px}
  /* THE BAR NEVER WRAPS — at any width, on any screen.
     It used to wrap above 1000 px, and the page is capped at 1040 px, so the bar has a FIXED
     ~1004 px slot no matter how wide the monitor is: the moment its links needed 1007 px the ⚙
     dropped onto a second row under the logo. That is the third time the owner has circled it
     (2026-09-05), and each previous fix bought a few pixels that the next label spent. Pixels are
     not the answer; the failure mode is. Wrapping is the only one that looks broken, so it is
     removed, and the design's own answer for a bar too long — a one-row scroller, which has run
     below 1000 px since August — now runs everywhere. Open panels are portalled to <body> (see
     the toggle handler), so nothing is clipped by this scroller. */
  nav{display:flex;gap:3px;align-items:center;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    border-bottom:1px solid var(--line);padding-bottom:12px}
  nav::-webkit-scrollbar{display:none}
  nav a,nav .ng>summary,nav .gear>summary,nav form button{white-space:nowrap}
  nav a{color:var(--ink-2);text-decoration:none;padding:7px 12px;border-radius:8px;font-size:14px;font-weight:560;
    display:inline-flex;align-items:center;gap:7px}
  .nv-ic{display:inline-flex;flex:none;opacity:.8}
  nav a.on .nv-ic,nav a:hover .nv-ic{opacity:1}
  .nv-ic svg{display:block}
  /* WHERE THE BAR STOPS FITTING, IT SCROLLS — it must never wrap.
     This began at 760 px, so between 761 and ~960 the bar wrapped to a second row and the ⚙ landed
     under the logo: the icon the owner circled, and the reason it kept coming back is that the bar
     has no single link to blame — at 900 px it wants ~883 px in an ~850 px slot no matter which
     links are in it. Wrapping is the only failure mode that looks broken; a one-row scroller is
     the design's own answer for a narrow bar and it already worked, it just started 240 px too
     late. Above 1000 px the bar fits on one row with ~90 px to spare (measured, 2026-09-02).
     Everything inside here — the padding, the byline, and the bell panel's escape — belongs to
     that one decision and moves with it. */
  @media (max-width:1000px){
    /* -webkit-overflow-scrolling:touch is deliberately absent: iOS 13+ scrolls with momentum on
       its own, and the property makes position:fixed descendants behave as position:absolute
       against this scroller — which is half of why the dropdowns would not come down. */
    nav{padding-bottom:10px;margin:0 -10px;padding-inline:10px}
    nav a{padding:7px 10px;font-size:13.5px}
    .bwm i{display:none}
    .bwm b{font-size:14px}
    nav form button{white-space:nowrap;padding:7px 10px;font-size:13px}
  }
  nav a.brand{display:flex;align-items:center;gap:9px;padding:4px 8px 4px 2px;margin-inline-end:4px}
  /* wordmark: PULSE is the product, SYNERGY GEORGIA the quiet parent under it.
     The line box must clear the descender of "უ": at line-height 1.05 the b ended at
     exactly the y where the i began, so the tail was drawn over SYNERGY GEORGIA. */
  .bwm{display:flex;flex-direction:column}
  .bwm b{font-size:15.5px;font-weight:800;letter-spacing:-.01em;color:var(--ink);line-height:1.22}
  /* "by" stays lowercase and quiet so SYNERGY GEORGIA still reads as the name */
  /* 3px was too tight: „უ" in პულსი drops a descender, so the byline read as touching it.
     Wide enough to breathe, still close enough to be one mark rather than two lines. */
  .bwm i{font-style:normal;font-size:8.5px;font-weight:600;letter-spacing:.1em;color:var(--muted);line-height:1;margin-top:6px}
  .bwm i em{font-style:normal;font-weight:500;letter-spacing:.02em;opacity:.72;margin-inline-end:1px}
  /* category dropdowns — coloured underline marks the group of the open page */
  .ng{position:relative}
  .ng>summary{list-style:none;cursor:pointer;user-select:none;display:inline-flex;align-items:center;gap:6px;
    padding:7px 13px;border-radius:8px;font-size:14px;font-weight:560;color:var(--ink-2);white-space:nowrap}
  .ng>summary::-webkit-details-marker{display:none}
  /* 761–1200 px: ONE ROW ON A LAPTOP TOO.
     Above 760 the bar stops scrolling and starts wrapping, and on a 1024-wide screen it needed
     977 px in a 973 px slot — four pixels, and the ⚙ dropped onto a second row under the logo.
     That is the icon the owner circled, and it is not a fault of any one link: at that width the
     bar has no slack at all, so the next label anybody adds tips it again. Six pixels off each
     item's sides buys ~45 px of room and is invisible at a glance. */
  @media (min-width:1001px) and (max-width:1200px){
    nav a{padding-inline:9px}
    nav .ng>summary,nav .gear>summary{padding-inline:9px}
    nav a.brand{margin-inline-end:4px}
  }
  .ng>summary:hover,.ng[open]>summary{background:var(--surface-2);color:var(--ink)}
  .ng>summary.on{color:var(--ink);box-shadow:inset 0 -2px 0 var(--gc)}
  .ng-cur{font-style:normal;font-weight:700;color:var(--gc)}
  /* „there is something in here" — small enough to be noticed, not to nag */
  .ng-dot{width:6px;height:6px;border-radius:50%;background:var(--warn);flex:none;margin-inline-start:-2px}
  .nv-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;
    border-radius:999px;background:var(--crit);color:#fff;font-style:normal;font-size:11px;font-weight:800;line-height:1;
    margin-inline-start:6px;flex:none;letter-spacing:0;cursor:help}
  nav a.on .nv-badge{background:var(--crit)}
  /* THE NUMBER DOES NOT BLINK — THE THING DOES.
     A pulsing badge was tried for half a day and the owner's verdict was immediate: the menu is
     chrome, it must sit still; what has to catch the eye is the task itself, on the page the badge
     points to. So the animation lives here, on a row/card, and every module that feeds a nav badge
     marks the exact rows that badge counted. If the badge says 2, two things on that page pulse —
     tools/verify-badge-target.mjs holds them to it.
     The ring is drawn OUTSIDE the box (box-shadow), so nothing inside moves or reflows. */
  .needs-you{position:relative;animation:needsyou 2.4s ease-in-out infinite}
  @keyframes needsyou{
    0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--crit) 0%,transparent)}
    45%{box-shadow:0 0 0 3px color-mix(in srgb,var(--crit) 34%,transparent)}
  }
  @media (prefers-reduced-motion:reduce){
    /* still marked, just not moving */
    .needs-you{animation:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--crit) 30%,transparent)}
  }

  /* fixed, above the modals (120), untouchable: the page underneath still works */
  .nw-bar,.nw-card{position:fixed;pointer-events:none;opacity:0;transition:opacity .12s ease-out}
  .nw-bar{inset-block-start:0;inset-inline:0;block-size:3px;z-index:130;
    background:color-mix(in srgb,var(--accent) 14%,transparent)}
  .nw-bar>i{display:block;block-size:100%;transform:scaleX(.08);transform-origin:left center;
    background:linear-gradient(90deg,var(--accent),var(--teal));
    box-shadow:0 0 9px color-mix(in srgb,var(--accent) 55%,transparent)}
  .nw-card{inset-block-start:50%;inset-inline-start:50%;transform:translate(-50%,-50%);z-index:129;
    inline-size:min(288px,calc(100vw - 32px));padding:20px 18px 16px;text-align:center;
    background:var(--surface);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow)}
  /* the app's own mark, undistorted; the pulse is two rings leaving it */
  .nw-mark{position:relative;inline-size:44px;block-size:44px;margin:0 auto 10px}
  .nw-mark>svg{display:block;position:relative;z-index:1}
  .nw-mark>i{position:absolute;inset:0;border-radius:50%;border:2px solid var(--accent);opacity:0}
  .nw-say{margin:0;font-size:13.5px;font-weight:560;color:var(--ink-2);overflow-wrap:anywhere}
  /* in the layout from the first frame, visible only at SLOW: the card never grows */
  .nw-note{margin:4px 0 0;font-size:12px;font-weight:500;color:var(--muted);visibility:hidden;
    overflow-wrap:anywhere}
  /* it eases towards the end and never arrives: no moment is promised */
  .nw-b .nw-bar{opacity:1}
  .nw-b .nw-bar>i{animation:nwcreep 28s cubic-bezier(.08,.74,.2,1) forwards}
  .nw-c .nw-card{opacity:1}
  .nw-c .nw-mark>i{animation:nwping 1.9s cubic-bezier(.2,.62,.3,1) infinite}
  .nw-c .nw-mark>i+i{border-color:var(--teal);animation-delay:.95s}
  .nw-s .nw-note{visibility:visible}
  @keyframes nwcreep{0%{transform:scaleX(.08)}10%{transform:scaleX(.44)}38%{transform:scaleX(.72)}100%{transform:scaleX(.94)}}
  @keyframes nwping{0%{transform:scale(.92);opacity:.55}70%{opacity:0}100%{transform:scale(2);opacity:0}}
  @media (prefers-reduced-motion:reduce){
    /* still drawn and still worded, only not moving — the ring rests as a halo */
    .nw-bar,.nw-card{transition:none}
    .nw-b .nw-bar>i{animation:none;transform:scaleX(.42)}
    .nw-c .nw-mark>i{animation:none;opacity:.38;transform:scale(1.5)}
  }

  /* „something moved while you were typing" — only ever shown instead of an auto-refresh, so it
     must be reachable with a thumb and must not cover the field being typed in */
  /* An open nav panel, moved out of the nav (see the toggle handler). Above the gear's sticky
     block (60) and every sticky toolbar in the app (≤40); below the live bar (110) and the
     modals (90/120), which are meant to cover it. */
  .ngmenu.ngm-portal,.gmenu.ngm-portal,.nb-p.ngm-portal{position:fixed;z-index:100;max-height:60vh;overflow-y:auto}
  /* On a phone the panel spans the screen; on a laptop it stands under the summary that opened it,
     and the script writes that offset. Both are portalled now that the bar scrolls at every width —
     an absolutely positioned panel inside an overflow:auto bar is clipped by it. */
  .ngmenu.ngm-portal{min-width:185px}
  .gmenu.ngm-portal{left:auto;right:8px;min-width:190px}
  /* THE BELL PANEL TRAVELS TOO. It was left behind when the bar became a scroller at every width,
     and an absolutely positioned panel inside an overflow:auto box is clipped by it: the owner saw
     the notifications open as a grey sliver stuck under the bar („მენიუ იმალება ლეიერის უკან",
     2026-09-05). Same portal, same anchor as the gear — this panel has always been right-aligned. */
  .nb-p.ngm-portal{left:auto;right:8px;width:330px;max-width:92vw;max-height:min(70vh,520px)}
  @media (max-width:760px){
    .ngmenu.ngm-portal{left:12px;right:12px;min-width:0}
  }
  .livebar{position:fixed;left:50%;transform:translateX(-50%);bottom:18px;z-index:110;display:flex;align-items:center;gap:12px;
    padding:10px 12px 10px 16px;border-radius:999px;background:var(--surface);border:1px solid var(--line);
    box-shadow:0 12px 30px -8px rgba(0,0,0,.5);font-size:13.5px;max-width:calc(100vw - 24px)}
  .livebar button{font:inherit;font-size:13px;font-weight:680;padding:8px 14px;border:none;border-radius:999px;
    background:var(--accent);color:#fff;cursor:pointer;white-space:nowrap}
  .livebar button:hover{opacity:.92}
  .ng-ic{display:inline-flex;align-items:center;color:var(--gc);opacity:.9}
  .ng-ic svg{display:block}
  .ng .chv{width:6px;height:6px;border-inline-end:1.5px solid currentColor;border-block-end:1.5px solid currentColor;
    transform:rotate(45deg);margin-block-start:-3px;opacity:.55}
  .ng[open] .chv{transform:rotate(225deg);margin-block-start:3px}
  .ngmenu{position:absolute;left:0;top:calc(100% + 6px);z-index:50;min-width:185px;background:var(--surface);
    border:1px solid var(--line);border-top:2px solid var(--gc);border-radius:11px;box-shadow:var(--shadow);
    padding:6px;display:flex;flex-direction:column;gap:1px}
  /* A row, not a block: display:block killed the flex gap the bar links use, so the icon sat
     flush against its label. The icon gets a fixed 16px slot rather than only a gap, so every
     label in the panel starts at the same x and the column reads as a list. */
  .ngmenu a{display:grid;grid-template-columns:16px 1fr auto;align-items:center;column-gap:10px;
    padding:9px 12px 9px 11px;border-radius:8px;font-size:13.5px;white-space:nowrap}
  .ngmenu a:not(:has(.nv-ic)){grid-template-columns:1fr auto}
  .ngmenu a:hover{background:var(--surface-2)}
  /* A sentence at the top of this panel was tried on 2026-09-05 and removed the same day: with two
     groups counting, it ran the width of the menu and read as an error message over the links.
     The tooltip keeps the sentence; the PAGE is where the thing itself is marked (.needs-you). */
  .ngmenu a.on{color:var(--gc);font-weight:700;background:color-mix(in srgb,var(--gc) 9%,transparent)}
  @media (max-width:760px){
    /* the nav strip scrolls horizontally — an absolute panel would be clipped,
       so on phones the panel goes fixed under the bar (top set by JS) */
    .ngmenu{position:fixed;left:12px;right:12px;min-width:0;max-height:60vh;overflow-y:auto}
    .ng>summary{padding:7px 10px;font-size:13.5px}
  }
  /* ⚙ menu: rarely-used actions off the main bar */
  /* the theme toggle takes the auto margin; the gear then sits right beside it */
  /* 40px minimum in both axes: at 37×31 the theme toggle was the hardest thing on the bar to
     hit with a thumb, and it sits next to the gear, so a miss opened the wrong menu */
  /* ---- the notification bell (markup lives in notices.mjs; the header owns its own look) ---- */
  .nb{position:relative}
  .nb-s{list-style:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;position:relative;
    width:34px;height:34px;border-radius:10px;color:var(--muted)}
  .nb-s::-webkit-details-marker{display:none}
  .nb-s:hover{background:var(--surface-2);color:var(--ink)}
  .nb-n{position:absolute;top:1px;right:0;min-width:15px;height:15px;padding:0 3px;border-radius:99px;background:var(--crit);
    color:#fff;font-size:9.5px;font-weight:750;font-style:normal;display:flex;align-items:center;justify-content:center}
  .nb-p{position:absolute;top:40px;right:0;width:330px;max-width:92vw;z-index:60;background:var(--surface);
    border:1px solid var(--line);border-radius:13px;box-shadow:var(--shadow);overflow:hidden}
  /* THE PANEL LEAVES THE SCROLLER AT THE SAME WIDTH THE SCROLLER STARTS — and this override has
     to sit AFTER the base rule above, not in the nav media block where it was first written.
     A media query adds NO specificity: same selector, same weight, so the later plain rule wins
     whatever the query says. Written earlier in the sheet it silently lost every time, and the
     panel stayed absolutely positioned inside a bar that had scrolled sideways — laid out off the
     right edge of the window and clipped to the ~45 px nav strip. It rendered, and not one pixel
     of it could be clicked, on every 7–8" tablet in portrait, every phone in landscape and every
     half-width desktop window. Checking that the rule EXISTS is not checking that it applies;
     this one is verified by reading getComputedStyle in a browser at 768 and 900 px. */
  @media (max-width:1000px){
    .nb-p{position:fixed;top:56px;right:8px;left:8px;width:auto}
  }
  .nb-h{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:11px 13px;border-bottom:1px solid var(--line)}
  .nb-all{font-size:11.5px;padding:4px 9px;background:var(--surface-2);border:1px solid var(--line);color:var(--muted)}
  .nb-l{max-height:min(60vh,420px);overflow-y:auto}
  .nb-i{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 10px;padding:10px 13px;text-decoration:none;color:inherit;
    border-bottom:1px solid var(--line)}
  .nb-i:last-child{border-bottom:0}
  .nb-i:hover{background:var(--surface-2)}
  .nb-i.new{border-inline-start:3px solid var(--accent)}
  /* min-width:0 — a 1fr grid track refuses to shrink below its content, so a long body ran off
     the panel and put a horizontal scrollbar on a phone. overflow-wrap breaks the one word that
     cannot fit rather than pushing the whole row. */
  /* nav a{white-space:nowrap} is the header's own rule and the panel lives inside <nav>, so every
     notice was one unwrappable line that scrolled sideways. Matched at equal specificity, later. */
  nav .nb-i,nav .nb-i span{white-space:normal}
  .nb-t,.nb-b{min-width:0;overflow-wrap:anywhere}
  .nb-w{white-space:nowrap}
  /* „4 ახალი" — a thread that spoke several times is ONE row that says how many, not four rows */
  .nb-c{grid-column:1;justify-self:start;font-style:normal;font-size:10.5px;font-weight:700;color:var(--accent);
        border:1px solid var(--accent);border-radius:999px;padding:1px 7px;margin-top:2px}
  .nb-t{font-size:12.5px;font-weight:620;line-height:1.35}
  .nb-i.new .nb-t{font-weight:700}
  /* an unread row whose moment has passed (notices.expires_at): still drawn, never bold, never „new" */
  .nb-i.lapsed .nb-t{font-weight:500;color:var(--muted)}
  .nb-x{color:var(--muted);border-color:var(--line)}
  .nb-b{grid-column:1;font-size:11.5px;color:var(--muted);line-height:1.4}
  .nb-w{grid-row:1;grid-column:2;font-size:10.5px;color:var(--muted);white-space:nowrap}
  .nb-e{padding:16px 13px;margin:0;font-size:12.5px;color:var(--muted)}

  .thbtn{font:inherit;display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:40px;padding:0 10px;border:none;background:none;
    border-radius:8px;color:var(--muted);cursor:pointer;margin-inline-start:auto}
  .thbtn:hover{background:var(--surface-2);color:var(--ink)}
  /* themeSwitch() — the same control on a page instead of in the bar, so it is drawn in the page's
     own chip language (.nb-all / .hseg): surface-2 pill, 1px line, 11.5px label. 34px min height
     is the bell's, which is the smallest thing on this app a thumb is expected to hit. */
  .thsw{font:inherit;font-size:11.5px;font-weight:650;display:inline-flex;align-items:center;gap:7px;
    min-height:34px;padding:0 12px;border:1px solid var(--line);border-radius:10px;background:var(--surface-2);
    color:var(--ink-2);cursor:pointer;flex:none;white-space:nowrap}
  .thsw:hover{border-color:var(--accent);color:var(--ink)}
  .thsw b{font-weight:650}
  /* a page heading with a control parked at its right edge. Lives here rather than in either
     dashboard because both home views draw it and they are rendered by different functions. */
  .hhd{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;margin:0 0 12px}
  .hhd>h1{margin:0}
  /* which icon shows = what pressing it gives you. Base (light): the moon. System-dark with
     no stored choice: the sun. Explicit choices come LAST so they win over the media rule. */
  .th-sun{display:none}
  .th-moon{display:inline-flex}
  @media (prefers-color-scheme:dark){
    :root:not([data-theme="light"]) .th-sun{display:inline-flex}
    :root:not([data-theme="light"]) .th-moon{display:none}
  }
  :root[data-theme="dark"] .th-sun{display:inline-flex}
  :root[data-theme="dark"] .th-moon{display:none}
  :root[data-theme="light"] .th-sun{display:none}
  :root[data-theme="light"] .th-moon{display:inline-flex}
  .gear{position:relative;margin-inline-start:6px}
  /* was the ⚙ glyph; now the drawn gear, so it matches the group headers beside it. inline-flex
     because a bare inline SVG sits on the text baseline and rides ~2px high. */
  .gear>summary{list-style:none;cursor:pointer;padding:7px 11px;border-radius:8px;color:var(--muted);user-select:none;
    display:inline-flex;align-items:center}
  .gear>summary::-webkit-details-marker{display:none}
  .gear>summary:hover,.gear[open]>summary{background:var(--surface-2);color:var(--ink)}
  .gear>summary.on{color:var(--accent)}
  .gmenu{position:absolute;right:0;top:calc(100% + 6px);z-index:50;min-width:190px;background:var(--surface);
    border:1px solid var(--line);border-radius:12px;box-shadow:0 10px 30px -8px rgba(0,0,0,.45);padding:6px;display:flex;flex-direction:column}
  .gwho{font-size:11.5px;color:var(--muted);padding:7px 12px 5px;border-bottom:1px solid var(--line);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* same 16px icon slot and column-gap as .ngmenu — the two panels sit under the same bar and
     must not be two different lists */
  .gmenu a,.gmenu button{font:inherit;font-size:13.5px;text-align:left;text-decoration:none;color:var(--ink-2);background:none;border:none;
    display:grid;grid-template-columns:16px 1fr auto;align-items:center;column-gap:10px;
    padding:9px 12px 9px 11px;min-height:40px;border-radius:8px;cursor:pointer;white-space:nowrap;width:100%}
  .gmenu a:hover,.gmenu button:hover{background:var(--surface-2);color:var(--ink);opacity:1}
  .gmenu a.on{color:var(--accent)}
  .gmenu form{display:contents}
  @media (max-width:760px){
    .gmenu{position:fixed;right:8px;top:52px}
  }
  /* THE ⚙ AND THE 🔔 STAY AT THE RIGHT EDGE WHILE THE BAR SCROLLS — at every width now.
     This lived inside the 760 px query while the bar only scrolled below 760. Since 2026-09-05 it
     scrolls at every width, so between 761 and 1000 px the two controls simply travelled off the
     right edge with the rest of the row and the owner had to scroll the bar to reach settings.
     The z-index is not decoration: position:sticky ALWAYS creates a stacking context, so the
     panel's own z-index:50 only ranks it INSIDE .gear — and .gear itself sat at auto, i.e. level 0
     of the page. Every sticky toolbar further down then painted over the open menu (/courier and
     /shipments at 20, /order's filter bar at 5, /schedule's frozen headers at 3–4; owner report
     2026-08-21). Raising the CONTEXT fixes it on every page at once. */
  .gear{position:sticky;right:0;z-index:60;background:var(--bg);box-shadow:-8px 0 8px -4px var(--bg)}
  .nb{position:sticky;right:44px;z-index:59;background:var(--bg)}
  /* „დააყენე აპი" (installButton) — third in the sticky row: the ⚙ holds right:0, the bell right:44px
     and is 34px wide, so this box ends at 78px.
     WHAT YOU SEE IS THE BELL; WHAT YOU HIT IS 44px. The pill (.iapp-p) is the bell's 34px and radius 10.
     The button around it is transparent and taller, and it must not make the bar taller when it
     appears — the row is 34.9px on a phone and 41px on a laptop, and a 40px box pushed every page
     down 5px on a phone (measured 2026-09-21). So it asks the row for 34px (content 34 + padding-bottom
     10, margin-bottom -10), is then STRETCHED to the row, and its padding-bottom reaches 10px into
     the bar's own bottom padding (10–12px): box = row + 10 = 44.9 / 51px tall, never clipped by the
     scroller because it starts at the row's top and ends inside the padding box.
     [hidden] is restated because display:inline-flex would otherwise beat the UA's display:none and
     the invisible button would still take its seat. The words show only where the bar has room for
     them — INSTALL_JS drops them (.iapp-i) when they would make the bar scroll. Measured on the
     1040px column (2026-09-21): a consultant's bar has ~133px free and gets the words (the labelled
     box is ~128px), a shop login's ~52px and the owner's ~43px get the icon, whose title says it — and
     on the page they land on, the worded strip under the bar instead (installBar, below). */
  .iapp{font:inherit;flex:none;align-self:stretch;display:inline-flex;align-items:center;justify-content:center;
    min-width:44px;padding:0 3px 10px;margin:0 0 -10px;border:0;border-radius:0;background:var(--bg);color:var(--accent);
    cursor:pointer;position:sticky;right:78px;z-index:59;box-shadow:-8px 0 8px -4px var(--bg)}
  .iapp[hidden]{display:none}
  @media (display-mode:standalone){.iapp,.iapp-bar{display:none!important}}
  .iapp:hover{filter:none}
  .iapp-p{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:34px;height:34px;padding:0 10px;
    border:1px solid var(--accent);border-radius:10px;background:var(--accent-soft);font-size:12px;font-weight:650;white-space:nowrap}
  .iapp:hover .iapp-p,.iapp:focus-visible .iapp-p{background:var(--accent);color:#fff}
  .iapp svg{display:block;flex:none}
  .iapp b{font-weight:650}
  .iapp.iapp-i .iapp-p{padding:0}
  .iapp.iapp-i b{display:none}
  /* installBar() — the same offer in words, under the bar on the landing page, when the bar has no
     room for the labelled button (the shop logins' and the owner's never do on a laptop). The bar
     button's colours — accent border on accent-soft — so the two read as one control; the button in it
     is the ordinary filled button at the 44px target. [hidden] restated for the same reason as .iapp.
     Only ever shown at computer width (INSTALL_JS), so it has no phone layout to keep. */
  .iapp-bar{display:flex;align-items:center;gap:12px;padding:8px 8px 8px 14px;border:1px solid var(--accent);
    border-radius:10px;background:var(--accent-soft);color:var(--ink)}
  .iapp-bar[hidden]{display:none}
  .iapp-bi{display:flex;flex:none;color:var(--accent)}
  .iapp-bt{flex:1;min-width:0;font-size:13.5px;line-height:1.4}
  .iapp-bh{font-weight:650}
  .iapp-bs{color:var(--ink-2)}
  .iapp-bar button{flex:none;display:inline-flex;align-items:center;gap:7px;min-height:44px;white-space:nowrap}
  .iapp-bar button svg{display:block;flex:none}
  .iapp-bl{font-weight:650}
  nav a.brand:hover{background:transparent}
  nav a.on{background:var(--accent-soft);color:var(--accent)}
  nav a:hover{background:var(--surface-2)}
  nav form{margin-inline-start:auto}
  h1{margin:0;font-size:clamp(21px,3.5vw,27px);font-weight:650;letter-spacing:-.015em}
  h2{margin:0;font-size:17px;font-weight:620}
  .label{font-size:11.5px;letter-spacing:.1em;color:var(--muted);font-weight:600}
  .hint{margin:0;color:var(--muted);font-size:13.5px;max-width:72ch}
  .card{background:var(--surface);border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow)}
  .pad{padding:16px}
  section{display:flex;flex-direction:column;gap:12px}
  .kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;background:var(--line);
    border:1px solid var(--line);border-radius:10px;overflow:hidden}
  .kpi{background:var(--surface);padding:14px 16px;display:flex;flex-direction:column;gap:3px}
  .kpi .v{font-size:22px;font-weight:640;letter-spacing:-.02em}
  .kpi .d{font-size:12px;color:var(--muted)}
  .kpi .d.up{color:var(--good)} .kpi .d.down{color:var(--crit)}
  .scroll{overflow-x:auto}
  table{border-collapse:collapse;width:100%}
  th,td{padding:9px 12px;text-align:right;border-bottom:1px solid var(--line)}
  th:first-child,td:first-child{text-align:left}
  tbody tr:last-child td{border-bottom:0}
  th{font-size:11.5px;letter-spacing:.07em;font-weight:600;color:var(--muted);white-space:nowrap}
  td{font-size:14px}
  .name{font-weight:560}
  .q{color:var(--muted);font-size:12.5px}
  .pos{color:var(--good);font-weight:600}.neg{color:var(--crit);font-weight:600}
  .chip{display:inline-block;padding:1px 9px;border-radius:999px;font-size:11.5px;font-weight:580;border:1px solid transparent}
  .chip.k-reorder{color:var(--crit);border-color:color-mix(in srgb,var(--crit) 40%,transparent)}
  .chip.k-warehouse{color:var(--warn);border-color:color-mix(in srgb,var(--warn) 45%,transparent)}
  .chip.k-transfer{color:var(--accent);border-color:color-mix(in srgb,var(--accent) 45%,transparent)}
  .chip.done{color:var(--good);border-color:color-mix(in srgb,var(--good) 40%,transparent)}
  button{font:inherit;border:0;border-radius:8px;padding:8px 16px;background:var(--accent);color:#fff;font-weight:580;cursor:pointer}
  button:hover{filter:brightness(1.08)}
  button:active{filter:brightness(.9)} /* after :hover — a pressed mouse is also hovering */
  button.ghost{background:transparent;color:var(--muted);padding:7px 10px;font-size:13px}
  button.ghost:hover{background:var(--surface-2);filter:none}
  button.small{padding:4px 12px;font-size:12.5px}
  input[type=text],input[type=password],input[type=search]{font:inherit;width:100%;padding:9px 12px;border:1px solid var(--line);
    border-radius:8px;background:var(--surface);color:var(--ink)}
  /* 16px on every field, on phones. iOS Safari zooms the whole page when a field with a
     smaller font takes focus, and does not zoom back out — the body is 15px, fields inherit
     it, so every one of the ten inputs on the feedback form did this to a consultant, per
     customer, all day. Desktop keeps the 15px rhythm; the media query is the whole point. */
  @media (max-width:760px){
    /* !important on purpose — this is a browser-behaviour floor, not a design choice, and
       a page's own ".form textarea{font-size:15px}" would otherwise win by specificity */
    input:not([type=checkbox]):not([type=radio]):not([type=hidden]),select,textarea{font-size:16px!important}
    /* A <select> is as wide as its widest <option>, and that width is intrinsic: as a flex item it
       keeps min-width:auto, so nothing in the chain above it can shrink it. On /risk the focus filter
       („ყველაფერი — რისკები, სცენარები, ვალდებულებები") measured 436 px against a 375 px phone and
       hung 88 px off the right edge. Like the 16 px floor above, this is a browser-behaviour floor
       rather than a design choice: a control never gets to be wider than what contains it. */
    input,select,textarea{max-width:100%;min-width:0}
    /* and the wrapper too: a <label> holding that select is itself a flex item, so capping the
       control alone changes nothing while the label still reports the control's intrinsic width
       as its own floor. A label is a caption plus a field; it is never the thing that should
       decide how wide the page is. */
    label{min-width:0}
  }
  input:focus-visible,button:focus-visible,a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .login-wrap{min-height:82vh;display:grid;place-items:center}
  .login{width:min(360px,92vw);display:flex;flex-direction:column;gap:14px}
  .login .rule{height:3px;width:52px;background:linear-gradient(90deg,var(--accent),var(--green));border-radius:2px}
  .err{color:var(--crit);font-size:13.5px;margin:0}
  /* the goodbye after a shift is closed — the same slot as .err, read the opposite way */
  .bye{color:var(--green);font-size:13.5px;font-weight:600;margin:0;text-align:center;line-height:1.5}
  .row-actions{display:flex;gap:6px;justify-content:flex-end}
  /* --- hero: the big "how are we doing" card. Shared by the dashboard,
         analytics and rating so all three read the same way. --- */
  /* One calm surface for „which period" — the shape /sales has used since it was built.
     Its own classes, not .btab: that one is shared by half the app. */
  .hctrl{background:var(--surface);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
    padding:12px 14px;display:flex;flex-direction:column;gap:10px;margin-bottom:16px}
  .hctrl-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  /* .hctrl-sub is gone: „ერთი თვე" now sits with the segments, because „which period" is one
     question and its answers belong together. The card is a single row again. */
  .hsegs{display:inline-flex;background:var(--surface-2);border:1px solid var(--line);border-radius:11px;padding:3px;gap:2px}
  /* an <a> on the home control, a <button> where the switch has to be instant (the /tasks tabs).
     font:inherit first, then the size — the shorthand resets it. */
  .hseg{font:inherit;font-size:13px;font-weight:620;padding:7px 14px;border-radius:8px;text-decoration:none;
    color:var(--muted);white-space:nowrap;background:transparent;border:0;cursor:pointer}
  .hseg:hover{color:var(--ink)}
  .hseg.on{background:var(--surface);color:var(--ink);box-shadow:0 1px 4px rgba(0,0,0,.25)}
  .hrange{display:inline-flex;gap:7px;align-items:center;margin-inline-start:auto;flex-wrap:wrap}
  /* color-scheme is set once on :root (see the token blocks at the top) — it is a document-level
     property and a per-field copy of it is how this bug survived two attempts to fix it.
     two bright boxes floating on a dark card, which is exactly how this row looked. */
  .hdate{font:inherit;font-size:12.5px;padding:7px 10px;border-radius:9px;
    background:var(--surface-2);border:1px solid var(--line);color:var(--ink);font-variant-numeric:tabular-nums}
  .hdate:focus{outline:none;border-color:var(--accent)}
  .hgo{font:inherit;font-size:12.5px;font-weight:640;padding:7px 14px;border-radius:9px;cursor:pointer;
    border:1px solid var(--line);background:var(--surface-2);color:var(--ink-2)}
  .hgo:hover{border-color:var(--accent);color:var(--accent)}
  /* The pill IS the control. Without appearance:none the browser draws its own border, background
     and arrow INSIDE our border, background and arrow — a box in a box, which is what this looked
     like. One frame, one chevron (ours, on the label), and the select is just the text. */
  .hpick{position:relative;display:inline-flex;align-items:center;gap:8px;font-size:11.5px;font-weight:640;
    color:var(--muted);background:var(--surface-2);border:1px solid var(--line);border-radius:11px;
    padding:0 30px 0 13px;block-size:38px;cursor:pointer;letter-spacing:.02em;white-space:nowrap}
  .hpick:hover{border-color:var(--accent)}
  .hpick.on{border-color:var(--accent);color:var(--ink);background:color-mix(in srgb,var(--accent) 12%,var(--surface-2))}
  .hpick select{appearance:none;-webkit-appearance:none;font:inherit;font-size:13px;font-weight:560;
    background:transparent;border:0;color:var(--ink);padding:0;margin:0;cursor:pointer;outline:none}
  .hpick select:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}
  /* our chevron, drawn once, in the pill's own colour */
  .hpick::after{content:'';position:absolute;inset-inline-end:12px;inline-size:8px;block-size:8px;
    border-inline-end:1.6px solid var(--muted);border-block-end:1.6px solid var(--muted);
    transform:translateY(-2px) rotate(45deg);pointer-events:none}
  .hpick:hover::after,.hpick.on::after{border-color:var(--accent)}
  .hpick.on{border-color:var(--accent);color:var(--ink)}
  .hpick input{font:inherit;font-size:12.5px;border:0;background:transparent;color:var(--ink);
    cursor:pointer;font-variant-numeric:tabular-nums}
  .hpick input:focus{outline:none}
  @media (max-width:620px){
    .hrange{margin-inline-start:0;width:100%}
    .hrange .hdate{flex:1;min-width:0}
    .hsegs{width:100%;overflow-x:auto;scrollbar-width:none}
    .hsegs::-webkit-scrollbar{display:none}
    /* 44px is the smallest thing a thumb hits reliably; every control here was 28–31 */
    .hseg{padding:12px 16px}
    .hdate,.hgo{min-block-size:44px}
    .hpick{min-block-size:44px;padding-block:0}
    .hpick select,.hpick input{min-block-size:42px}
  }
  .hero{padding:18px 20px;display:flex;flex-direction:column;gap:14px}
  .hero-top{display:flex;gap:18px;align-items:stretch;justify-content:space-between;flex-wrap:wrap}
  .hero-rev{display:flex;flex-direction:column;gap:4px;min-width:180px;flex:1}
  .hrev{font-size:44px;font-weight:800;letter-spacing:-.03em;line-height:1}
  .hrev i{font-style:normal;font-size:24px;font-weight:600;color:var(--muted)}
  .hverdict{font-size:14px;font-weight:640;margin-top:2px}
  .hb2b{display:block;font-size:11.5px;color:var(--muted);margin-top:5px;line-height:1.45}
  .hm-note{display:block;font-size:10.5px;color:var(--muted);margin-top:3px;line-height:1.4}
  .hero-margin{display:flex;flex-direction:column;gap:2px;justify-content:center;padding:12px 18px;border-radius:14px;min-width:150px;
    background:color-mix(in srgb,var(--mc) 10%,transparent);border:1px solid color-mix(in srgb,var(--mc) 34%,transparent);
    text-decoration:none;color:inherit}
  a.hero-margin:hover{border-color:var(--mc)}
  .hm-pct{font-size:34px;font-weight:800;line-height:1;color:var(--mc);letter-spacing:-.02em}
  .hm-gel{font-size:13px;font-weight:640;color:var(--ink-2)}
  .hband{display:flex;flex-direction:column;gap:5px}
  .hb-track{height:8px;border-radius:99px;background:var(--surface-2);overflow:hidden}
  .hb-fill{display:block;height:100%;border-radius:99px;transition:width .4s}
  .hb-legend{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}
  .hstats{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
  .hstat{display:flex;flex-direction:column;gap:3px;padding:11px 13px;border-radius:12px;background:var(--surface-2);
    border:1px solid transparent;text-decoration:none;color:inherit}
  /* Three of the four home tiles are <div>; the fourth is an <a> to /tasks and carries .act —
     a class that existed in the markup and in no stylesheet. .hstat already reserves
     „border:1px solid transparent" for exactly this state, and nothing ever used it, so the one
     tile you can press looked identical to the three you cannot. */
  .hstat.act{cursor:pointer;transition:border-color .12s,background .12s}
  .hstat.act:hover{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 9%,var(--surface-2))}
  .hstat b{font-size:19px;font-weight:750;line-height:1.1}
  .hs-l{font-size:11px;color:var(--muted)}
  /* the small print under a number whose divisor is not the window the reader picked */
  .hs-n{display:block;font-size:10.5px;color:var(--muted);margin-top:2px;line-height:1.2}
  a.hstat:hover{border-color:var(--accent)}
  a.hstat b{color:var(--accent)}
  .hchips{display:flex;gap:8px;flex-wrap:wrap}
  .hchip{font-size:12.5px;font-weight:640;padding:6px 12px;border-radius:99px;border:1px solid currentColor;text-decoration:none}
  .hchip.good,.hchip.green{color:var(--green)} .hchip.warn,.hchip.amber{color:var(--warn)}
  .hchip.bad,.hchip.red{color:var(--crit)} .hchip.na{color:var(--muted)}
  .hdetails summary{cursor:pointer;font-size:12.5px;color:var(--muted);list-style:none;padding:2px 0}
  .hdetails summary::-webkit-details-marker{display:none}
  .hdetails[open] summary{color:var(--accent)}
  .hdetails p{margin:6px 0 0;line-height:1.55}
  @media (max-width:640px){
    .hero{padding:16px}
    .hrev{font-size:36px}
    .hero-top{gap:12px}
    .hero-margin{flex-direction:row;align-items:baseline;gap:10px;width:100%;padding:10px 14px}
    .hero-margin .label{order:-1}
    .hm-pct{font-size:26px}
    .hm-gel{margin-inline-start:auto;text-align:end}
    /* .tall keeps the column layout — for cards whose caption is a phrase, not a
       short figure, which would otherwise wrap to three cramped lines. */
    .hero-margin.tall{flex-direction:column;align-items:flex-start;gap:3px}
    .hero-margin.tall .hm-gel{margin-inline-start:0;text-align:start}
    .hstats{grid-template-columns:1fr 1fr;gap:8px}
    .hstat{padding:10px 11px}
    .hstat b{font-size:17px}
    .hverdict{font-size:13px}
  }
  @media (max-width:560px){
    table.stack,table.stack tbody,table.stack tr,table.stack td{display:block;width:auto}
    table.stack thead{display:none}
    table.stack tr{border:1px solid var(--line);border-radius:11px;padding:10px 12px;margin-bottom:8px;background:var(--surface-2)}
    /* flex-wrap is the safety net, not decoration. This rule assumes a cell is a label plus one
       value, and with two items wrap never fires — but /payroll's „დღეები" cell holds thirty day
       chips, and thirty flex items on a nowrap line pushed the page to 1070 px on a 375 px phone.
       .card.scroll:has(table.stack) deliberately turns the horizontal scroller off, so there was
       nothing to catch them: the page slid sideways instead. */
    table.stack td{border:0;padding:3px 0;display:flex;align-items:baseline;justify-content:space-between;gap:2px 12px;flex-wrap:wrap;min-width:0;text-align:left}
    table.stack td::before{content:attr(data-l);font-size:10.5px;font-weight:700;letter-spacing:.04em;
      text-transform:uppercase;color:var(--muted);flex:none}
    /* a cell with no heading — the row's name, or the button column — is not a labelled pair */
    table.stack td:not([data-l])::before{content:none}
    table.stack td.name{padding-bottom:7px;margin-bottom:5px;border-bottom:1px solid var(--line);font-size:14px}
    table.stack td.name::before{content:none}
    table.stack td.row-actions{justify-content:flex-end;padding-top:7px}
    /* the row is the card now; the scroller around it has nothing left to scroll */
    .card.scroll:has(table.stack){overflow-x:visible}
  }
  @media (max-width:640px){
    th,td{padding:8px 8px;font-size:13px}
    .page{padding:12px 10px 48px;gap:16px}
    h1{font-size:21px}
    h2{font-size:16px}
    .kpis{grid-template-columns:repeat(2,1fr)!important}
    .kpi .v{font-size:19px!important}
    button{padding:9px 14px}
    /* period picker: centre the tabs + date/range controls on phones */
    .btabs{justify-content:center;width:100%}
    .btabs .btab{justify-content:center;min-block-size:44px}
    /* nothing may push the page sideways on a phone */
    .card.scroll{max-width:100%}
    .bgrid{grid-template-columns:1fr!important}
    .bmeta{font-size:11.5px;line-height:1.5}
  }
  /* long Georgian words must wrap, not overflow, on narrow screens */
  h1,h2,p,td,th,.label,.q{overflow-wrap:anywhere}
