/* ═══════════════════════════════════════════════════════════
   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); }

/* ── A section card is a band on a phone ─────────────────────────────────
   Measured across 37 pages. On a 390px screen a page section sits inside two
   gutters, not one: the container's 12px a side and the row's own 16px a
   side, stacked, for 56px of a screen that has none to spare.

   What it is NOT is the card's chrome. That was the first guess and the
   measurement killed it: a .naly-card carries a 1px border and no padding at
   all, so its whole box costs 2px. Bleeding the section by the container's
   gutter is what collapses the two gutters into one — dropping the border,
   the radius and the shadow is only so that it stops looking like a floating
   card once it reaches the screen edges.

   A card earns its chrome when it sits beside something it is not. Full
   width, stacked, one per topic, it is a section, and a section is drawn
   with a rule rather than a shadow.

   Direct children of a page container only: a card nested inside another
   component is an object within a layout, and that one keeps its box.

   The bleed reads --m-gut rather than hardcoding a value, because the gutter
   is not the same everywhere — create_order_naly.html sets .naly-content
   padding to 0, and a fixed -12px would have pushed that page off screen. */
:is(.naly-content, .chub-page, .tm, .ig-page, .naly-branding,
    .dash-page) { --m-gut: var(--space-3); }

@media (max-width: 640px) {
  /* The list is explicit because CSS cannot ask "does this have a border",
     and an explicit list is greppable when a surface is added. Every one of
     these is a direct child of its page container and carries its own inner
     padding — which becomes the single gutter once the outer one is gone. */
  .naly-content > .naly-card,
  .naly-content > .search-section,
  .naly-content > .supplier-list,
  .naly-content > :is(.su-naly-head, .su-review-strip, .su-toolbar),
  .naly-content > :is(.filters-bar, .table-wrap),
  .naly-content > .ck-sendallbar,
  .naly-content > .wst-card,
  .naly-content > .cp-card,
  .naly-content > .pt-card,
  .chub-page > .chub-master,
  .tm > :is(.tm-list, .tm-setup-hint),
  .naly-branding > .naly-branding__card {
    margin-inline: calc(var(--m-gut) * -1);
    border-left: 0;
    border-right: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /* ── The same shape, one level deeper ──────────────────────────────────
     The surfaces left over are not different, they are nested: the page
     container holds ONE pass-through wrapper at padding 0, and the real
     sections live inside it. Measured on every one of them — .sc-page,
     .cl-shell, .an-page, .fl-page, .rcp-page, .wst-page — the wrapper
     contributes nothing but a level.

     So the wrapper takes the bleed and its sections give up their side
     chrome. Separating the two is what lets a wrapper hold things that are
     NOT sections (a grid, a form, a deck) without stripping them as well. */
  :is(.naly-content, .dash-page, .ig-page) >
  :is(.sc-page, .cl-shell, .xse-wrap, .settings-shell, .an-page, .fl-page,
      .pt-root, .rcp-page, .wst-page, .var-shell, .lsv2-mobile, .ck-groups) {
    margin-inline: calc(var(--m-gut) * -1);
  }

  /* Griglia turni builds its own shell instead of using .naly-content, so it
     declares its own gutter rather than inheriting one. */
  .swz-root { --m-gut: var(--space-3); }
  .swz-root > .swz-stage { margin-inline: calc(var(--m-gut) * -1); }

  /* Descendant rather than child: a few of these sit under a second inner
     div (.xse-inner, .ck-locsec) that exists for layout and carries no
     gutter of its own. The class names are page-specific, so reaching
     through cannot catch a component that belongs to somebody else. */
  :is(.naly-content, .dash-page, .ig-page) >
  :is(.sc-page, .cl-shell, .xse-wrap, .settings-shell, .an-page, .fl-page,
      .pt-root, .rcp-page, .wst-page, .var-shell, .lsv2-mobile, .ck-groups)
  :is(.sc-header, .sc-card, .card, .settings-rail, .an-header, .filter-bar,
      .an-panel, .fl-top, .pt-card, .rcp-header, .rcp-toolbar, .wst-head,
      .wst-hero, .wst-card, .lsv2-mobile-top, .xse-cardbody, .ck-expcard),
  .swz-root > .swz-stage .swz-card {
    border-left: 0;
    border-right: 0;
    border-radius: 0;
    box-shadow: none;
  }
}

/* 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; }

/* The mobile pill is taller than the 48px desktop bar it replaces, and
   --topbar-h (tokens.css) is what the shell's grid row and every sticky offset
   use to clear it. At 48px the pill overflowed its row by 22px and the page's
   own sticky header painted over the subtitle — measured 70.25px of pill in a
   48px row at 390px, 2026-09-12, found by looking at a screenshot rather than
   by any test. Scoped to body.naly-shell, so pages still using the classic
   topbar keep the bar they were laid out for. */
@media (max-width: 1024px) {
  body.naly-shell { --topbar-h: 70px; }
}
.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(--green-ink); }
.naly-status-badge--success .dot { background: var(--green-ink); }
.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(--m-gut)
           calc(var(--naly-safe-bottom-fab) + env(safe-area-inset-bottom, 0px));
}

/* ── Where a section cannot bleed, bring it nearly to the edge ────────────
   Not every section can run to the screen edges. Some are genuinely a card —
   the food-cost block, a confirmation panel — and some sit under a wrapper
   that holds other things too, where stripping the side chrome would take
   the wrong boxes with it. Those were left at the container's 12px a side.

   The gutter and the bleed are the same number, read from --m-gut and
   cancelled exactly by `margin-inline: calc(var(--m-gut) * -1)`. So shrinking
   it moves the two groups in opposite directions without touching either
   rule: a section that bleeds subtracts the smaller number and still lands
   flush on the edge, and a card that cannot bleed simply starts closer to it.

   8px rather than 0. The page needs SOME edge or a card stops reading as an
   object at all, and text inside it keeps its own 16px, which is the gutter
   that actually matters for reading. What changes is only how much of the
   screen the card is allowed to occupy: 366px wide becomes 374px. */
@media (max-width: 640px) {
  /* .naly-content only, and that is the whole point of the restriction: the
     gutter and the bleed have to move together or the cancellation breaks.
     Measured the version that did not respect this — .chub-page, .tm and
     .naly-branding take their mobile padding from naly-company.css at a
     higher specificity, so --m-gut shrank, their sections' negative margins
     shrank with it, and the padding did not: Team, Sedi, Analytics azienda
     and Branding each LOST 8px. A rule that only reaches half of a pair is
     worse than no rule.

     .swz-root is absent for the opposite reason: it carries no padding of
     its own and bleeds through .dash-main's gutter, so shrinking its --m-gut
     would stop .swz-stage short of the edge it currently reaches. */
  .naly-content { --m-gut: var(--space-2); }

  /* The company, integrations and settings shells declare their own mobile
     gutter in naly-company.css, naly-integrations.css and settings-hub.css —
     three copies of `padding: 0 var(--space-3) var(--naly-safe-bottom)`, at a
     specificity naly.css cannot reach. Those three now read var(--m-gut)
     instead of the constant, which is what lets this line move the padding
     and the bleed together on those surfaces too. The fallback keeps them at
     12px if this rule is ever removed. */
  :is(.chub-page, .tm, .ig-page, .naly-branding, .dash-page,
      [data-company-surface]) { --m-gut: var(--space-2); }
}
.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);
  /* The card gradient. NOT --acc/--acc-hover: with the magenta accent those
     are #FF0090/#D6006F, and every string that sits directly on the card
     fails there (the total label measures 2.50:1, the empty total 1.61:1,
     and the date label was inheriting near-black at 3.59:1). Pulling the
     light stop 30% toward the accent's darkest stop makes the surface
     reliably dark for BOTH accents, which is what lets one set of on-card
     text colours work. Shared verbatim with the desktop band below, so
     mobile and desktop agree on what this card's colour is.
     Measured worst case, full-strength --acc-on: navy 14.31:1, magenta 5.61:1. */
  --cfg-band-grad: linear-gradient(135deg,
    var(--acc-grad-a),
    color-mix(in srgb, var(--acc-grad-a) 70%, var(--acc-grad-b)));
  background: var(--acc-grad-a);
  background: var(--cfg-band-grad);
  box-shadow: 0 14px 34px -14px rgba(20,42,82,0.45), inset 0 1px 0 rgba(255,255,255,0.08);
  /* Flex column so `.naly-config__band` can be re-ordered to the top on
     desktop while staying the bottom total row below 1025px. Block layout
     and this flex column render identically for the mobile children. */
  display: flex; flex-direction: column;
  /* Label geometry, shared by the location label (absolute, lifted above its
     control) and the date picker's label (in flow). They must agree or the
     two columns sit on different baselines — the reason these are variables
     instead of two sets of numbers that drift apart. */
  --cfg-label-h: 13px;
  --cfg-label-gap: 7px;
  /* One height for both controls in the card. Without this the location
     control (icon 28px + 20px padding + 3px border = 50px) and the date
     input (min-height 48px) end their boxes 2px apart, which is visible
     as a ragged row. Verified with getBoundingClientRect, not by eye. */
  --cfg-control-h: 50px;
}
.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%); }

/* Band wrapper. Below 1025px this is deliberately inert: transparent, no
   padding, last in the column — so all that shows is `.naly-config__total`
   styled exactly as before. Desktop turns it into the accent strip. */
.naly-config__band{ display: block; }
.naly-config__band-text{ display: none; }
.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; }
/* --text-3 (#9AA0A6) on the white control gradient measures 2.44:1 — it was
   the worst of the three contrast failures in the New Order audit (Sketch
   017). --ink-4-on-tint is the slate the repo already ships for small text on
   tinted surfaces: 6.95:1 here, 8.90:1 on the dark control. Applies at every
   width, because the label sits on the same white control on mobile. */
.naly-cfg-label{ font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-4-on-tint); }
.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(--ink-4-on-tint); 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;
  /* #9AA0A6 on white is 2.64:1, under the 3:1 floor for a non-text control
     affordance (WCAG 1.4.11). --text-2 is 4.83:1 and visually a shade darker. */
  background: rgba(15,17,21,0.045); color: var(--text-2);
}
.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);
}
/* Full-strength --acc-on, no opacity: these two sit directly on the card, and
   the semi-transparent versions (0.78 and 0.55) measured 2.50:1 and 1.61:1
   against the magenta accent. Hierarchy comes from the 10.5px/19px size gap. */
.naly-config__total-lbl{ font-size: 10.5px; font-weight: 700; color: var(--acc-on); }
.naly-config__total-val{ font-size: 19px; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; color: var(--acc-on); }
.naly-config__total-val:is(.empty, .is-empty){ color: var(--acc-on); }

/* The other two strings that sit on the card itself rather than on a white
   control. Both were previously unset, so they inherited body ink: the date
   label rendered near-black ON NAVY at 1.28:1 — the exact failure that
   started the New Order audit — and the helper inherited --text-3 at 4.22:1. */
.naly-config .smart-order__date-picker label{ color: var(--acc-on); }
.naly-config .smart-order__date-picker p{ color: rgba(255,255,255,0.88); }
/* The delivery date is stated, not chosen: the supplier's calendar decides it.
   Sized as a sentence rather than a field, so nothing invites a click. */
.naly-delivery-when{ margin:0; font-size:.86rem; font-weight:600; line-height:1.35; }

/* `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) {
  /* ── Config card, variant C — "split band" ──────────────────────────
     Chosen 2026-09-12 from Sketch 017 over two alternatives (a light card
     with an accent rail, and the existing slab recoloured). The navy slab
     was the heaviest element on a page whose real work is the product list
     below it, and the total had no hierarchy inside it.

     Here the slab is cut in two: a slim accent band carries identity and
     the total, the row underneath carries the fields on the same material
     as the rest of the page. The dark area drops from ~200px to ~62px.
     Sketch + measurements: .planning/sketches/017-neworder-config-bar/   */
  .naly-config{
    background: var(--bg-card);
    border: 1px solid var(--naly-surface-border);
    box-shadow: var(--naly-elev-2);
    padding: 0;
  }
  .naly-config__rail{ display: none; }

  /* The band, lifted to the top by order — the DOM keeps the total last so
     the mobile card is untouched. */
  .naly-config__band{
    order: -1;
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    padding: 13px 20px;
    color: var(--acc-on);
    /* Same gradient as the mobile card, defined once on .naly-config. Solid
       first as a fallback: if color-mix is unsupported the gradient
       declaration is dropped and the band must still be dark, never
       transparent white-on-white. --acc-grad-a is the accent's darkest stop
       (navy #0B1730, magenta #A3005A) and carries --acc-on on its own. */
    background: var(--acc-grad-a);
    background: var(--cfg-band-grad);
  }
  .naly-config__band-text{ display: block; }
  /* Every string on the band is full-strength --acc-on, none of it dimmed by
     opacity. Opacity is what made the magenta accent fail: 78% white on
     #FF0090 is 2.58:1. Hierarchy here comes from size and weight instead, so
     the band survives ANY accent the user picks — the light stop above is
     pulled to 50% specifically so magenta clears 4.5:1 too (5.29:1 worst
     case, against navy's 14.52:1). */
  .naly-config__band-eyebrow{
    display: block; font-size: 10px; font-weight: 800; text-transform: uppercase;
    letter-spacing: 0.09em; color: var(--acc-on);
  }
  .naly-config__band-title{
    display: block; font-size: 14.5px; font-weight: 800; letter-spacing: -0.01em;
    margin-top: 3px; color: var(--acc-on);
  }

  /* The total moves into the band and stops being a bordered footer row. */
  .naly-config__total{
    background: none; border-top: 0;
    padding: 0; flex-direction: column; align-items: flex-end; text-align: right;
  }
  .naly-config__total-lbl{ color: var(--acc-on); }
  .naly-config__total-val{ font-size: 26px; line-height: 1.1; letter-spacing: -0.025em; color: var(--acc-on); }
  /* No opacity on the empty state either — same magenta reason as above.
     "$0.00" already reads as empty; dimming it only cost contrast. */
  .naly-config__total-val:is(.empty, .is-empty){ color: var(--acc-on); }

  /* Two columns: location | date. Explicit areas, not auto-placement —
     #locationError is a third child and would otherwise take the date's
     cell whenever it becomes visible. */
  .naly-config__body{
    padding: 15px 20px 17px;
    display: grid; grid-template-columns: 1.2fr 1.1fr; gap: 16px; align-items: start;
    grid-template-areas: "loc date" "err err";
  }
  .naly-config #cfgLocationWrap{ grid-area: loc; }
  .naly-config .smart-order__date-picker{ grid-area: date; }
  .naly-config .naly-cfg-err{ grid-area: err; color: var(--red-ink); }

  /* Label above the control. .naly-cfg-select keeps position:relative — the
     absolutely-positioned <select> still overlays it, so click-to-open is
     unchanged. The label is lifted out of the control's box, which is why it
     is absolute rather than restructured in the markup. */
  .naly-config .naly-cfg-select{ margin-top: calc(var(--cfg-label-h) + var(--cfg-label-gap)); }
  .naly-config .naly-cfg-label{
    position: absolute; top: calc(-1 * (var(--cfg-label-h) + var(--cfg-label-gap))); left: 0;
    height: var(--cfg-label-h); line-height: var(--cfg-label-h);
  }

  /* Date picker: drops the rule that separated it from the location field
     back when the two were stacked, and adopts the control grammar so the
     two boxes are the same height and sit on the same baseline. */
  .naly-config .smart-order__date-picker{
    border-top: 0; padding-top: 0; gap: 0;
  }
  .naly-config .smart-order__date-picker label{
    font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--ink-4-on-tint);
    height: var(--cfg-label-h); line-height: var(--cfg-label-h);
    margin-bottom: var(--cfg-label-gap);
  }
  .naly-config .smart-order__date-picker input{
    min-height: var(--cfg-control-h);
    background: var(--naly-control-bg);
    border: var(--naly-control-bw) solid var(--naly-control-border);
    box-shadow: var(--naly-control-shadow);
    border-radius: var(--naly-r-control);
    padding: 9px 12px;
  }
  .naly-config .smart-order__date-picker input:focus{
    outline: none; border-color: var(--acc-ink);
    box-shadow: var(--naly-control-shadow), 0 0 0 3px var(--acc-soft);
  }
  .naly-config .smart-order__date-picker p{ color: var(--ink-4-on-tint); }

  /* Location control: share the date input's height so the row is flush. */
  .naly-config .naly-cfg-select{ min-width: 0; min-height: var(--cfg-control-h); }

  /* 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; }
