/* Analytics dashboard: stat tiles, SVG line chart, ranked bar lists.
   Loaded by the app layouts and by AnalyticsPdf, so every rule here has to hold
   on screen and on an A4 page. */

:root {
  /* The two series hues. Orange is the brand accent one step darker
     (--ls-orange-hover), which is what clears 3:1 against the surface; the blue
     is its partner. The pair was validated for colour-vision separation
     (ΔE 19.3 protan / 34.1 tritan) rather than picked by eye, so do not nudge
     either value without re-checking. */
  --chart-1: #e35812;
  --chart-2: #2f6f9f;
  --chart-grid: var(--color-border-subtle);
}

/* ---- Stat tiles --------------------------------------------------------- */
.stat-grid {
  display: grid; gap: 16px; margin-bottom: 24px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
/* Four tiles that must stay on one row. At the default 190px floor the fourth
   drops to a line of its own on an A4 page, which reads as a separate, lesser
   figure rather than the fourth of four. */
.stat-grid-4 { grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); }
.stat-tile { padding: 18px 20px; }
.stat-label {
  font-size: var(--font-size-caption); color: var(--color-text-secondary);
  font-weight: var(--weight-semibold);
}
/* Proportional figures, not tabular: at this size tabular-nums gives every
   digit the width of a zero and a number like 121 reads loose. */
.stat-value {
  font-family: var(--font-sans); font-weight: var(--weight-bold);
  font-size: var(--font-size-h3); letter-spacing: var(--tracking-tight);
  line-height: 1.1; margin-top: 6px;
}
.stat-delta { font-size: var(--font-size-caption); font-weight: var(--weight-semibold); margin-top: 4px; }
.stat-hint { font-size: var(--font-size-caption); color: var(--color-text-secondary); margin-top: 4px; }

/* ---- Line chart --------------------------------------------------------- */
.chart { width: 100%; height: auto; display: block; overflow: visible; }
.chart-grid { stroke: var(--chart-grid); stroke-width: 1; }
.chart-tick {
  font-family: var(--font-sans); font-size: 11px; fill: var(--color-text-secondary);
  font-variant-numeric: tabular-nums;
}
/* Values and labels wear text tokens, never the series colour — a light hue is
   illegible as text. Identity comes from the mark beside them. */
.chart-endlabel {
  font-family: var(--font-sans); font-size: 11px; font-weight: var(--weight-semibold);
  fill: var(--color-text-primary);
}
.chart-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-area { stroke: none; opacity: .1; }
/* 2px ring in the surface colour keeps the two end dots legible where they
   land on top of one another during a quiet week. */
.chart-dot { stroke: var(--color-bg-surface); stroke-width: 2; }

.chart-line.chart-s1 { stroke: var(--chart-1); }
.chart-line.chart-s2 { stroke: var(--chart-2); }
.chart-area.chart-s1 { fill: var(--chart-1); }
.chart-area.chart-s2 { fill: var(--chart-2); }
.chart-dot.chart-s1 { fill: var(--chart-1); }
.chart-dot.chart-s2 { fill: var(--chart-2); }

.chart-empty {
  font-size: var(--font-size-body-sm); color: var(--color-text-secondary);
  padding: 28px 0; text-align: center;
}

/* ---- Legend ------------------------------------------------------------- */
.chart-legend { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 12px; }
.chart-legend span {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--font-size-caption); color: var(--color-text-secondary);
}
.chart-key { width: 14px; height: 3px; border-radius: 2px; flex-shrink: 0; }
.chart-key-1 { background: var(--chart-1); }
.chart-key-2 { background: var(--chart-2); }

/* ---- Ranked bar lists --------------------------------------------------- */
.bar-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
/* The track gets a full share of the width rather than a fixed 96px: a bar
   that short carries almost no comparison, which is the only reason it is
   there. */
.bar-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 58px; align-items: center; gap: 12px; }
.bar-label {
  font-size: var(--font-size-body-sm); color: var(--color-text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bar-track { background: var(--color-bg-muted); border-radius: var(--radius-xs); height: 10px; }
/* Square where it leaves the baseline, rounded at the data end. */
.bar-fill { display: block; height: 10px; background: var(--chart-1); border-radius: 0 4px 4px 0; }
.bar-value {
  font-size: var(--font-size-caption); color: var(--color-text-secondary);
  text-align: right; font-variant-numeric: tabular-nums;
}

/* ---- Layout ------------------------------------------------------------- */
.analytics-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.analytics-panel { padding: 20px 22px; }
.analytics-panel .section-title { margin-bottom: 4px; }
.analytics-panel-hint {
  font-size: var(--font-size-caption); color: var(--color-text-secondary); margin-bottom: 16px;
}
.analytics-toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.analytics-note {
  font-size: var(--font-size-caption); color: var(--color-text-secondary);
  margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--color-border-subtle);
}
.analytics-warning {
  border-color: var(--color-warning); color: var(--color-warning);
  font-size: var(--font-size-body-sm); margin-bottom: 20px;
}

/* ---- Empty states -------------------------------------------------------- */
/* Nothing chosen yet, or nothing recorded. Deliberately not styled as a
   warning: neither is a failure, and the yellow rule would send somebody
   looking for a bug that is not there. */
.analytics-vuoto { text-align: center; padding: 40px 24px; margin-bottom: 20px; }
.analytics-vuoto-titolo {
  font-size: var(--font-size-body); font-weight: var(--weight-semibold); margin-bottom: 6px;
}
.analytics-vuoto-testo {
  font-size: var(--font-size-body-sm); color: var(--color-text-secondary);
  max-width: 52ch; margin: 0 auto;
}

/* ---- Source-labelled section (Search Console) ---------------------------- */
/* The Google figures are a second source, not more of the first one. A rule
   above the block and a heading naming the source is what stops a reader
   comparing "clic" against "visite" and concluding one of them is broken. */
.analytics-section {
  margin-top: 32px; padding-top: 24px;
  border-top: 2px solid var(--color-border-subtle);
}
.analytics-section-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 16px; flex-wrap: wrap; margin-bottom: 20px;
}
.analytics-section-head .analytics-panel-hint { margin-bottom: 0; }
.analytics-section-link,
.analytics-inline-link {
  font-size: var(--font-size-caption); font-weight: var(--weight-semibold); white-space: nowrap;
}
.analytics-link-sep { color: var(--color-text-secondary); font-size: var(--font-size-caption); }

/* Right-aligned figures in the queries table need tabular digits: the whole
   point of the column is comparing them down the page. */
.analytics-queries td:not(:first-child),
.analytics-queries th:not(:first-child) { font-variant-numeric: tabular-nums; }
/* A long query must not push the numeric columns off the card. */
.analytics-queries td:first-child {
  max-width: 0; width: 55%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

@media (max-width: 860px) {
  .analytics-cols { grid-template-columns: 1fr; }
}

/* ---- Loading skeleton --------------------------------------------------- */
/* Stands in for the report while the frame is being fetched. Shaped like the
   real thing so the page does not jump when the figures land, and quiet enough
   that it is not mistaken for content. */
.skeleton-bar, .skeleton-chart {
  background: var(--color-border-subtle);
  border-radius: var(--radius-sm);
  animation: skeleton-pulse 1.4s ease-in-out infinite;
}
.skeleton-sm { height: 10px; width: 45%; }
.skeleton-lg { height: 22px; width: 70%; margin-top: 10px; }
.skeleton-chart { height: 200px; margin-top: 14px; }

@keyframes skeleton-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .45; }
}
/* Respected rather than assumed: a pulsing block is exactly the kind of motion
   somebody turns off at the operating system. */
@media (prefers-reduced-motion: reduce) {
  .skeleton-bar, .skeleton-chart { animation: none; }
}

/* Announced to a screen reader, invisible to everyone else. The skeleton
   itself is aria-hidden — a dozen grey rectangles is not a page description. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---- Print -------------------------------------------------------------- */
/* Chromium renders the PDF at A4 width; the two-column grid would otherwise
   overflow the page box and silently drop the right-hand panels. */
@media print {
  .analytics-cols { grid-template-columns: 1fr 1fr; gap: 14px; }
  .analytics-panel, .stat-tile { break-inside: avoid; }
  .bar-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 52px; }
  /* The Google block opens a new page rather than starting three rows from the
     bottom of the Umami one — the whole point of the section is that a reader
     sees where one source ends and the next begins. */
  .analytics-section { break-before: page; margin-top: 0; padding-top: 0; border-top: none; }
  .analytics-queries tr { break-inside: avoid; }
  /* The PDF renders the report directly and never waits on a frame. Without
     this it would carry a first page of empty grey boxes. */
  .analytics-skeleton { display: none; }
}
