/* What this application adds to Backoffice, only with the variables of tokens.css.
   Media queries cannot read variables: 1024px is bp-rail and 600px is bp-stack. */

/* Shell: top bar across, side nav on the left, content to the right. The top bar and the side
   nav stay in view while the content scrolls, so the foot of the nav («Datos») is always there. */
.bo-topbar { position: sticky; top: 0; z-index: 1; }
.app-body { display: flex; min-height: calc(100vh - var(--size-topbar)); }
.app-body > .bo-nav { position: sticky; top: var(--size-topbar); height: calc(100vh - var(--size-topbar)); flex: none; align-self: flex-start; overflow-y: auto; }
.app-main { flex: 1; min-width: 0; max-width: calc(var(--size-content) + 2 * var(--space-6)); padding: var(--space-5) var(--space-6); }
.app-title { margin: 0 0 var(--space-5); font: var(--type-page-title); letter-spacing: var(--type-page-title-tracking); color: var(--ink); }
.app-notice { margin-bottom: var(--space-5); border: 1px solid var(--line); }

/* A failed extraction: the strip takes the danger colour on its edge and its icon. */
.app-notice.bo-strip-danger { border-color: var(--danger); }
.app-notice.bo-strip-danger > .bo-ico { color: var(--danger); }

/* Top bar: the product mark, and at the right the age of the data and the way out. */
.app-mark { color: var(--ink); }
.app-topbar-end { margin-left: auto; display: flex; align-items: center; gap: var(--space-4); }
a.app-freshness { display: inline-flex; align-items: center; gap: var(--space-2); font: var(--type-meta); color: var(--ink-muted); text-decoration: none; }
a.app-freshness:hover { color: var(--ink); }
a.app-freshness:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Shared: large figures (PVP, stock, counts) and section titles over blocks. */
.app-bigfig { margin: var(--space-1) 0 var(--space-2); font: var(--type-page-title); color: var(--ink); font-variant-numeric: tabular-nums; }
.app-bigfig.is-empty { font: var(--type-figure); font-weight: 400; color: var(--ink-muted); }  /* «Sin dato» */
.app-section-title { margin: 0 0 var(--space-2); font: var(--type-section-title); color: var(--ink); }
.app-block + .app-block { margin-top: var(--space-5); }

/* List page: the title with its result count on one line; the pager only says the page. */
.app-titlerow { display: flex; align-items: baseline; gap: var(--space-3); margin-bottom: var(--space-5); }
.app-titlerow .app-title { margin: 0; }
.app-count { font: var(--type-meta); color: var(--ink-subtle); }
.app-pager-end { margin-left: auto; }

/* Search: the field above the list, and the lines that say what the list shows or why it is empty. */
.app-search { margin-bottom: var(--space-4); }
.app-hint { margin: var(--space-3) 0; font-size: 12px; line-height: 16px; color: var(--ink-muted); }

/* Articles: the list in columns (article, laboratory, price, stock). */
.bo-row.app-cols, .bo-list-head.app-cols { display: grid; grid-template-columns: minmax(0, 1fr) 220px 80px 112px; gap: var(--space-4); align-items: center; }
.app-lab { font-size: 12px; line-height: 16px; color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.app-num strong { font-size: 13px; font-weight: 600; color: var(--ink); }
.bo-row-sub > .app-sub-lab { display: none; }  /* the laboratory in the second line, below bp-rail */

/* List page: the window holds still and only the rows scroll, under their column header, with
   the search above and the pager below always in view. */
.app-fixed { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
.app-fixed .app-body { flex: 1; min-height: 0; }
.app-fixed .app-main { display: flex; flex-direction: column; min-height: 0; padding-bottom: 0; }
.app-list-scroll { flex: 1; min-height: 0; overflow-y: auto; border-bottom: 1px solid var(--line); }
.app-list-scroll > .bo-list-head { position: sticky; top: 0; z-index: 1; }

/* Rows that open a record: the title is the link, stretched over the whole row. */
.app-links .bo-row { position: relative; }
.app-links .bo-row:hover { background: var(--surface-sunken); }
.app-links .bo-row:focus-within { outline: 2px solid var(--accent); outline-offset: -2px; }
a.app-row-link { color: inherit; text-decoration: none; outline: 0; }
a.app-row-link::after { content: ""; position: absolute; inset: 0; }

/* Record: the way back, the name as the page title with its identifiers and warnings under it. */
.app-crumbs { display: flex; align-items: center; gap: var(--space-2); font: var(--type-meta); color: var(--ink-muted); }
.app-crumbs a { color: var(--ink-muted); text-decoration: none; }
.app-crumbs a:hover { color: var(--ink); }
.app-recordhead { padding: var(--space-4) 0 var(--space-5); }
.app-recordname { margin: 0 0 var(--space-2); font: var(--type-page-title); letter-spacing: var(--type-page-title-tracking); color: var(--ink); }
.app-recordmeta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); font: var(--type-meta); color: var(--ink-muted); }

/* Record: the card in groups, with the figure panel at its right. */
.app-detail { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: var(--space-5); }  /* both as tall as the taller */
.app-detail > .bo-figure { display: flex; flex-direction: column; }
.app-detail > .bo-figure > .app-buttons { margin-top: auto; }  /* at the bottom when the record is taller */
/* Flex items keep both margins, so the details under the price keep the spacing they had when
   their margins collapsed: 1em above, after the price's own space, and none below. */
.app-detail > .bo-figure > .bo-figure-meta { margin: calc(1em - var(--space-2)) 0 0; }
.app-group-title { margin: 0; padding: var(--space-3) var(--space-4) var(--space-2); font: var(--type-section-title); color: var(--ink); border-bottom: 1px solid var(--line); }
.bo-dl + .app-group-title { border-top: 1px solid var(--line); }
/* The record of an article, tighter, so it stays close to the height of its figures. */
.app-record .app-group-title { padding-top: var(--space-2); padding-bottom: var(--space-1); }
.app-record .bo-dl-row { padding-top: 6px; padding-bottom: 6px; }
.app-dl-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); padding: var(--space-2) var(--space-4); }
.app-dl-cols dd { margin: 0; }

/* A value followed by its state: Backoffice's status, a dot and a word. */
.app-flag { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

/* Barcodes: each code with its type. */
.app-code { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.app-code + .app-code { margin-top: var(--space-1); }
.app-mono { font: var(--type-code); letter-spacing: var(--type-code-tracking); }

/* Figure panel with two figures: the PVP and its details, then the stock below a rule. */
.app-figure-sep { padding-top: var(--space-3); border-top: 1px solid var(--line); }
.bo-figure-meta + .app-figure-sep { margin-top: var(--space-4); }
.app-buttons { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* Details in columns: each label right above its value, so short figures never drift. */
.app-meta-cols { display: grid; grid-template-rows: auto auto; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); column-gap: var(--space-4); }

/* Article units: current bars with previous-period markers; native disclosures keep the
   exact values available on hover, keyboard focus and touch without JavaScript. */
.app-article-sales { margin-top: var(--space-5); padding: var(--space-5); }
.app-article-sales-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-4); margin-bottom: var(--space-5); }
.app-article-sales-head .app-section-title { flex: 1; margin: 0; font: var(--type-item-title); font-weight: 600; }
.app-chart-types { display: flex; flex: none; gap: var(--space-1); }
.app-chart-types .bo-iconbtn { height: 28px; border: 1px solid var(--line-control); }
.app-chart-types a[aria-current="true"] { background: var(--surface-selected); color: var(--accent); }
.app-article-sales-body { display: grid; grid-template-columns: 176px minmax(0, 1fr); gap: var(--space-5); }
.app-article-sales-summary { min-width: 0; border-right: 1px solid var(--line); padding-right: var(--space-4); color: var(--ink-muted); font: var(--type-body); }
.app-article-sales-total { margin: 0; color: var(--ink); font-variant-numeric: tabular-nums; }
.app-article-sales-total strong { font: 600 36px/40px var(--font-sans); }
.app-article-sales-dates { margin: var(--space-1) 0 var(--space-4); }
.app-article-sales-comparison { margin-top: var(--space-4); border-top: 1px solid var(--line); padding-top: var(--space-3); }
.app-article-sales-comparison > p { margin: 0; }
.app-article-sales-comparison > p + p { font: var(--type-item-title); }
.app-article-sales-comparison strong { color: var(--ink); font-weight: 500; }
.app-article-sales-change { margin-left: var(--space-3); white-space: nowrap; }
.app-article-sales-stats { margin: var(--space-4) 0 0; border-top: 1px solid var(--line); padding-top: var(--space-4); }
.app-article-sales-stats > div + div { margin-top: var(--space-4); }
.app-article-sales-stats dd { margin: var(--space-1) 0 0; color: var(--ink); font: var(--type-figure); font-weight: 400; }
.app-article-sales-chart { --base: calc(100% * var(--top) / var(--range)); display: flex; flex-direction: column; min-width: 0; padding: var(--space-2) 0 0 36px; color: var(--ink-muted); font: var(--type-caption); }
.app-article-sales-plot { --plot-height: 200px; position: relative; container-type: inline-size; display: grid; flex: none; grid-template-columns: repeat(var(--slots), minmax(0, 1fr)); height: var(--plot-height); margin-bottom: var(--space-6); }
.app-article-sales-grid { position: absolute; inset: 0; pointer-events: none; }
.app-article-sales-grid > span { position: absolute; left: 0; right: 0; border-top: 1px dashed var(--line); }
.app-article-sales-grid > span[data-label]::before { content: attr(data-label); font-variant-numeric: tabular-nums; position: absolute; top: -1px; right: calc(100% + var(--space-3)); transform: translateY(-50%); }
.app-article-sales-grid > .app-article-sales-base { top: var(--base); border-top-style: solid; border-color: var(--line-control); }
.app-article-sales-slot { min-width: 0; }
.app-article-sales-slot > summary { position: relative; display: block; height: var(--plot-height); list-style: none; cursor: default; }
.app-article-sales-slot > summary::-webkit-details-marker { display: none; }
.app-article-sales-slot > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-article-sales-slot[open] > summary, .app-article-sales-slot > summary:hover, .app-article-sales-slot > summary:focus-visible { background: var(--surface-sunken); }
.app-article-sales-bars { display: block; position: relative; height: 100%; }
.app-article-sales-series { --y: calc(100% * (var(--top) - var(--value)) / var(--range)); position: absolute; top: 0; bottom: 0; left: 50%; width: 44%; max-width: clamp(32px, calc(288px / var(--slots)), 48px); transform: translateX(-50%); z-index: 1; }
.app-article-sales-series[style]::before { content: ""; position: absolute; top: min(var(--base), var(--y)); height: calc(max(var(--base), var(--y)) - min(var(--base), var(--y))); left: 0; right: 0; background: var(--ink-muted); border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.app-article-sales-series.is-previous { width: 68%; max-width: clamp(48px, calc(432px / var(--slots)), 72px); z-index: 0; }
.app-article-sales-series.is-previous::before { top: var(--y); height: 2px; transform: translateY(-50%); border-radius: var(--radius-sm); background: var(--ink-subtle); opacity: .55; }
.app-article-sales-label { position: absolute; top: 100%; left: 0; right: 0; padding-top: var(--space-2); color: var(--ink-subtle); font: var(--type-caption); text-align: center; }
/* The units so far, day by day, over the three months before; the dashed line ends the months
   that count. */
.app-article-sales-line { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.app-article-sales-line polyline { fill: none; stroke: var(--ink-muted); stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.app-article-sales-line polyline.is-previous { stroke: var(--ink-subtle); stroke-width: 1.5; stroke-dasharray: 4 3; opacity: .7; }
.app-article-sales-line .is-cut { stroke: var(--line-control); stroke-width: 1; stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; }
.app-article-sales i.is-line { width: 18px; height: 2px; }
.app-article-sales-plot:has(.app-article-sales-line) { margin-bottom: var(--space-4); }
/* The months under the weeks, as in the heat map. */
.app-article-sales-months { display: grid; grid-template-columns: repeat(var(--slots), minmax(0, 1fr)); margin: calc(-1 * var(--space-2)) 0 var(--space-4); color: var(--ink); font: var(--type-caption); }
.app-article-sales-months > span { overflow: hidden; border-top: 1px solid var(--line-control); padding: var(--space-1) 2px 0; white-space: nowrap; text-overflow: ellipsis; }
.app-article-sales-months > span + span { margin-left: var(--space-2); }
.app-article-sales-months abbr { display: none; text-decoration: none; }
.app-article-sales-tip { display: none; position: absolute; z-index: 2; top: var(--space-3); left: 0; width: max-content; max-width: min(280px, 50cqw); padding: var(--space-2); border: 1px solid var(--line-control); background: var(--surface); font: var(--type-caption); color: var(--ink); pointer-events: none; }
.app-article-sales-slot.is-end .app-article-sales-tip { left: auto; right: 0; }
.app-article-sales-slot[open] .app-article-sales-tip, .app-article-sales-slot > summary:hover .app-article-sales-tip, .app-article-sales-slot > summary:focus-visible .app-article-sales-tip { display: block; }
.app-article-sales-plot:has(summary:focus-visible) summary:not(:focus-visible) .app-article-sales-tip,
.app-article-sales-plot:not(:has(summary:focus-visible)):has(details[open]) details:not([open]) .app-article-sales-tip { display: none; }
.app-article-sales-tip > span, .app-article-sales-legend > span { display: flex; align-items: center; gap: var(--space-2); }
.app-article-sales-tip > span + span { margin-top: var(--space-1); }
.app-article-sales i { display: inline-block; flex: none; width: 8px; height: 10px; border-radius: var(--radius-sm); background: var(--ink-muted); }
.app-article-sales i.is-previous { width: 18px; height: 2px; background: var(--ink-subtle); opacity: .55; }
.app-article-sales-legend { display: flex; justify-content: center; flex-wrap: wrap; gap: var(--space-5); margin-top: auto; color: var(--ink-muted); font: var(--type-caption); }
.app-article-sales-note { margin: var(--space-1) 0; color: var(--ink-muted); font: var(--type-caption); }
.app-heatmap { display: flex; flex-direction: column; min-width: 0; padding-top: var(--space-2); color: var(--ink-muted); font: var(--type-caption); }
.app-heatmap table { width: 100%; table-layout: fixed; border-spacing: 2px; font: inherit; text-align: center; font-variant-numeric: tabular-nums; }
.app-heatmap th { height: 24px; font-weight: 500; white-space: nowrap; }
.app-heatmap th:first-child, .app-heatmap thead td { width: 38px; text-align: left; }
.app-heatmap th:last-child { width: 38px; }
.app-heatmap thead tr + tr > th, .app-heatmap thead tr + tr > th:first-child { width: auto; text-align: center; color: var(--ink-subtle); }
.app-heatmap-month { overflow: hidden; background: linear-gradient(var(--line-control), var(--line-control)) bottom / 100% 1px no-repeat; padding: 0 2px; color: var(--ink); text-align: left; text-overflow: ellipsis; }
.app-heatmap-month abbr { display: none; text-decoration: none; }
.app-heatmap td { height: 28px; overflow: hidden; border-radius: var(--radius-sm); color: var(--ink); font-size: 10px; }
.app-heatmap td[style] { background: color-mix(in srgb, var(--accent) var(--intensity), var(--surface-sunken)); }
/* Zero-lightness ink keeps the middle of the ramp legible before switching to white. */
.app-heatmap [data-level="light"] { color: hsl(from var(--ink) h s 0%); }
.app-heatmap [data-level="dark"] { color: var(--on-accent); }
.app-heatmap [data-level="missing"] { outline: 1px dashed var(--line-control); outline-offset: -1px; }
.app-heatmap [data-level="negative"] { background: var(--danger-soft); color: var(--danger); }
.app-heatmap tfoot > tr > * { border-top: 1px solid var(--line); }
.app-heatmap-total, .app-heatmap tfoot td { color: var(--ink); font-weight: 500; }
.app-heatmap tfoot .app-heatmap-total { font-weight: 600; }
.app-heatmap-legend { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); margin-top: auto; padding-top: var(--space-3); }
.app-heatmap-legend > span { display: inline-flex; align-items: center; gap: var(--space-1); }
.app-heatmap-legend i { width: 18px; height: 18px; background: var(--surface); }
/* Match the cells' quadratic curve at quarter intervals. */
.app-heatmap-legend .app-heatmap-scale { width: 96px; height: 12px; background: linear-gradient(to right, var(--surface-sunken), color-mix(in srgb, var(--accent) 6.25%, var(--surface-sunken)) 25%, color-mix(in srgb, var(--accent) 25%, var(--surface-sunken)) 50%, color-mix(in srgb, var(--accent) 56.25%, var(--surface-sunken)) 75%, var(--accent)); }
/* An empty column between months, so every day keeps the same width. */
.app-heatmap .app-heatmap-gap { width: var(--space-1); padding: 0; background: none; }

/* Data: the extractions as a status card, the contents as tiles. */
.app-mid { max-width: 760px; }
.app-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--line); border-left: 1px solid var(--line); }
.app-tiles > div { padding: var(--space-4); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }

/* Sales. The period: arrows and its fields (a GET form), its figures, its chart, then the
   tickets of a day or the days of a period. The period at the left, the payment at the right:
   they change everything below. */
.app-daybar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-3); margin-bottom: var(--space-5); }
.app-daybar-day, .app-daybar-filters { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); margin: 0; }
.app-daybar .app-date { width: 168px; }
.app-date .app-clear { margin-right: var(--space-1); }
.app-date input::-webkit-calendar-picker-indicator { margin: 0; }
.app-daystep { border: 1px solid var(--line-control); width: 36px; height: 36px; }
.app-dayname { margin-left: var(--space-2); font: var(--type-body-strong); color: var(--ink); }

/* The period says what is shown; the arrows step by its kind (a day, a week, a month, a year, or
   the N days of any other). Without JavaScript, «Desde», «Hasta» and «Ver»; periodo.js marks the
   form is-picker, hides them and makes the period a button that opens the picker. */
.app-periodbar { position: relative; display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); margin: 0; }
.app-period-val { margin: 0 var(--space-2); font: var(--type-body-strong); color: var(--ink); white-space: nowrap; }
.app-period-kind { font: var(--type-meta); color: var(--ink-muted); }
.app-hour-chip { gap: var(--space-1); padding-right: 2px; font: var(--type-meta); }
.app-hour-chip .bo-iconbtn { width: 24px; height: 24px; }
.app-period-fields { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); margin-left: var(--space-2); }
.app-period-fields .app-date { width: auto; padding-left: var(--space-3); }
.app-period-fields .app-date input { padding: 0 var(--space-2); }
.app-periodbar.is-picker .app-period-fields { display: none; }
.app-period-btn { gap: var(--space-2); padding: 0 var(--space-2) 0 var(--space-3); min-width: 220px; color: var(--ink); cursor: pointer; font: inherit; }
.app-period-btn .bo-ico { margin: 0; color: var(--ink-muted); }
.app-period-btn .bo-ico:last-child { margin-left: auto; }
.app-period-btn[aria-expanded="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.app-period-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-period-btn .app-period-val { margin: 0; }

/* The picker: first what to pick (Día · Semana · Mes · Año · Periodo), then pick it. The mode says
   what a click marks: a day, its whole week, a month of the year, a year, or «Desde» then
   «Hasta». The foot says what is chosen; «Ver» applies. What has no data cannot be picked. */
.app-range { position: absolute; left: 44px; top: calc(100% + var(--space-1)); z-index: 3; width: 320px; padding: var(--space-3) var(--space-4) var(--space-4); border: 1px solid var(--line-control); border-radius: var(--radius-sm); background: var(--surface); }
.app-range[hidden] { display: none; }
.app-range button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.app-range-modes { display: flex; margin-bottom: var(--space-3); border: 1px solid var(--line-control); border-radius: var(--radius-sm); overflow: hidden; }
.app-range-modes button { flex: 1; height: 28px; padding: 0; border: 0; background: none; font: 500 12px/16px var(--font-sans); color: var(--ink-muted); cursor: pointer; }
.app-range-modes button + button { border-left: 1px solid var(--line-control); }
.app-range-modes button:hover { background: var(--surface-sunken); color: var(--ink); }
.app-range-modes button[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
.app-range-shortcuts { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.app-range-shortcuts button { height: 28px; padding: 0 var(--space-3); border: 1px solid var(--line-control); border-radius: var(--radius-sm); background: none; font: 500 12px/16px var(--font-sans); color: var(--ink); cursor: pointer; }
.app-range-shortcuts button:hover { background: var(--surface-sunken); }
.app-range-shortcuts button[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.app-range-shortcuts button:disabled { color: var(--line-control); cursor: default; background: none; }
.app-range-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
.app-range-title { font: var(--type-section-title); color: var(--ink); }
.app-range-fields { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); margin-bottom: var(--space-3); }
.app-range-field { display: flex; flex-direction: column; align-items: flex-start; padding: 6px var(--space-3); border: 1px solid var(--line-control); border-radius: var(--radius-sm); background: var(--surface); cursor: pointer; text-align: left; }
.app-range-field span { font: var(--type-caption); color: var(--ink-muted); }
.app-range-field strong { font: var(--type-body-strong); color: var(--ink); font-variant-numeric: tabular-nums; }
.app-range-field[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.app-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); row-gap: 2px; }
.app-cal-head span { height: 24px; display: grid; place-items: center; font: var(--type-caption); color: var(--ink-muted); }
.app-cal-day, .app-cal-cell { height: 32px; border: 0; background: none; font: 400 13px/1 var(--font-sans); color: var(--ink); cursor: pointer; font-variant-numeric: tabular-nums; }
.app-cal-day:hover, .app-cal-cell:hover { background: var(--surface-sunken); }
.app-cal-day.is-other { color: var(--ink-subtle); }
.app-cal-day.is-in { background: var(--surface-selected); }
.app-cal-day.is-start, .app-cal-day.is-end, .app-cal-cell.is-in { background: var(--accent); color: var(--on-accent); font-weight: 600; }
.app-cal-day.is-week.is-in { background: var(--accent); color: var(--on-accent); }  /* a week is marked whole */
.app-cal-day:disabled, .app-cal-cell:disabled { color: var(--line-control); cursor: default; background: none; }
.app-cal-months { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-1); }
.app-cal-years { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-1); }
.app-cal-months .app-cal-cell, .app-cal-years .app-cal-cell { height: 44px; }
.app-range-note { margin: var(--space-3) 0 0; font: var(--type-meta); color: var(--ink-muted); }
/* The hours of the day shown, under its month: from and to, each its hour and its minutes, and an
   icon back to the whole day, 00:00 to 00:00. Without JavaScript, the same selects by the dates. */
.app-range-hours { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--line); }
.app-time { flex: none; gap: 2px; padding: 0 var(--space-2); color: var(--ink-muted); }
.app-time .bo-ico { margin: 0 var(--space-1) 0 0; }
.app-time select { flex: none; width: auto; padding: 0 2px; font-variant-numeric: tabular-nums; cursor: pointer; }
.app-range-hours .app-range-dash { color: var(--ink-muted); }
.app-range-hours .bo-iconbtn { margin-left: auto; }
.app-range-foot { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--line); font: var(--type-meta); color: var(--ink-muted); }
.app-range-sum { margin-right: auto; }
.app-range-sum strong { color: var(--ink); font-weight: 600; }

/* A menu of links that looks like a select: <details>, open on click, closed by the page it opens. */
.app-menu { position: relative; }
.app-menu > summary { list-style: none; cursor: pointer; gap: var(--space-2); padding: 0 var(--space-2) 0 var(--space-3); min-width: 200px; color: var(--ink); }
.app-menu > summary::-webkit-details-marker { display: none; }
.app-menu > summary .bo-ico { margin: 0 0 0 auto; color: var(--ink-muted); }
.app-menu > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-menu[open] > summary { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.app-menu-key { font-size: 11px; color: var(--ink-muted); }
.app-menu-val { font-size: 13px; color: var(--ink); white-space: nowrap; }
.app-menu-list { position: absolute; right: 0; top: calc(100% + var(--space-1)); z-index: 2; min-width: 100%; padding: var(--space-1) 0; border: 1px solid var(--line-control); border-radius: var(--radius-sm); background: var(--surface); }
.app-menu-list a { display: flex; align-items: center; gap: var(--space-2); height: 32px; padding: 0 var(--space-3); font-size: 13px; color: var(--ink); text-decoration: none; white-space: nowrap; }
.app-menu-list a:hover, .app-menu-list a:focus-visible { background: var(--surface-sunken); outline: none; }
.app-menu-list a[aria-current="true"] { font-weight: 600; }
.app-menu-list .bo-ico, .app-menu-gap { width: 16px; flex: none; }

/* The figures: tiles in a row; those of a day are links that choose what the chart shows
   (?metrica=), the chosen one with the accent bar on top, as Backoffice marks what is active. */
.app-summary { margin-bottom: var(--space-5); }
.app-tiles.is-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.app-tile-sub { font: var(--type-meta); color: var(--ink-muted); }
.app-tiles .bo-status { margin-top: var(--space-1); }
.app-tiles > a.app-kpi { position: relative; display: block; padding: var(--space-4); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); color: inherit; text-decoration: none; }
.app-tiles > a.app-kpi:hover { background: var(--surface-sunken); }
.app-tiles > a.app-kpi[aria-current="true"] { background: var(--surface-selected); }
.app-tiles > a.app-kpi[aria-current="true"]::before { content: ""; position: absolute; left: -1px; right: -1px; top: -1px; height: 2px; background: var(--accent); }
.app-tiles > a.app-kpi:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* The day's chart: two views as links (?vista=hora | acumulado), drawn as SVG by the server.
   Grey ink only: colour stays for states. Each hourly bar is a link that filters the list. */
.app-chart { margin-bottom: var(--space-5); }
.app-chart-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.app-chart-head .app-section-title { margin: 0; }
.app-seg { display: inline-flex; flex: none; border: 1px solid var(--line-control); border-radius: var(--radius-sm); overflow: hidden; }
.app-seg a { display: inline-flex; align-items: center; height: 28px; padding: 0 var(--space-3); font: 500 12px/16px var(--font-sans); color: var(--ink-muted); text-decoration: none; }
.app-seg a + a { border-left: 1px solid var(--line-control); }
.app-seg a:hover { background: var(--surface-sunken); color: var(--ink); }
.app-seg a[aria-current="true"] { background: var(--accent); color: var(--on-accent); }
.app-seg a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-chart-body { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: var(--space-2); }
.app-chart-y { display: flex; flex-direction: column; justify-content: space-between; height: 120px; margin-top: -6px; margin-bottom: 14px; font: var(--type-caption); color: var(--ink-muted); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.app-chart-plot svg { display: block; width: 100%; height: 120px; overflow: visible; }
.app-chart .grid { stroke: var(--line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.app-chart .base { stroke: var(--line-control); stroke-width: 1; vector-effect: non-scaling-stroke; }
.app-chart .bar { fill: var(--ink-subtle); }
.app-chart .bar.is-partial { fill: var(--line-control); }  /* a day or a month the data only cover in part */
.app-chart .bar.is-chosen, .app-chart a:hover .bar, .app-chart a:focus .bar { fill: var(--ink); }
.app-chart a:focus { outline: none; }
.app-chart .area { fill: var(--surface-selected); }
.app-chart .line { fill: none; stroke: var(--ink-muted); stroke-width: 2; vector-effect: non-scaling-stroke; }
.app-chart-x { display: grid; margin-top: var(--space-1); font: var(--type-caption); color: var(--ink-muted); text-align: center; }

/* The tickets: time, ticket with its states, lines, payment and total; with the date for those of
   an article. A cancelled one is struck through and out of the figures, but still in its place. */
.bo-row.app-tk, .bo-list-head.app-tk { display: grid; grid-template-columns: 56px minmax(0, 1fr) 64px 160px 112px; gap: var(--space-4); align-items: center; }
.bo-row.app-tk.is-dated, .bo-list-head.app-tk.is-dated { grid-template-columns: 128px minmax(0, 1fr) 64px 160px 112px; }
.app-reg { font-size: 12px; line-height: 16px; color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-tk .bo-row-title a { font-variant-numeric: tabular-nums; }
.is-void .app-strike, .is-void .app-strike strong { text-decoration: line-through; color: var(--ink-muted); font-weight: 400; }
.bo-pager .app-hint { margin: 0; }

/* The previous period: a light mark across each bar, at its height; in the accumulated view, a
   dashed line; under each figure, the change. */
.app-chart .mark-prev { stroke: var(--line-control); stroke-width: 3; vector-effect: non-scaling-stroke; }
.app-chart .prev { pointer-events: none; }
.app-chart .line-prev { fill: none; stroke: var(--ink-subtle); stroke-width: 1.5; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
.app-chart-head { flex-wrap: wrap; }
.app-cmp-legend { display: flex; gap: var(--space-4); margin-left: auto; font: var(--type-meta); color: var(--ink-muted); }
.app-cmp-legend > span { display: inline-flex; align-items: center; gap: var(--space-2); }
.app-cmp-key { width: 12px; height: 10px; }
.app-cmp-key.is-cur { background: var(--ink-subtle); border-radius: 2px; }
.app-cmp-key.is-prev { width: 16px; height: 0; border-top: 3px solid var(--line-control); }
.app-cmp-key.is-prev.is-dashed { border-top: 2px dashed var(--ink-subtle); }
/* The change from the previous period, under its figure instead of its note: arrow and %, soft
   green if it goes up, soft red if it goes down. */
.app-figrow { display: block; }
.app-figrow .app-bigfig { margin-bottom: var(--space-1); }
.app-delta { display: inline-flex; align-items: center; gap: 2px; height: 20px; padding: 0 6px 0 4px; border-radius: 10px; font: var(--type-caption); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.app-delta .bo-ico { width: 12px; height: 12px; margin: 0; stroke-width: 2; }
.app-delta.is-up { background: var(--success-soft); color: var(--success); }
.app-delta.is-down { background: var(--danger-soft); color: var(--danger); }
.app-delta.is-flat { background: var(--surface-sunken); color: var(--ink-muted); }
.app-delta.is-none { background: var(--surface-sunken); color: var(--ink-muted); padding: 0 8px; font-weight: 500; }

/* The receptions of a day: time, reception with its states and its supplier and delivery notes
   below, lines, units and net amount. */
.bo-row.app-rc, .bo-list-head.app-rc { display: grid; grid-template-columns: 56px minmax(0, 1fr) 64px 96px 128px; gap: var(--space-4); align-items: center; }
.bo-row.app-rc.is-dated, .bo-list-head.app-rc.is-dated { grid-template-columns: 128px minmax(0, 1fr) 80px 96px 128px; }
.app-rc .app-cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The lines of a purchase: a table, and on a phone a card for each one. */
.app-table td > .bo-badge { margin-top: var(--space-1); }
.app-lines-cards { display: none; }
.app-lines-cards .bo-card { padding: var(--space-3) var(--space-4); }
.app-lines-cards .bo-figure-meta { margin-top: var(--space-3); }
.app-lines-cards .bo-card.is-void { color: var(--ink-muted); }

/* A period longer than a day: a row for each day or month, which opens it; the empty ones say why. */
.bo-row.app-dayrow, .bo-list-head.app-dayrow { display: grid; grid-template-columns: minmax(0, 1fr) 96px 96px 140px 140px; gap: var(--space-4); align-items: center; }
.app-dayrow.is-empty .bo-row-title { color: var(--ink-muted); }
.app-rowdate { font-variant-numeric: tabular-nums; }
.app-weekday { margin-left: var(--space-2); font: var(--type-meta); color: var(--ink-muted); }
.app-dayrow-empty { grid-column: 2 / -1; text-align: right; font: var(--type-meta); color: var(--ink-muted); }

/* The filters said in words, each with the way to remove it: an article, an hour. */
.app-chipline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-5); font: var(--type-meta); color: var(--ink-muted); }
.app-chip { display: inline-flex; align-items: center; gap: var(--space-2); height: 28px; padding: 0 var(--space-3); border: 1px solid var(--line-control); border-radius: var(--radius-sm); color: var(--ink); text-decoration: none; }
.app-chip .app-mono { font-size: 12px; }
a.app-chip-clear { margin: 0 var(--space-3) 0 var(--space-1); color: var(--ink-muted); }
a.app-chip-clear:hover { color: var(--ink); }

/* The lines of a ticket: a real table, numbers right-aligned, the sum of the lines in its foot. When
   the page is narrower than its columns, the table scrolls sideways in its box. */
.app-table-wrap { overflow-x: auto; }
.app-table { width: 100%; border-collapse: collapse; border: 1px solid var(--line); font-size: 13px; line-height: 20px; }
.app-table caption { text-align: left; }
.app-table th, .app-table td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.app-table thead th { padding-top: 6px; padding-bottom: 6px; background: var(--surface-sunken); font-size: 11px; line-height: 16px; font-weight: 400; color: var(--ink-muted); }
.app-table .app-num { text-align: right; }
.app-table td a, .app-recordmeta a, .app-lines-cards a { color: var(--ink); text-decoration: none; }
.app-table td a:hover, .app-recordmeta a:hover, .app-lines-cards a:hover { text-decoration: underline; }
.app-table tfoot th, .app-table tfoot td { border-bottom: 0; background: var(--surface-sunken); font-weight: 600; }
.app-cell-sub { font: var(--type-meta); color: var(--ink-muted); }
.app-table .is-empty { color: var(--ink-muted); }  /* «Sin dato» */

/* Suppliers: the list (supplier with its code, type, receptions, net amount and last reception)
   with the search and the type at its top; the record, its four figures and its last receptions. */
.app-daybar > .app-search { flex: 1; max-width: 480px; margin: 0; }
.bo-row.app-pv, .bo-list-head.app-pv { display: grid; grid-template-columns: minmax(0, 1fr) 112px 104px 152px 128px; gap: var(--space-4); align-items: center; }
.app-pv-tipo { font-size: 13px; color: var(--ink-muted); }
.app-pv-last { font-size: 12px; color: var(--ink-muted); }
.app-pv .bo-row-sub .app-mono { font-size: 12px; }
.app-pv-top { margin-top: var(--space-5); }
.app-pv-top caption { padding-bottom: var(--space-3); }
.app-pv-all { margin-top: var(--space-4); }
.app-nowrap { white-space: nowrap; }
a.bo-btn { text-decoration: none; }

/* Laboratories: the list (laboratory with its code, articles, units sold, sales, margin and
   purchases in the period) with the search and the period at its top; the record, with the
   period, four figures, its purchases by supplier and the articles that sell the most. */
.bo-row.app-labrow, .bo-list-head.app-labrow { display: grid; grid-template-columns: minmax(0, 1fr) 88px 96px 128px 88px 128px; gap: var(--space-4); align-items: center; }
.app-labrow .bo-row-sub .app-mono { font-size: 12px; }
/* A long name wraps instead of running into the figures. */
.app-labrow > :first-child, .app-labrow .bo-row-title a { min-width: 0; }
.app-lab-period { margin-top: var(--space-4); }
.app-lab-section { margin-top: var(--space-5); }
.app-lab-section caption { padding-bottom: var(--space-3); }
.app-lab-all { margin-top: var(--space-4); }
@media (max-width: 1279.98px) {  /* the articles and the units give way first */
  .bo-row.app-labrow, .bo-list-head.app-labrow { grid-template-columns: minmax(0, 1fr) 128px 88px 128px; }
  .app-labrow > :nth-child(2), .app-labrow > :nth-child(3) { display: none; }
}

/* Entry: the password and its button. */
.app-entry { display: grid; gap: var(--space-3); max-width: 360px; }
.app-entry .bo-btn { justify-self: start; }
.app-label { font-size: 11px; line-height: 16px; color: var(--ink-muted); }

/* The nav items, the back arrow and the × of the fields are links, so pages work without JavaScript. */
a.bo-nav-item, a.bo-iconbtn { text-decoration: none; }
/* A page still to come: in its place in the nav, but neither a link nor hovered. */
.bo-nav-item[aria-disabled="true"], .bo-nav-item[aria-disabled="true"] .bo-ico { color: var(--ink-subtle); cursor: default; }
.bo-nav-item[aria-disabled="true"]:hover { background: none; }

/* The × of a field: the same search without its value. The browser's own one only empties the
   field, without searching again, so it is hidden. In a select it sits left of the chevron. */
.bo-field .app-clear { width: 24px; height: 24px; margin-right: var(--space-1); flex: none; }
.bo-field .app-clear .bo-ico { margin: 0; }
.bo-select .app-clear { position: absolute; right: 28px; }
.bo-select.app-clearable select { padding-right: 56px; }
.bo-field input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }

/* Below bp-rail the side nav becomes the icon rail (the rules of .bo-nav.is-rail), the figure
   panel drops below the card, and the laboratory column gives way to the second line. */
@media (max-width: 1023.98px) {
  .app-article-sales-head { flex-wrap: wrap; }
  .app-article-sales-body { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .app-article-sales-summary { border-right: 0; border-bottom: 1px solid var(--line); padding: 0 0 var(--space-4); }
  .bo-nav { width: var(--size-rail); padding: var(--space-4) var(--space-2) 0; }
  .bo-nav .bo-nav-label, .bo-nav .bo-nav-text { display: none; }
  .bo-nav .bo-nav-group + .bo-nav-group { margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--line); }
  .bo-nav .bo-nav-item { justify-content: center; padding: 0; height: 36px; }
  .bo-nav .bo-nav-item[aria-current="page"]::before { left: -8px; }
  .app-detail { grid-template-columns: minmax(0, 1fr); }
  /* FilterBar: the selects wrap to their own row, two-up at equal width. */
  .bo-filters { flex-wrap: wrap; }
  .bo-filters > .bo-field:first-child { flex-basis: 100%; }
  .bo-filters > .bo-select { flex: 1; width: auto; min-width: 0; }
  .app-main { padding: var(--space-5) var(--space-5); }
  .bo-row.app-cols, .bo-list-head.app-cols { grid-template-columns: minmax(0, 1fr) 80px 112px; }
  .app-cols > .app-lab, .bo-list-head.app-cols > :nth-child(2) { display: none; }
  .bo-row-sub > .app-sub-lab { display: inline; }
  .app-tiles, .app-tiles.is-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* The tickets: the line count gives way first. */
  .bo-row.app-tk, .bo-list-head.app-tk { grid-template-columns: 56px minmax(0, 1fr) 112px 112px; }
  .bo-row.app-tk.is-dated, .bo-list-head.app-tk.is-dated { grid-template-columns: 128px minmax(0, 1fr) 112px 112px; }
  .app-tk > :nth-child(3) { display: none; }
  .bo-row.app-rc, .bo-list-head.app-rc { grid-template-columns: 56px minmax(0, 1fr) 96px 112px; }
  .bo-row.app-rc.is-dated, .bo-list-head.app-rc.is-dated { grid-template-columns: 128px minmax(0, 1fr) 96px 112px; }
  .app-rc > :nth-child(3) { display: none; }
  /* The days of a period: the units give way first. */
  .bo-row.app-dayrow, .bo-list-head.app-dayrow { grid-template-columns: minmax(0, 1fr) 80px 120px 120px; }
  .app-dayrow > .app-num:nth-child(3) { display: none; }
  .app-table { min-width: 720px; }
  /* The suppliers: the name and the amount. */
  .bo-row.app-pv, .bo-list-head.app-pv { grid-template-columns: minmax(0, 1fr) 152px; }
  .app-pv > :nth-child(2), .app-pv > :nth-child(3), .app-pv > :nth-child(5) { display: none; }
  /* The laboratories: the name, the sales and the purchases. */
  .bo-row.app-labrow, .bo-list-head.app-labrow { grid-template-columns: minmax(0, 1fr) 112px 112px; }
  .app-labrow > :nth-child(5) { display: none; }
  .app-daybar > .app-search { flex-basis: 100%; max-width: none; }
}

/* Phone: the top bar drops the product name (compact) and labels sit above their values. */
@media (max-width: 599.98px) {
  .app-article-sales { padding: var(--space-3); }
  .app-article-sales-head { flex-wrap: wrap; }
  .app-chart-types { padding-right: 0; border-right: 0; }
  .app-chart-types .bo-iconbtn { width: 44px; height: 44px; }
  .app-article-sales-total strong { font-size: 32px; }
  .app-article-sales-chart { padding-left: 28px; }
  .app-article-sales-grid > span[data-label]::before { right: calc(100% + var(--space-2)); }
  .app-article-sales-slot > summary { position: static; }
  .app-article-sales-plot .app-article-sales-slot .app-article-sales-tip { left: 0; right: 0; width: auto; max-width: none; }
  .app-article-sales-label { display: none; }
  .app-article-sales-plot { margin-bottom: var(--space-4); }
  .app-article-sales-months > span > span { display: none; }
  .app-article-sales-months abbr { display: inline; }
  /* Eighteen weeks fit only as colour: the units stay in each cell's title. */
  .app-heatmap td:not(.app-heatmap-total) { font-size: 0; }
  .app-heatmap td { height: 22px; }
  .app-heatmap thead tr + tr { display: none; }
  .app-heatmap-month > span { display: none; }
  .app-heatmap-month abbr { display: inline; }
  .bo-brand { display: none; }
  .bo-crumb { margin-left: 0; padding-left: 0; border-left: 0; }
  .app-main { padding: var(--space-4); }
  /* The filters stack, so the list page scrolls whole again: the rows would have no room. */
  .app-fixed { display: block; height: auto; overflow: visible; }
  .app-fixed .app-main { display: block; padding-bottom: var(--space-4); }
  .app-list-scroll { overflow: visible; }
  /* Rows: the article over the whole width, the price above the stock at its right. */
  .bo-row.app-cols { grid-template-columns: minmax(0, 1fr) auto; row-gap: 0; }
  .bo-row.app-cols > :first-child { grid-row: span 2; }
  .bo-dl-row { grid-template-columns: 1fr; gap: 0; }
  .bo-list-head, .bo-list-head.app-cols { display: none; }  /* as in ListHeader: each row already says what its values are */
  /* Sales: the day, then the payment, each on a row of its own; the tickets keep their time,
     ticket and total; the chart, its hours. */
  .app-daybar-filters, .app-menu { flex-basis: 100%; }
  /* A long name, of a supplier, is cut in the field and wraps in the list, as wide as the field. */
  .app-daybar-filters, .app-menu, .app-menu > summary, .app-menu-val { min-width: 0; }
  .app-menu > summary { width: 100%; box-sizing: border-box; }
  .app-menu-val { overflow: hidden; text-overflow: ellipsis; }
  .app-menu-list { left: 0; right: 0; }
  .app-menu-list a { height: auto; min-height: 32px; white-space: normal; }
  .bo-row.app-tk, .bo-row.app-tk.is-dated { grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-3); }
  .bo-list-head.app-tk { display: none; }
  .app-tk > :nth-child(4) { display: none; }
  .bo-row.app-rc, .bo-row.app-rc.is-dated { grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-3); }
  .bo-list-head.app-rc { display: none; }
  .app-lines-table { display: none; }
  .app-lines-cards { display: flex; flex-direction: column; gap: var(--space-3); }
  .app-rc > :nth-child(4) { display: none; }
  .bo-row.app-dayrow { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3); }
  .bo-list-head.app-dayrow { display: none; }
  .app-dayrow > .app-num:not(:last-child) { display: none; }  /* only the amount */
  .app-dayrow-empty { grid-column: 2; max-width: 160px; }
  /* Two figures a row: an amount of millions keeps its euro beside it, in a smaller size. */
  .app-tiles .app-bigfig { font: var(--type-figure); white-space: nowrap; }
  .bo-row.app-pv { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3); }
  .bo-list-head.app-pv { display: none; }
  .bo-row.app-labrow { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3); }
  .bo-list-head.app-labrow, .app-labrow > :nth-child(6) { display: none; }  /* the name and the sales */
  .app-range { left: 0; right: 0; width: auto; }  /* as wide as the period bar */
  /* The period takes the whole row between its arrows; what kind it is, and its hours, below. */
  .app-periodbar { flex-basis: 100%; }
  .app-period-btn { flex: 1 1 calc(100% - 2 * 36px - 2 * var(--space-2)); min-width: 0; }
  .app-period-btn .app-period-val { overflow: hidden; text-overflow: ellipsis; }
  .app-chart-body { grid-template-columns: 60px minmax(0, 1fr); }
  .app-chart-x span:nth-child(even) { visibility: hidden; }
}
