/* ═══════════════════════════════════════════════════════════
   NalyOS — primitive
   Ogni valore viene da tokens.css. Nessun hex qui dentro.

   Regole che questo file fa rispettare, e che valgono per ogni
   pagina migrata:
     · tre strati di elevazione su ogni superficie
     · gradiente sui CONTROLLI, superficie piatta sui CONTENITORI
     · niente backdrop-filter su fixed/sticky (trappola iOS)
     · tabular-nums su ogni cifra
   ═══════════════════════════════════════════════════════════ */

/* ── Contenitori ──────────────────────────────────────────── */
.naly-shell {
  /* NalyOS secondary copy still needs to clear the locked --ink-4 floor.
     Alias through --text-2 so the dark-theme value remains theme-aware. */
  --text-3: var(--text-2);
}

.naly-card,
.naly-tile {
  position: relative;
  overflow: hidden;
  background: var(--naly-surface);
  border: 1px solid var(--naly-surface-border);
}
.naly-card { border-radius: var(--naly-r-card); box-shadow: var(--naly-elev-2); }
.naly-tile { border-radius: var(--naly-r-tile); box-shadow: var(--naly-elev-1); }

/* Binario d'accento in cima alla card principale */
.naly-rail {
  height: 4px;
  background: linear-gradient(90deg, var(--acc), var(--acc) 70%, var(--margherita) 100%);
}

.naly-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-soft);
}
.naly-card__title { font-size: var(--font-size-sm); font-weight: 800; color: var(--text-1); }
.naly-card__sub   { font-size: var(--font-size-xs); font-weight: 600; color: var(--text-3); }

/* ── Controlli — gradiente + bordo 1.5px ─────────────────── */
.naly-control,
.naly-count,
.naly-seg,
.naly-iconbtn {
  background: var(--naly-control-bg);
  border: var(--naly-control-bw) solid var(--naly-control-border);
  box-shadow: var(--naly-control-shadow);
  color: var(--text-1);
}
.naly-control  { border-radius: var(--naly-r-control); padding: 10px 12px; display: flex; align-items: center; gap: var(--space-2); }
.naly-iconbtn  { border-radius: var(--naly-r-icon); width: var(--tap); height: var(--tap); display: flex; align-items: center; justify-content: center; }
.naly-count    { border-radius: 9px; min-width: 29px; padding: 5px 8px; text-align: center;
                 font-size: var(--font-size-sm); font-weight: 800; font-variant-numeric: tabular-nums; }

/* Segmented — Week / Day */
.naly-seg { display: inline-flex; border-radius: var(--naly-r-control); padding: 2px; }
.naly-seg button {
  border: 0; background: none; font: inherit;
  font-size: var(--font-size-xs); font-weight: 800;
  padding: 5px 11px; border-radius: 9px; cursor: pointer;
  color: var(--text-3); min-height: 32px;
}
.naly-seg button[aria-pressed="true"] { background: var(--acc); color: var(--acc-on); }

/* ── CTA primaria ────────────────────────────────────────── */
.naly-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: var(--tap); padding: 0 17px;
  border: 0; border-radius: var(--naly-r-control);
  background: var(--naly-cta-bg); box-shadow: var(--naly-cta-shadow);
  color: var(--ink-10); font: inherit; font-size: var(--font-size-base); font-weight: 800;
  cursor: pointer; white-space: nowrap; text-decoration: none;
}

/* FAB — sta SOPRA la chrome fissa, non dentro */
.naly-fab {
  position: fixed; right: 14px; z-index: 14;
  bottom: calc(var(--naly-safe-bottom) - 16px + env(safe-area-inset-bottom, 0px));
}

/* ── Chrome fissa — nessun blur, mai ─────────────────────── */
.naly-chrome {
  background: var(--naly-chrome-bg);
  border: 1px solid var(--naly-chrome-border);
  box-shadow: var(--naly-elev-3);
  /* backdrop-filter deliberatamente assente: vedi tokens.css */
}
.naly-topbar { border-radius: 18px; display: flex; align-items: center; gap: 9px; padding: 10px 11px; }
.naly-tabbar {
  position: fixed; left: 12px; right: 12px; z-index: 12;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  border-radius: 19px; padding: var(--space-2);
  display: flex; align-items: center; justify-content: space-around;
}
.naly-tab {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  min-width: 54px; min-height: var(--tap); justify-content: center;
  padding: 4px 12px; border-radius: var(--naly-r-control);
  background: transparent; border: 0; appearance: none;
  color: var(--text-1); font: inherit; font-size: 8.5px; font-weight: 700; text-decoration: none;
}
.naly-tab[aria-current="page"] { background: var(--nav-active-bg); color: var(--nav-active-text); }
.naly-tab svg { width: 17px; height: 17px; }
.naly-tab-badge {
  position: absolute; top: 1px; right: 6px;
  min-width: 14px; height: 14px; padding: 0 3px; border-radius: var(--naly-r-pill);
  background: var(--red); color: #fff; font-size: 8px; font-weight: 800;
  font-variant-numeric: tabular-nums; display: flex; align-items: center; justify-content: center;
}
.naly-tab { position: relative; }

/* ── Shared chrome — desktop sidebar + mobile topbar/drawer ──────────
   Reference: 06-dashboard-mobile.html (mockup), .naly-shell gates
   these on the body — the existing sidebar/topbar keep working
   everywhere this class is absent. ─────────────────────────────────── */

/* Desktop sidebar — graphite → near-black, active item is the margherita
   pill (--nav-active-bg / --nav-active-text, already defined). Flat, not
   glass: chrome is a fixed surface, per the elevation rule. */
.naly-sidebar {
  position: fixed; top: 0; left: 0; bottom: 0;
  width: var(--sidebar-w);
  background: linear-gradient(180deg, var(--ink-1), var(--ink-0));
  display: flex; flex-direction: column;
  z-index: 200; overflow-y: auto; overflow-x: hidden; scrollbar-width: none;
  color: var(--text-on-dark);
}
.naly-sidebar::-webkit-scrollbar { display: none; }
.naly-sidebar__brand {
  display: flex; align-items: center; gap: 10px;
  padding: var(--space-4) var(--space-3) var(--space-3);
  text-decoration: none; color: inherit; flex-shrink: 0;
}
.naly-sidebar__mark {
  width: 30px; height: 30px; border-radius: var(--naly-r-icon); flex-shrink: 0;
  background: var(--margherita); color: var(--ink-1);
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 800;
}
.naly-sidebar__name { font-size: 15px; font-weight: 800; }

.naly-sidebar__user {
  display: flex; align-items: center; gap: 9px;
  margin: 0 var(--space-3) var(--space-3);
  padding: 9px 8px; border-radius: var(--naly-r-control);
  background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.09);
}
.naly-sidebar__avatar {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 11.5px; font-weight: 800; color: #fff;
  background: linear-gradient(150deg, #2A5298, var(--acc));
}
.naly-sidebar__avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.naly-sidebar__uname { font-size: 12px; font-weight: 700; line-height: 1.2; }
.naly-sidebar__urole { font-size: 9.5px; font-weight: 600; color: rgba(255,255,255,0.45); }

.naly-sidebar__nav { flex: 1; display: flex; flex-direction: column; padding: 0 var(--space-2) var(--space-3); }
.naly-sidebar__section {
  font-size: 8.5px; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase;
  color: rgba(255,255,255,0.34); padding: 12px 9px 6px;
}
.naly-sidebar__item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 9px; border-radius: var(--naly-r-control);
  font-size: 12.5px; font-weight: 700; color: rgba(255,255,255,0.72);
  text-decoration: none;
}
.naly-sidebar__item svg { width: 15px; height: 15px; flex-shrink: 0; }
.naly-sidebar__item[aria-current="page"] {
  background: var(--nav-active-bg); color: var(--nav-active-text);
  box-shadow: 0 4px 14px -4px rgba(248,192,38,0.5);
}
.naly-sidebar__badge {
  margin-left: auto; min-width: 18px; text-align: center; padding: 1px 5px;
  border-radius: var(--naly-r-pill); background: var(--red); color: #fff;
  font-size: 9px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.naly-sidebar__divider { height: 1px; background: rgba(255,255,255,0.08); margin: 11px 9px; }
.naly-sidebar__foot { margin-top: auto; padding: 0 var(--space-2) var(--space-3); }

/* Mobile topbar wrapper — floats the .naly-chrome + .naly-topbar pill
   just below the notch/safe-area. Sticky ⇒ opaque, no blur (see tokens.css). */
.naly-topbar-wrap { position: sticky; top: 0; z-index: 20; padding: var(--space-3) var(--space-3) 0; }
.naly-burger, .naly-bell {
  width: 34px; height: 34px; border-radius: var(--naly-r-icon); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--naly-control-bg); border: var(--naly-control-bw) solid var(--naly-control-border);
  box-shadow: var(--naly-control-shadow); color: var(--text-2);
}
.naly-burger svg, .naly-bell svg { width: 16px; height: 16px; }
.naly-topbar__title-wrap { flex: 1; min-width: 0; }
.naly-topbar__title { font-size: 15px; font-weight: 800; letter-spacing: -0.01em; color: var(--text-1); }
.naly-topbar__subtitle { font-size: 10px; font-weight: 600; color: var(--text-3); }
.naly-bell { position: relative; }
.naly-bell__badge {
  position: absolute; top: -5px; right: -5px; width: 16px; height: 16px; border-radius: 50%;
  font-size: 9px; font-weight: 800; display: flex; align-items: center; justify-content: center;
  color: #fff; background: var(--red); box-shadow: 0 0 0 2.5px var(--bg-page);
}
.naly-avatar {
  width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; font-weight: 800; color: #fff; text-decoration: none;
  background: linear-gradient(150deg, #2A5298, var(--acc));
  box-shadow: 0 0 0 2px var(--bg-page), 0 2px 7px rgba(30,58,110,0.35);
}
.naly-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Mobile drawer (opened by the burger) — scrim + sliding panel. Panel
   reuses the sidebar's graphite gradient and item markup so nav data
   stays defined once in the partial, not duplicated in CSS. Overlay ⇒
   glass is allowed here (see the @supports block below), scrim stays a
   flat tint so it never competes with the panel for legibility. */
.naly-scrim {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(5,7,12,0.5);
  opacity: 0; pointer-events: none;
  transition: opacity 200ms ease;
}
.naly-scrim.is-open { opacity: 1; pointer-events: auto; }

.naly-drawer {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: 301;
  width: min(264px, 84vw);
  background: linear-gradient(180deg, var(--ink-1), var(--ink-0));
  display: flex; flex-direction: column;
  padding: calc(env(safe-area-inset-top, 0px) + var(--space-4)) var(--space-2) var(--space-4);
  box-shadow: 6px 0 34px rgba(0,0,0,0.5);
  color: var(--text-on-dark);
  transform: translateX(-100%);
  transition: transform 220ms ease;
}
.naly-drawer.is-open { transform: translateX(0); }

/* The drawer is a fixed, viewport-tall flex column and .naly-sidebar__foot is
   pushed to its end by margin-top:auto. With enough destinations the nav grows
   past the bottom edge and takes the foot with it, and nothing scrolls:
   measured on a 390x780 phone, scrollHeight 837 against clientHeight 780, so
   the last 57px — Settings and Logout — were simply unreachable. There was no
   way to log out from a phone on any page that uses this rail.

   The nav takes the leftover height and scrolls; brand, user and foot stay put,
   so Logout is always one tap away instead of depending on list length. */
.naly-drawer .naly-sidebar__nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.naly-drawer .naly-sidebar__foot {
  flex-shrink: 0;
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + var(--space-3));
}
/* Panel content reuses .naly-sidebar__* class names so markup is identical
   to the desktop sidebar — only the outer wrapper differs. */

/* ── Vetro — solo overlay ────────────────────────────────── */
@supports (backdrop-filter: blur(1px)) {
  .naly-sheet, .naly-modal, .naly-drawer {
    backdrop-filter: var(--naly-glass);
    -webkit-backdrop-filter: var(--naly-glass);
  }
}

/* ── Cifre ───────────────────────────────────────────────── */
.naly-num, .naly-metric, .naly-count { font-variant-numeric: tabular-nums; }
.naly-metric { font-size: 30px; font-weight: 800; letter-spacing: -0.025em; line-height: 1.05; color: var(--text-1); }
.naly-metric--sm { font-size: 22px; letter-spacing: -0.02em; }
.naly-label { font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); }

/* Delta positivo / negativo */
.naly-delta {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 3px 7px; border-radius: var(--naly-r-pill);
  font-size: var(--font-size-xs); font-weight: 800; font-variant-numeric: tabular-nums;
}
.naly-delta--up   { background: var(--success-bg); color: var(--success); }
.naly-delta--down { background: var(--danger-bg);  color: var(--danger); }

/* ── Status badge — Orders/Invoices row status pill ──────────
   Same tint-chip shape as .naly-delta, semantic colour set by
   modifier. Tokens only (--success/--warning/--danger/--info +
   their *-bg pairs, already defined in tokens.css) — no new hex. */
.naly-status-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--naly-r-pill);
  font-size: var(--font-size-xs); font-weight: 800; white-space: nowrap;
}
.naly-status-badge .dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.naly-status-badge--success { background: var(--success-bg); color: var(--emerald); }
.naly-status-badge--success .dot { background: var(--emerald); }
.naly-status-badge--warning { background: var(--warning-bg); color: var(--warning); }
.naly-status-badge--warning .dot { background: var(--warning); animation: nalyPulse 1.9s ease-in-out infinite; }
.naly-status-badge--danger  { background: var(--danger-bg);  color: var(--danger); }
.naly-status-badge--danger .dot { background: var(--danger); }
.naly-status-badge--info    { background: var(--info-bg, var(--surface-soft)); color: var(--info, var(--text-2)); }
.naly-status-badge--info .dot { background: var(--info, var(--text-3)); }
.naly-status-badge--neutral { background: var(--surface-soft); color: var(--text-3); }
.naly-status-badge--neutral .dot { background: var(--text-3); }
@keyframes nalyPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(180,83,9,0.28); } 50% { box-shadow: 0 0 0 4px rgba(180,83,9,0); } }
@media (prefers-reduced-motion: reduce) { .naly-status-badge--warning .dot { animation: none; } }

/* ── Row amount + chevron — right-aligned trailing cluster for
   .naly-row list items (Orders/Invoices). Amount always tabular. ── */
.naly-row__amount {
  flex-shrink: 0; text-align: right; font-size: var(--font-size-sm); font-weight: 800;
  color: var(--text-1); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.naly-row__chev { flex-shrink: 0; width: 14px; height: 14px; color: var(--text-3); }

/* ── Chart ───────────────────────────────────────────────── */
/* Scala UNIFORME: niente preserveAspectRatio="none", che deforma
   lo spessore del tratto e trasforma i punti in ellissi. */
.naly-chart { display: block; width: 100%; height: auto; overflow: visible; }
.naly-chart .grid    { stroke: var(--border-soft); stroke-width: 1; }
.naly-chart .ln      { fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.naly-chart .dot     { stroke: var(--bg-card); stroke-width: 2; }
.naly-chart .nowline { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 3; }
.naly-chart .tick    { font-size: 8px;  font-weight: 600; fill: var(--text-3); }
.naly-chart .day     { font-size: 9px;  font-weight: 700; fill: var(--text-3); }
.naly-chart .day--now{ font-weight: 800; fill: var(--text-1); }

.naly-legend { display: grid; grid-template-columns: 1fr 1fr; gap: 7px var(--space-3);
               padding-top: var(--space-3); border-top: 1px solid var(--border-soft); }
.naly-legend__item { display: flex; align-items: center; gap: 7px; min-width: 0; }
.naly-legend__dot  { width: 9px; height: 9px; border-radius: 3px; flex-shrink: 0; }
.naly-legend__name { flex: 1; min-width: 0; font-size: var(--font-size-xs); font-weight: 600; color: var(--text-2);
                     overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.naly-legend__val  { font-size: var(--font-size-xs); font-weight: 800; font-variant-numeric: tabular-nums; color: var(--text-1); }

/* ── Layout pagina ───────────────────────────────────────── */
.naly-page {
  width: 100%; min-height: 100vh;
  background:
    radial-gradient(700px 500px at 15% -8%, var(--margherita-soft), transparent 55%),
    radial-gradient(600px 460px at 100% 10%, var(--acc-glow-lt), transparent 55%),
    var(--bg-page);
}
.naly-content {
  width: 100%;
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-3) var(--space-3)
           calc(var(--naly-safe-bottom-fab) + env(safe-area-inset-bottom, 0px));
}
.naly-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }

/* ── Righe elenco ────────────────────────────────────────── */
.naly-row { display: flex; align-items: center; gap: var(--space-3); padding: 10px var(--space-4);
            border-bottom: 1px solid var(--border-soft); text-decoration: none; color: inherit;
            min-height: var(--tap); }
.naly-row:last-child { border-bottom: none; }
.naly-row__icon { width: 32px; height: 32px; border-radius: var(--naly-r-icon); flex-shrink: 0;
                  display: flex; align-items: center; justify-content: center; }
.naly-row__body { flex: 1; min-width: 0; }
.naly-row__name { font-size: var(--font-size-sm); font-weight: 700; color: var(--text-1); }
.naly-row__meta { font-size: var(--font-size-xs); font-weight: 500; color: var(--text-3); }

/* ── Desktop ─────────────────────────────────────────────── */
@media (min-width: 1025px) {
  .naly-content {
    padding: var(--space-5) var(--space-6) var(--space-8); gap: var(--space-4);
    max-width: 1180px; margin: 0 auto;
  }
  .naly-tabbar, .naly-fab { display: none; }
  .naly-grid-2 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .naly-metric { font-size: 34px; }
  /* The rule above outranks .naly-metric--sm (later in source, same
     specificity), which flattens the sales pair into two identical 34px
     figures. Scoped here rather than on .naly-metric--sm itself, so the KPI
     tiles on Orders and Invoices keep the size they ship with today. */
  .naly-sales__pair .naly-metric--sm { font-size: 25px; }
}

@media (prefers-reduced-motion: reduce) {
  .naly-cta, .naly-tab, .naly-control { transition: none; }
  .naly-drawer, .naly-scrim { transition: none; }
}

/* ── Dashboard — hero shift banner, sales card, KPI grid, priorities ──
   Reference: 06-dashboard-mobile.html. Containers get elevation/radius
   once (.naly-card / .naly-tile already do); these only add the
   dashboard-specific layout + colour bits naly.css didn't have yet. ── */

/* "Your shift today" banner — margherita tint, own surface per the
   elevation rule (not stacked on another card). */
.naly-shift {
  display: flex; align-items: center; gap: var(--space-3);
  border-radius: var(--naly-r-tile); padding: 11px 13px;
  background: linear-gradient(100deg, var(--margherita-soft), transparent 120%);
  border: 1px solid rgba(248,192,38,0.34);
  box-shadow: var(--naly-elev-1);
  text-decoration: none; color: inherit;
}
.naly-shift__icon {
  width: 32px; height: 32px; border-radius: var(--naly-r-icon); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--margherita); color: var(--ink-1);
}
.naly-shift__icon svg { width: 16px; height: 16px; }
.naly-shift__body { flex: 1; min-width: 0; }
.naly-shift__label { font-size: 9px; font-weight: 800; text-transform: uppercase;
                      letter-spacing: 0.06em; color: var(--warning); }
.naly-shift__value { font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums;
                      color: var(--text-1); margin-top: 1px; }
.naly-shift__meta  { display: inline-flex; align-items: center; gap: 4px;
                      font-size: 10.5px; font-weight: 600; color: var(--text-3); margin-top: 1px; }
.naly-shift__meta .dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.naly-shift__chev  { width: 22px; height: 22px; border-radius: 7px; flex-shrink: 0;
                      display: flex; align-items: center; justify-content: center;
                      background: rgba(15,17,21,0.06); color: var(--text-3); }
.naly-shift__chev svg { width: 9px; height: 9px; }

/* Sales hero card — accent rail like .naly-rail, body + segmented + chart. */
.naly-sales__body { padding: 14px 15px 13px; }
.naly-sales__top  { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.naly-sales__row  { display: flex; align-items: baseline; gap: 9px; margin-top: 3px; }
.naly-sales__sub  { font-size: var(--font-size-xs); font-weight: 500; color: var(--text-3); margin-top: 4px; }
/* Yesterday + week-to-date sit side by side and wrap on a narrow phone rather
   than shrinking: two truncated money figures are worse than two stacked ones. */
.naly-sales__pair { display: flex; flex-wrap: wrap; gap: 6px var(--space-5); margin-top: 6px; }
.naly-sales__fig  { min-width: 0; }
.naly-sales__figlabel { font-size: 9px; font-weight: 800; text-transform: uppercase;
                        letter-spacing: 0.06em; color: var(--text-3); }

/* Day/Week switch above the chart — caption on the left, segmented on the right. */
.naly-chart-switch__head { display: flex; align-items: center; justify-content: space-between;
                            gap: var(--space-3); margin: 12px 0 2px; }
.naly-chart-switch__cap  { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.naly-chart-switch [data-naly-chart-pane][hidden] { display: none; }

/* KPI 2×2 grid — cells reuse .naly-tile, this only lays them out + the
   icon/label/value stack inside each one. */
.naly-kpi-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
/* .naly-tile is a bare surface primitive with no padding of its own, and it
   clips (overflow:hidden) — so KPI content needs its own inset or the label
   and footnote get cut off at the edge. */
.naly-kpi-grid .naly-tile,
.naly-d-kpis .naly-tile {
  padding: 13px 14px; min-width: 0;
  border-top: 3px solid var(--border-soft);
}
.naly-kpi-grid .naly-tile--fc, .naly-d-kpis .naly-tile--fc { border-top-color: var(--warning); }
.naly-kpi-grid .naly-tile--or, .naly-d-kpis .naly-tile--or { border-top-color: var(--gloc-blue); }
.naly-kpi-grid .naly-tile--lb, .naly-d-kpis .naly-tile--lb { border-top-color: var(--acc); }
.naly-kpi-grid .naly-tile--iv, .naly-d-kpis .naly-tile--iv { border-top-color: var(--danger); }
/* Labels and footnotes must be free to wrap: at four columns "need products
   mapped" and "Data unavailable" overflowed their tile and were clipped. */
.naly-kpi__head { display: flex; align-items: center; gap: 6px; min-width: 0; }
.naly-kpi__head .naly-label { min-width: 0; overflow-wrap: anywhere; }
.naly-kpi__foot { overflow-wrap: anywhere; }
.naly-kpi__icon { width: 21px; height: 21px; border-radius: 7px; flex-shrink: 0;
                  display: flex; align-items: center; justify-content: center; }
.naly-kpi__icon svg { width: 11px; height: 11px; }
.naly-kpi__icon--fc { background: rgba(248,192,38,0.18); color: var(--warning); }
.naly-kpi__icon--or { background: rgba(66,133,244,0.13); color: var(--gloc-blue); }
.naly-kpi__icon--lb { background: rgba(30,58,110,0.11); color: var(--acc); }
.naly-kpi__icon--iv { background: rgba(214,59,59,0.12); color: var(--danger); }
.naly-kpi__val  { font-size: 22px; font-weight: 800; letter-spacing: -0.02em;
                   font-variant-numeric: tabular-nums; margin-top: 6px; color: var(--text-1); }
.naly-kpi__foot { font-size: 9.5px; font-weight: 600; color: var(--text-3); margin-top: 2px; }
.naly-kpi__foot--warn { color: var(--warning); }
.naly-kpi__foot--bad  { color: var(--danger); }

/* Priorities panel — head + rows, reuses .naly-card for the container. */
.naly-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 15px; border-bottom: 1px solid var(--border-soft);
}
.naly-panel__title { font-size: 12.5px; font-weight: 800; color: var(--text-1); }
.naly-panel__sub   { font-size: 10.5px; font-weight: 600; color: var(--text-3); }
.naly-prow, .product-line {
  display: flex; align-items: center; gap: 11px; padding: 10px 15px;
  border-bottom: 1px solid var(--border-soft); text-decoration: none; color: inherit;
  min-height: var(--tap);
}
.naly-prow:last-child, .product-line:last-child { border-bottom: none; }
.naly-prow__icon { width: 32px; height: 32px; border-radius: var(--naly-r-icon); flex-shrink: 0;
                    display: flex; align-items: center; justify-content: center; }
.naly-prow__icon svg { width: 14px; height: 14px; }
.naly-prow__icon--warn { background: rgba(248,192,38,0.18); color: var(--warning); }
.naly-prow__icon--bad  { background: rgba(214,59,59,0.12); color: var(--danger); }
.naly-prow__icon--info { background: rgba(66,133,244,0.12); color: var(--gloc-blue); }
.naly-prow__info { flex: 1; min-width: 0; }
.naly-prow__name { font-size: 12.5px; font-weight: 700; color: var(--text-1); }
.naly-prow__meta { font-size: 10.5px; font-weight: 600; color: var(--ink-3); }
[data-theme="dark"] .naly-prow__meta { color: var(--text-2); }
.naly-prow__empty { padding: 20px 15px; text-align: center; font-size: var(--font-size-sm);
                     font-weight: 600; color: var(--text-3); }

/* Dashboard "New order" FAB — .naly-fab only provides fixed positioning;
   compose it with .naly-cta in markup for the emerald gradient/shadow/shape
   (the mockup's rounded-rect FAB with text label, not a bare icon circle). */

/* ── Chrome breakpoint — sidebar (desktop) vs topbar/drawer/tabbar
   (mobile). Same 1024px chrome breakpoint the foundation already uses
   (tokens.css comment: "1024px chrome (sidebar→drawer)"). Only takes
   effect under body.naly-shell, so pages that haven't opted in are
   untouched. ───────────────────────────────────────────────────── */
.naly-shell .naly-sidebar { display: none; }
.naly-shell .naly-topbar-wrap,
.naly-shell .naly-scrim { display: block; }
/* The drawer is listed apart because it must stay a flex column. This block is
   about visibility, but `display` also carries layout: grouping the drawer with
   the others gave it `block` at 0,2,0, which outranked its own `display: flex`
   at 0,1,0 and silently flattened it. Its `flex: 1` nav and `margin-top: auto`
   foot then did nothing, which is why the footer fell off the bottom. */
.naly-shell .naly-drawer { display: flex; }
.naly-shell .naly-tabbar { display: flex; }

@media (min-width: 1025px) {
  .naly-shell .naly-sidebar { display: flex; }
  .naly-shell .naly-topbar-wrap,
  .naly-shell .naly-scrim,
  .naly-shell .naly-drawer,
  .naly-shell .naly-tabbar { display: none; }
  /* .naly-shell-main lives inside <main class="dash-main">, already the
     second column of .dash-root's grid-template-columns: var(--sidebar-w) 1fr
     (chrome.css:676). An extra margin-left here double-offsets the content —
     found by rendering the real dashboard, not just reading the CSS. */
}

/* ═══════════════════════════════════════════════════════════
   NalyOS — New Order primitives
   Reference: docs/superpowers/specs/assets/2026-08-05-macos-redesign/
     04-neworder-mobile-v4-BASELINE.html (mobile, the corrected v4)
     03-neworder-desktop-mobile.html     (desktop half only)

   Config card is the one deliberate exception to "containers are
   flat": it is a navy→yellow gradient block (its own colour
   signature, matches the mockup's config-card), not .naly-card.
   The two select fields inside it ARE controls — gradient + 1.5px
   border, same rule as quantity controls (corrected per user review,
   see the design-language spec's "Explicitly rejected" section).
   ═══════════════════════════════════════════════════════════ */

/* ── Config card — supplier / location / total ──────────────── */
.naly-config{
  position: relative; overflow: hidden; border-radius: var(--naly-r-card);
  background: linear-gradient(135deg, var(--acc), var(--acc-hover, var(--acc)));
  box-shadow: 0 14px 34px -14px rgba(20,42,82,0.45), inset 0 1px 0 rgba(255,255,255,0.08);
}
.naly-config::before{
  content: ""; position: absolute; top: -40%; right: -10%;
  width: 220px; height: 220px; border-radius: 50%;
  background: radial-gradient(circle, rgba(248,192,38,0.16), transparent 70%);
  pointer-events: none;
}
.naly-config__rail{ height: 4px; background: linear-gradient(90deg, var(--margherita), var(--margherita) 30%, transparent 100%); }
.naly-config__body{ position: relative; z-index: 1; padding: var(--space-4) var(--space-4) var(--space-3); display: flex; flex-direction: column; gap: 10px; }

/* the supplier/location field — its own raised control surface inside
   the navy card. Gradient + 1.5px border: the corrected rule. */
.naly-cfg-select{
  position: relative;
  display: flex; align-items: center; gap: 10px;
  border-radius: var(--naly-r-control); padding: 10px 12px 10px 11px;
  background: var(--naly-control-bg);
  border: var(--naly-control-bw) solid var(--naly-control-border);
  box-shadow: var(--naly-control-shadow);
  cursor: pointer;
}
.naly-cfg-select select{
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; margin: 0; padding: 0; cursor: pointer;
}
.naly-cfg-icon{
  width: 28px; height: 28px; border-radius: 9px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.naly-cfg-icon svg{ width: 13.5px; height: 13.5px; }
.naly-cfg-icon--sup{ background: rgba(30,58,110,0.10); color: var(--acc); }
.naly-cfg-icon--loc{ background: rgba(248,192,38,0.16); color: #B4790E; }
.naly-cfg-text{ flex: 1; min-width: 0; }
.naly-cfg-label{ font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); }
.naly-cfg-value{ font-size: 13px; font-weight: 700; margin-top: 1px; color: var(--text-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.naly-cfg-sub{ font-size: 10px; font-weight: 500; margin-top: 1px; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.naly-cfg-chevwell{
  width: 24px; height: 24px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15,17,21,0.045); color: var(--text-3);
}
.naly-cfg-chevwell svg{ width: 10px; height: 10px; }
.naly-cfg-err{
  display: none; font-size: 10.5px; font-weight: 700; color: #FFD1D1;
  margin-top: -4px;
}
.naly-cfg-select.is-invalid{ border-color: var(--danger); }
.naly-cfg-select.is-invalid ~ .naly-cfg-err,
.naly-cfg-err.is-visible{ display: block; }

.naly-config__total{
  position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px var(--space-4);
  background: linear-gradient(90deg, rgba(255,255,255,0.06), rgba(248,192,38,0.08));
  border-top: 1px solid rgba(255,255,255,0.14);
}
.naly-config__total-lbl{ font-size: 10.5px; font-weight: 700; color: rgba(255,255,255,0.78); }
.naly-config__total-val{ font-size: 19px; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; color: #fff; }
.naly-config__total-val:is(.empty, .is-empty){ color: rgba(255,255,255,0.55); }

/* `dash-main` centres its flex children.  Without an explicit inline size,
   New Order's form shrink-wraps on a phone until a selected label happens to
   make it wider.  Reserve the available page width from the first paint. */
.naly-shell .dash-main > #orderForm{
  width: min(100%, 1180px);
  min-width: 0;
}

/* ── Supplier chip row ───────────────────────────────────────── */
.naly-chip-row{ display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 2px; }
.naly-chip{
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 6px;
  border-radius: var(--naly-r-pill); padding: 8px 14px;
  font: inherit; font-size: 11.5px; font-weight: 700; white-space: nowrap;
  background: var(--naly-surface); border: 1px solid var(--naly-surface-border);
  box-shadow: var(--naly-elev-1); color: var(--text-2); cursor: pointer;
}
.naly-chip .dot{ width: 6px; height: 6px; border-radius: 50%; background: var(--text-3); flex-shrink: 0; }
.naly-chip.is-active{ background: linear-gradient(150deg, var(--acc), var(--ink-1)); border-color: transparent; color: #fff; box-shadow: 0 8px 18px -6px rgba(20,42,82,0.5); }
.naly-chip.is-active .dot{ background: var(--margherita); box-shadow: 0 0 6px rgba(248,192,38,0.6); }

/* ── Product panel rows ──────────────────────────────────────── */
.naly-panel__head{ display: flex; align-items: center; justify-content: space-between; padding: 13px var(--space-4); border-bottom: 1px solid var(--border-soft); }
.naly-panel__title{ font-size: 12.5px; font-weight: 800; color: var(--text-1); }
.naly-panel__sub{ font-size: 10.5px; font-weight: 600; color: var(--text-3); }
.naly-hint{ padding: 28px 16px; text-align: center; color: var(--text-3); font-size: 13px; }

.naly-order-split :is(.naly-prow, .product-line){
  display: flex; align-items: center; gap: 11px; padding: 11px var(--space-4);
  border-bottom: 1px solid var(--border-soft); position: relative;
}
.naly-order-split :is(.naly-prow, .product-line):last-child{ border-bottom: 0; }
.naly-order-split :is(.naly-prow, .product-line).in-cart{ background: linear-gradient(90deg, var(--success-bg), transparent); }
.naly-p-icon{
  width: 34px; height: 34px; border-radius: var(--naly-r-icon); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(66,133,244,0.12); color: #4285F4;
}
.naly-p-icon svg{ width: 15px; height: 15px; }
.naly-p-info{ flex: 1; min-width: 0; }
.naly-p-name{ font-size: 13px; font-weight: 700; color: var(--text-1); }
.naly-p-meta{ font-size: 11px; font-weight: 500; color: var(--text-3); }

/* Quantity stepper — gradient + 1.5px border, same control rule. */
.naly-qty-ctrl{
  display: flex; align-items: center; border-radius: 10px; overflow: hidden; flex-shrink: 0;
  background: var(--naly-control-bg); border: var(--naly-control-bw) solid var(--naly-control-border);
  box-shadow: var(--naly-control-shadow);
}
.naly-order-split :is(.naly-prow, .product-line).in-cart .naly-qty-ctrl{ border-color: var(--success); box-shadow: 0 2px 8px rgba(30,138,76,0.2); }
.naly-qty-btn{
  appearance: none; border: 0; background: transparent; width: 28px; height: 30px;
  font-size: 15px; font-weight: 800; color: var(--text-1); cursor: pointer;
  display: flex; align-items: center; justify-content: center; font-family: inherit;
}
.naly-qty-btn:disabled{ opacity: 0.35; cursor: default; }
.naly-qty-val{
  width: 30px; text-align: center; font-size: 12.5px; font-weight: 800;
  color: var(--text-1); font-variant-numeric: tabular-nums; border: 0; background: transparent;
  appearance: none; -webkit-appearance: none; font-family: inherit;
}

/* Desktop: the .product-line rows gain table-like columns + a header row,
   without changing the mobile markup — same elements, .naly-p-name /
   .naly-p-meta / .naly-qty-ctrl are shared by _collectOrderLines and
   saveDraft. */
.naly-table__head-row{ display: none; }
.naly-table__sub{ display: none; }
@media (min-width: 1025px) {
  /* grid columns: name · unit+price (folded into .naly-p-meta) · subtotal · qty */
  .naly-table__head-row{
    display: grid; grid-template-columns: 1fr 100px 130px; gap: 11px;
    padding: 8px var(--space-4); font-size: 9px; font-weight: 800; text-transform: uppercase;
    letter-spacing: 0.05em; color: var(--text-3); border-bottom: 1px solid var(--border-soft);
  }
  .naly-table__head-row span:nth-child(2){ text-align: right; }
  .naly-order-split :is(.naly-prow, .product-line){ display: grid; grid-template-columns: 1fr 100px 130px; align-items: center; gap: 11px; }
  .naly-p-icon{ display: none; }  /* the icon column collapses into the name column on desktop */
  .naly-p-info{ grid-column: 1; }
  .naly-table__sub{
    display: block; text-align: right; font-size: 12px; font-weight: 800;
    font-variant-numeric: tabular-nums; color: var(--text-1); grid-column: 2;
  }
  .naly-table__sub:empty::before{ content: "—"; color: var(--border); font-weight: 600; }
  .naly-qty-ctrl{ grid-column: 3; justify-self: end; }

  /* The New Order product workspace owns its height in
     create_order_naly.html, where it is anchored to the supplier column. */
  .naly-order-split .naly-product-block.active{
    display: block; flex: 1 1 auto; min-height: 0; overflow-y: auto;
    overscroll-behavior: contain; scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
  }
  .naly-order-split .naly-product-block.active::-webkit-scrollbar{ width: 8px; }
  .naly-order-split .naly-product-block.active::-webkit-scrollbar-thumb{
    background: var(--border); border: 2px solid transparent; border-radius: 999px; background-clip: padding-box;
  }
  .naly-order-split .naly-product-block.active .naly-table__head-row{
    position: sticky; top: 0; z-index: 1; background: var(--bg-card);
  }
}

/* ── Notes card — margherita post-it, own gradient family ────── */
.naly-note-card{
  border-radius: var(--naly-r-tile); padding: 14px 16px;
  background: linear-gradient(160deg, #FFFCF0, #FFF6D9);
  border: 1px solid #F5D982;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.7), 0 18px 36px -18px rgba(180,121,14,0.35);
}
:root[data-theme="dark"] .naly-note-card{
  background: linear-gradient(160deg, rgba(248,192,38,0.10), rgba(248,192,38,0.04));
  border-color: rgba(248,192,38,0.28);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 18px 36px -18px rgba(0,0,0,0.5);
}
.naly-note-card__title{ font-size: 11.5px; font-weight: 800; color: #8A5E0B; margin-bottom: 6px; }
:root[data-theme="dark"] .naly-note-card__title{ color: var(--margherita); }
.naly-note-card textarea{
  width: 100%; min-height: 56px; resize: vertical; font: inherit; font-size: 12.5px; line-height: 1.5;
  color: #5C4200; background: transparent; border: 0; padding: 0;
}
:root[data-theme="dark"] .naly-note-card textarea{ color: #FFEAB0; }
.naly-note-card textarea::placeholder{ color: inherit; opacity: 0.65; }
.naly-note-card textarea:focus{ outline: none; }

/* ── Sticky footer — Add to cart. OPAQUE, never backdrop-filter:
   the same iOS trap documented on --naly-chrome-bg / --tb-bar-bg. ── */
.naly-order-footer{
  /* bottom clears the fixed tab bar (--naly-safe-bottom, ~104px) on mobile —
     without it this footer lands underneath the tab bar instead of above it. */
  position: sticky; bottom: calc(var(--naly-safe-bottom) + 8px); z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  border-radius: 19px; padding: 13px 15px;
  background: var(--tb-bar-bg);
  border: 1px solid var(--naly-surface-border);
  box-shadow: var(--naly-elev-3);
}
.naly-order-footer__recap .n{ font-size: 10.5px; font-weight: 700; color: var(--text-3); display: block; }
.naly-order-footer__recap .a{ font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; color: var(--text-1); }

/* ── Desktop split layout — structure C: suppliers · products · cart ──
   Decided on mockup 09 (variant C) over a card grid and a plain dense
   table: it's the only one of the three that lets a manager switch
   supplier without losing place, which matters because the cart is
   scoped per (supplier, location) — switching supplier doesn't clear
   anything, it opens a DIFFERENT cart. ────────────────────────────── */
@media (min-width: 1025px) {
  .naly-config{ display: grid; grid-template-columns: 1fr auto; gap: 18px; align-items: start; padding: 17px 20px; }
  .naly-config__rail{ display: none; }
  .naly-config__body{ padding: 0; }
  .naly-config .naly-cfg-select{ min-width: 0; }
  .naly-config__total{ background: none; border-top: 0; border-left: 1px solid rgba(255,255,255,0.18); padding: 0 0 0 20px; flex-direction: column; align-items: flex-end; text-align: right; }

  /* Supplier moves out of the config card into its own column — a
     dropdown makes sense when there's one field to scan, not when
     switching between them is the primary action on the page. */
  .naly-config #cfgSupplierWrap{ display: none; }

  .naly-order-split{ display: grid; grid-template-columns: 200px minmax(0,1.6fr) minmax(280px,1fr); gap: var(--space-4); align-items: start; }
  .naly-order-footer{ position: sticky; bottom: var(--space-4); }
}

/* ── Supplier column (desktop only) ──────────────────────────────── */
.naly-sup-col{ display: none; }
@media (min-width: 1025px) {
  .naly-sup-col{ display: block; position: sticky; top: var(--space-4); }
}
.naly-sup-item{
  display: flex; align-items: center; gap: 9px; padding: 9px 11px;
  border-radius: var(--naly-r-control); cursor: pointer; margin-bottom: 4px;
  border: 1px solid transparent; background: none; width: 100%; text-align: left;
  font: inherit; color: var(--text-1);
}
.naly-sup-item:hover{ background: var(--surface-soft); }
.naly-sup-item.is-active{ background: var(--acc); color: #fff; }
.naly-sup-item.has-draft:not(.is-active){ border-color: var(--green); }
.naly-sup-item__av{
  width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 800; color: #fff;
}
.naly-sup-item__body{ flex: 1; min-width: 0; }
.naly-sup-item__name{ font-size: 12.5px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.naly-sup-item__meta{ font-size: 10px; font-weight: 600; opacity: 0.75; }
.naly-sup-item__meta--draft{ color: var(--emerald); font-weight: 700; opacity: 1; }
.naly-sup-item.is-active .naly-sup-item__meta--draft{ color: #C9F2DC; }

/* ── Cart column (desktop only) — same row markup as the sheet's
   confirm-card items, so both read from one source of truth in JS. ── */
.naly-cart-col{ display: none; }
@media (min-width: 1025px) {
  .naly-cart-col{ display: flex; flex-direction: column; gap: var(--space-3); position: sticky; top: var(--space-4); }
}
.naly-cart-row{ display: flex; align-items: center; gap: 9px; padding: 9px 15px; border-bottom: 1px solid var(--border-soft); }
.naly-cart-row:last-child{ border-bottom: none; }
.naly-cart-row__qty{
  min-width: 26px; height: 22px; padding: 0 5px; border-radius: 7px;
  background: var(--acc); color: #fff; display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 800; font-variant-numeric: tabular-nums; flex-shrink: 0;
}
.naly-cart-row__name{ flex: 1; min-width: 0; font-size: 11.5px; font-weight: 700; color: var(--text-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.naly-cart-row__val{ font-size: 11.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--text-1); flex-shrink: 0; }
.naly-cart-empty{ padding: 24px 16px; text-align: center; font-size: 12px; color: var(--text-3); }

/* ═══════════════════════════════════════════════════════════
   NalyOS — mobile / desktop compositions

   Each page renders TWO arrangements of the same data (shared Jinja
   macros), not one markup that reflows. Some desktop layouts simply
   aren't reachable by reflowing a mobile column — four KPIs in a row
   above a wide chart is a different composition, not a wider 2x2.

   Only one is in the accessibility tree at a time: the hidden one uses
   `display:none`, so screen readers and tab order see a single page.

   Breakpoint is 1025px — matching .dash-root's grid in chrome.css:676,
   not 1024px. That one-pixel gap was a real bug.
   ═══════════════════════════════════════════════════════════ */
.naly-only-d { display: none; }
.naly-only-m { display: flex; }

@media (min-width: 1025px) {
  .naly-only-m { display: none; }
  .naly-only-d { display: flex; }

  /* KPIs first, one row, above the fold — the manager's glance layer. */
  .naly-d-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); }

  /* Chart takes the width it needs; shift + locations ride alongside. */
  .naly-d-main { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(280px, 1fr); gap: var(--space-4); align-items: start; }
  .naly-d-side { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }

  /* No max-height needed: the desktop composition passes a shorter viewBox
     (74 instead of 132) to sales_charts(), so the chart is *drawn* wide and
     low rather than stretched with preserveAspectRatio="none" — which would
     distort stroke width and flatten the data points into ellipses. */
}

/* ── Locations panel — shared by both compositions ────────── */
.naly-loc { display: flex; align-items: center; gap: var(--space-3); padding: 10px var(--space-4);
            border-bottom: 1px solid var(--border-soft); }
.naly-loc:last-child { border-bottom: none; }
.naly-loc__sig { width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0;
                 display: flex; align-items: center; justify-content: center;
                 font-size: 10px; font-weight: 800; color: var(--ink-10); }
.naly-loc__info { flex: 1; min-width: 0; }
.naly-loc__name { font-size: var(--font-size-sm); font-weight: 700; color: var(--text-1); display: block; }
.naly-loc__bar { display: block; height: 5px; border-radius: var(--naly-r-pill);
                 background: var(--surface-soft); margin-top: 5px; overflow: hidden; }
.naly-loc__fill { display: block; height: 100%; border-radius: var(--naly-r-pill); }
.naly-loc__val { font-size: var(--font-size-sm); font-weight: 800; font-variant-numeric: tabular-nums;
                 color: var(--text-1); flex-shrink: 0; }
/* Yesterday's count leads, the week-to-date total trails it in the same
   column — one row still reads as one location, not as two numbers. */
.naly-loc__nums { display: flex; flex-direction: column; align-items: flex-end;
                  flex-shrink: 0; line-height: 1.25; }
.naly-loc__meta { font-size: 9.5px; font-weight: 600; color: var(--text-3);
                  font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Dashboard insight cards deliberately share the Locations density: a short
   coloured signature, one readable bar and one trailing value. They replace
   the old full-width Priorities table without borrowing New Order's rows. */
.naly-d-insights { display: grid; grid-template-columns: 1fr; gap: var(--space-3); }
.naly-insight-row { display: flex; align-items: center; gap: var(--space-3); padding: 10px var(--space-4);
                     border-bottom: 1px solid var(--border-soft); }
.naly-insight-row:last-child { border-bottom: none; }
.naly-insight-row__sig { width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0;
                         display: flex; align-items: center; justify-content: center;
                         font-size: 10px; font-weight: 800; }
.naly-insight-row__sig--pizza { background: var(--warning-bg); color: var(--warning); }
.naly-insight-row__sig--ingredient { background: var(--success-bg); color: var(--success); }
.naly-insight-row__info { flex: 1; min-width: 0; }
.naly-insight-row__name { display: block; color: var(--text-1); font-size: var(--font-size-sm); font-weight: 700;
                          overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.naly-insight-row__bar { display: block; height: 5px; margin-top: 5px; overflow: hidden;
                         border-radius: var(--naly-r-pill); background: var(--surface-soft); }
.naly-insight-row__fill { display: block; height: 100%; border-radius: inherit; }
.naly-insight-row__fill--pizza { background: var(--warning); }
.naly-insight-row__fill--ingredient { background: var(--success); }
.naly-insight-row__value { color: var(--text-1); flex-shrink: 0; font-size: var(--font-size-sm);
                            font-weight: 800; font-variant-numeric: tabular-nums; }
.naly-sales__caption { margin-top: var(--space-3); color: var(--text-3); font-size: 10.5px; font-weight: 600; }

/* ═══════════════════════════════════════════════════════════
   Depth — cards read as physical objects, not drawn rectangles

   Three things together do it, and none works alone:
     · the inset light edge (--naly-edge) catches the "top" of the card
     · a contact shadow tight under it, so it sits ON the page
     · a wide diffuse shadow, so it floats ABOVE it
   Hover lifts interactive cards; static ones stay put, because a card
   that lifts under the cursor but does nothing is a lie.
   ═══════════════════════════════════════════════════════════ */
.naly-card, .naly-tile {
  transition: box-shadow 180ms ease, transform 180ms ease;
}
.naly-tile { background-image: linear-gradient(180deg, rgba(255,255,255,0.9), rgba(255,255,255,0)); }

/* Only cards that go somewhere lift. */
a.naly-card:hover, a.naly-tile:hover,
.naly-card:has(> a.naly-prow):hover {
  box-shadow: var(--naly-elev-3);
  transform: translateY(-1px);
}
.naly-prow, .product-line { transition: background 140ms ease; }
.naly-prow:hover, .product-line:hover { background: var(--surface-soft); }
.naly-loc:hover { background: var(--surface-soft); }

@media (prefers-reduced-motion: reduce) {
  .naly-card, .naly-tile, .naly-prow, .product-line { transition: none; }
  a.naly-card:hover, a.naly-tile:hover { transform: none; }
}

@media (min-width: 1025px) {
  .naly-d-insights { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
}

/* ═══════════════════════════════════════════════════════════
   NalyOS — chart primitive (paired with naly-chart.js)

   Everything here is either a hairline or a hover affordance: the data
   should be the only thing with weight. Gridlines sit under the areas,
   the crosshair only appears on interaction.
   ═══════════════════════════════════════════════════════════ */
.nc-host { position: relative; }
.nc-host svg { display: block; width: 100%; height: auto; overflow: visible; }

.nc-grid  { stroke: var(--border-soft); stroke-width: 1; }
.nc-tick  { font-size: 8px; font-weight: 600; fill: var(--text-3); }
.nc-xlab  { font-size: 8.5px; font-weight: 700; fill: var(--text-3); }
.nc-xlab--now { font-weight: 800; fill: var(--text-1); }

.nc-line  { fill: none; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
.nc-area  { stroke: none; }
.nc-dot   { stroke: var(--bg-card); stroke-width: 1.3; }
.nc-dot--last { stroke-width: 1.6; }
.nc-endval { font-size: 8.5px; font-weight: 800; font-variant-numeric: tabular-nums; }

/* Comparison period — behind the data, deliberately unsaturated so it
   reads as context rather than as another series. */
.nc-benchmark { fill: none; stroke: var(--border); stroke-width: 1.4;
                stroke-dasharray: 3 3; opacity: 0.75; }
.nc-avg      { stroke: var(--text-3); stroke-width: 1; stroke-dasharray: 4 4; opacity: 0.5; }
.nc-avg-lbl  { font-size: 7.5px; font-weight: 700; fill: var(--text-3); font-variant-numeric: tabular-nums; }
.nc-now      { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 3; }

.nc-cross    { stroke: var(--text-3); stroke-width: 1; opacity: 0; transition: opacity 120ms ease; }
.nc-hoverdots { transition: opacity 120ms ease; }
.nc-hoverdot { stroke: var(--bg-card); stroke-width: 1.25; }
.nc-hit      { cursor: crosshair; }

/* Tooltip — a real surface, following the elevation rule like any card. */
.nc-tip {
  position: absolute; top: 0; z-index: 5; pointer-events: none;
  min-width: 132px; padding: 9px 11px;
  border-radius: var(--naly-r-control);
  background: var(--bg-card); border: 1px solid var(--naly-surface-border);
  box-shadow: var(--naly-elev-2);
}
.nc-tip__head { font-size: 9.5px; font-weight: 800; letter-spacing: 0.04em;
                text-transform: uppercase; color: var(--text-3); margin-bottom: 5px; }
.nc-tip__row  { display: flex; align-items: center; gap: 7px; padding: 2px 0; }
.nc-tip__dot  { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }
.nc-tip__name { flex: 1; min-width: 0; font-size: 11px; font-weight: 600; color: var(--text-2);
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nc-tip__val  { font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--text-1); }

@media (prefers-reduced-motion: reduce) {
  .nc-cross, .nc-hoverdots { transition: none; }
}

/* ═══════════════════════════════════════════════════════════
   NalyOS — bottom sheet
   Rises from the bottom (translateY), distinct from .naly-drawer
   (translateX, slides from the left). Overlay ⇒ glass allowed,
   same as the drawer — see the @supports block above.
   ═══════════════════════════════════════════════════════════ */
.naly-sheet-scrim {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(5,7,12,0.42);
  opacity: 0; pointer-events: none;
  transition: opacity 200ms ease;
}
.naly-sheet-scrim.is-open { opacity: 1; pointer-events: auto; }

.naly-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 301;
  max-height: 80vh;
  display: flex; flex-direction: column;
  background: var(--bg-card);
  border-radius: 22px 22px 0 0;
  box-shadow: 0 -10px 40px rgba(0,0,0,0.28);
  transform: translateY(100%);
  transition: transform 220ms ease;
}
.naly-sheet.is-open { transform: translateY(0); }
.naly-sheet__grab { width: 38px; height: 4px; border-radius: 99px; background: var(--border-soft); margin: 9px auto 3px; flex-shrink: 0; }
.naly-sheet__head { padding: 8px 16px 11px; border-bottom: 1px solid var(--border-soft); flex-shrink: 0; }
.naly-sheet__title { font-size: 14px; font-weight: 800; color: var(--text-1); }
.naly-sheet__sub { font-size: 10.5px; font-weight: 600; color: var(--text-3); }
.naly-sheet__body { flex: 1; overflow-y: auto; padding-bottom: env(safe-area-inset-bottom, 0px); }
.naly-sheet__foot { padding: 12px 16px calc(18px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--border-soft); background: var(--surface-soft); flex-shrink: 0; }

/* Desktop: a sheet is a mobile-only pattern (small viewport, thumb reach).
   On desktop the same content renders inline as a column instead — pages
   using this primitive pass a flag so it never mounts past the breakpoint. */
@media (min-width: 1025px) {
  .naly-sheet, .naly-sheet-scrim { display: none; }
}

/* ═══════════════════════════════════════════════════════════
   NalyOS — dropdown with search and sections
   Used wherever a choice list is too long for inline options:
   supplier picker, location picker. Reuses .naly-sheet on mobile;
   on desktop it is a positioned popover instead of a sheet, because
   nothing here needs thumb reach at that width.
   ═══════════════════════════════════════════════════════════ */
.naly-ddown-srch {
  margin: 10px 16px 4px;
  display: flex; align-items: center; gap: 8px;
  border-radius: var(--naly-r-control); padding: 9px 12px;
  background: var(--naly-control-bg); border: var(--naly-control-bw) solid var(--naly-control-border);
  box-shadow: var(--naly-control-shadow);
  font-size: 12px; color: var(--text-3);
}
.naly-ddown-srch input { flex: 1; min-width: 0; border: 0; background: none; font: inherit; color: var(--text-1); outline: none; }
.naly-ddown-srch input::placeholder { color: var(--text-3); }

.naly-ddown-grp {
  font-size: 8.5px; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--text-3); padding: 13px 16px 5px;
}
.naly-ddown-item {
  display: flex; align-items: center; gap: 11px; padding: 11px 16px;
  border-bottom: 1px solid var(--border-soft);
  text-decoration: none; color: inherit; cursor: pointer;
}
/* display:flex above has higher priority than the [hidden] UA rule, so
   naly-sheet.js setting item.hidden=true during search filtering did
   nothing — the row stayed laid out as empty space. Needs its own rule. */
.naly-ddown-item[hidden], .naly-ddown-grp[hidden] {
  display: none;
}
.naly-ddown-item:last-child { border-bottom: none; }
.naly-ddown-item[aria-selected="true"] { background: rgba(30,58,110,0.05); }
.naly-ddown-item__av {
  width: 32px; height: 32px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800; color: #fff;
}
.naly-ddown-item__body { flex: 1; min-width: 0; }
.naly-ddown-item__name { font-size: 12.5px; font-weight: 700; color: var(--text-1); }
.naly-ddown-item__meta { font-size: 10.5px; color: var(--text-3); }
.naly-ddown-item__meta--draft { color: var(--green); font-weight: 700; }
.naly-ddown-item__trail { font-size: 11.5px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--green); flex-shrink: 0; }
.naly-ddown-item__check { font-size: 14px; color: var(--acc); flex-shrink: 0; }

/* Desktop popover variant — same item markup, different container. */
.naly-ddown-pop {
  position: absolute; z-index: 40; top: calc(100% + 6px); left: 0;
  width: min(360px, 90vw); max-height: 420px; overflow-y: auto;
  background: var(--bg-card); border: 1px solid var(--naly-surface-border);
  border-radius: var(--naly-r-tile); box-shadow: var(--naly-elev-3);
  display: none;
}
.naly-ddown-pop.is-open { display: block; }

/* ═══════════════════════════════════════════════════════════
   NalyOS — dense table
   Row-based data with real columns and a per-row subtotal —
   the "this is a tool, not a catalogue" surface. Container carries
   the elevation once; rows are flat with a hairline, per the
   density rule proven on the labour grid (07-labour-grid-density-test).
   ═══════════════════════════════════════════════════════════ */
.naly-table-wrap { overflow-x: auto; }
.naly-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 11.5px; }
.naly-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-soft);
  padding: 8px 12px; font-size: 9px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--text-3); text-align: left;
  border-bottom: 1px solid var(--border-soft);
}
.naly-table thead th.naly-table--r { text-align: right; }
.naly-table tbody td { padding: 8px 12px; border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
.naly-table tbody tr:last-child td { border-bottom: none; }
.naly-table tbody tr.naly-table--active td { background: rgba(30,138,76,0.05); }
.naly-table td.naly-table--r { text-align: right; font-variant-numeric: tabular-nums; }
.naly-table .naly-table__name { font-weight: 700; color: var(--text-1); }
.naly-table .naly-table__unit { font-size: 9.5px; font-weight: 700; color: var(--text-3); text-transform: uppercase; }
.naly-table .naly-table__sub { font-weight: 800; color: var(--text-1); }
.naly-table .naly-table__sub--zero { color: var(--border); font-weight: 600; }
