/* Abilian Analytics on top of the Abilian Design System.
 *
 * Two layers, loaded after ads.css:
 *   1. Knobs: Abilian's brand (abilian.com: its logo's colours, Barlow) and a calmer
 *      surface. This is ADS as intended: overriding the 27 knobs and nothing else.
 *   2. A thin app layer, `aa-*` classes, for what's specific to analytics (the large
 *      figures, the breakdown lists, two tables side by side) and a few rules ADS leaves
 *      to the app (see notes/ads-requests.md).
 *
 * Direction: calm and precise. Figtree for text; one bold element, the numbers (Barlow
 * Condensed, tabular);
 * everything around them quiet. Navy for the interface, the logo's blue for data, its
 * pink for what's wrong, a deepened version of its cyan for what's right.
 */

/* --- Fonts: self-hosted (SIL OFL). A privacy tool doesn't call Google Fonts. --- */

@font-face { font-family: "Figtree"; font-weight: 300 900; font-display: swap; src: url("fonts/figtree.woff2") format("woff2"); }
@font-face { font-family: "Barlow Condensed"; font-weight: 500; font-display: swap; src: url("fonts/barlow-condensed-500.woff2") format("woff2"); }
@font-face { font-family: "Barlow Condensed"; font-weight: 600; font-display: swap; src: url("fonts/barlow-condensed-600.woff2") format("woff2"); }

/* --- 1. Knobs ---------------------------------------------------------------------- */

:root {
  --ads-brand: #0f3269;          /* the wordmark's navy */
  --ads-info: #2986ff;           /* the logo's blue: data */
  --ads-success: #00a3ad;        /* the logo's cyan, deepened to read as text */
  --ads-danger: #e8305f;         /* the logo's pink (#ff4a77), deepened to carry white text */
  --ads-warning: #ec8a00;
  --ads-neutral-hue: 222;        /* greys leaning towards the navy */
  --ads-neutral-chroma: .9;
  --ads-radius-scale: 1.33;      /* 8px cards: softer than Tabler, not bubbly */
  --ads-shadow-strength: .35;    /* borders carry the structure, not shadows */
  /* Figtree (variable) for text: weights between the usual steps, which Barlow's
     fixed weights couldn't give (400 too thin, 700 too bold). Barlow Condensed, the
     typeface of abilian.com's headings, stays for figures. */
  --ads-font: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --ads-text-base: .9375rem;
  --ads-weight-normal: 450;
  --ads-weight-medium: 550;
  --ads-weight-bold: 650;
  /* Darkens inks in light mode (an intent's colour as text by 25% per step, muted text by
     12%). At 0, ADS's default, coloured and muted text fail WCAG AA; at 1 they pass
     narrowly; 1.5 puts muted text at AAA (7:1), which is what reads as crisp. */
  --ads-contrast: 1.5;
  /* Sentence case for small labels: Abilian's voice. */
  --ads-label-case: none;
  --ads-label-tracking: normal;
  /* A flat page: surfaces on white rather than cards on grey. */
  --ads-page-contrast: 0;
  --ads-font-figures: "Barlow Condensed", var(--ads-font);
}

/* --- 2. App layer -------------------------------------------------------------------- */

/* Without capitals, the sidebar's section labels need size and weight to hold their place
   as headings: the text size, bold, in the strong ink. */
.ads-nav__section {
  font-size: var(--ads-text);
  font-weight: var(--ads-weight-bold);
  color: var(--ads-ink-strong);
}

/* The flat page puts ADS's page colour on the surface: the sidebar keeps a grey of its own. */
.ads-sidebar { background: var(--ads-sunken); }

/* A figure: the one typographic flourish of the app. */
.aa-figure {
  font-family: var(--ads-font-figures);
  font-weight: 600;
  font-size: 2.25rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  color: var(--ads-ink-strong);
}
.aa-figure--sm { font-size: 1.5rem; }

/* The figure band is ADS's (`ads-band`); in the report its items are links that pick
   what the chart draws, marked like ADS's pressed buttons. */
.ads-band > a { text-decoration: none; }
.ads-band > a:hover { background: var(--ads-sunken); }
.ads-band > [aria-current="true"] { box-shadow: inset 0 -2px 0 0 var(--ads-brand); }

/* Halves: two panels of one card (two short tables), side by side when there is room,
   divided by hairlines: the card's line showing through a 1px gap, as in ADS's band. */
.aa-halves {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ads-border-width);
  background: var(--ads-line-soft);
  border-block-start: var(--ads-border-width) solid var(--ads-line-soft);
}
.aa-halves > * { flex: 1 1 22rem; background: var(--ads-surface); }

/* A band or halves at the top or bottom of a card would paint square corners over the
   card's rounded ones (ADS rounds a table's wrapper there, not these): they clip, to the
   card's inner radius. An open menu in the halves must not be clipped. */
.ads-card > :is(.ads-band, .aa-halves) { overflow: hidden; }
.aa-halves:has(details[open]) { overflow: visible; }
/* ADS lines a table's outer columns up with the card's title, and drops its bottom margin,
   when its wrapper is the card's child; here the wrapper is a half's. */
.aa-halves > .ads-table-scroll > .ads-table { margin-bottom: 0; }
.aa-halves > .ads-table-scroll > .ads-table :is(th, td):first-child { padding-inline-start: var(--ads-space-5); }
.aa-halves > .ads-table-scroll > .ads-table :is(th, td):last-child { padding-inline-end: var(--ads-space-5); }
.ads-card > :is(.ads-band, .aa-halves):first-child {
  border-start-start-radius: calc(var(--ads-radius-lg) - var(--ads-border-width));
  border-start-end-radius: calc(var(--ads-radius-lg) - var(--ads-border-width));
}
.ads-card > :is(.ads-band, .aa-halves):last-child {
  border-end-start-radius: calc(var(--ads-radius-lg) - var(--ads-border-width));
  border-end-end-radius: calc(var(--ads-radius-lg) - var(--ads-border-width));
}

/* The main chart: its scale in a gutter on the left (labels placed by `--at`, from the
   top), the dates under the plot. */
.aa-chart {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  column-gap: var(--ads-space-2);
}
.aa-chart__axis {
  position: relative;
  min-width: 4ch;
  font-size: var(--ads-text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--ads-ink-muted);
}
.aa-chart__axis > span { position: absolute; inset-inline-end: 0; top: var(--at); translate: 0 -50%; }
.aa-chart__ticks { grid-column: 2; }

/* Breakdowns: each row's share as a pale fill behind its label (ADS's `ads-share`). */
/* The fill needs room around the label, but the label lines up with the card's title:
   the list gives that room back into the card's padding. */
.aa-bars { margin: 0 calc(-1 * var(--ads-space-2)); padding: 0; list-style: none; }
.aa-bars > li {
  display: flex;
  justify-content: space-between;
  gap: var(--ads-space-3);
  margin-block: 2px;
  padding: var(--ads-space-1) var(--ads-space-2);
  border-radius: var(--ads-radius-sm);
}
.aa-bars a { color: var(--ads-ink); text-decoration: none; }
.aa-bars a:hover { text-decoration: underline; }
.aa-bars__value { font-variant-numeric: tabular-nums; color: var(--ads-ink-muted); }

/* The product name, set like Abilian's headings. */
.aa-brandname {
  font-family: var(--ads-font-figures);
  font-weight: 600;
  font-size: 1.375rem;
  color: var(--ads-brand-ink);
}

/* A project's icon: its site's favicon, fetched once by the server and served from here
   (never loaded by the browser from the site), and replaceable in the project's settings. */
/* At 80% of the icon box: a favicon fills its square edge to edge, where an icon of the
   set keeps a margin inside its own. Same for the initial below. */
.aa-favicon { display: block; width: 80%; height: 80%; margin: auto; object-fit: contain; border-radius: var(--ads-radius-sm); }
.aa-project-icon { display: inline-flex; flex: none; width: 1rem; height: 1rem; }
.aa-project-icon--lg { width: 2rem; height: 2rem; }
/* An icon beside a name and the line under it: both lines start after the icon. */
.aa-with-icon { display: flex; align-items: flex-start; gap: var(--ads-space-2); }
.aa-with-icon > .aa-project-icon { margin-block-start: .2em; }
.aa-with-icon--center { align-items: center; }
.aa-with-icon--center > .aa-project-icon { margin-block-start: 0; }
.aa-with-icon > .ads-input { flex: 1; min-width: 0; }

/* In the menu, ADS shows an entry's initial only in the folded rail; among projects with
   favicons, a project without one then has its name out of line with the others. It
   shows open too, drawn as ADS draws it folded. */
.ads-nav__initial {
  display: grid;
  place-items: center;
  font-size: var(--ads-text-xs);
  font-weight: var(--ads-weight-bold);
  color: var(--ads-ink-muted);
  text-transform: uppercase;
  background: var(--ads-sunken-strong);
  border-radius: var(--ads-radius-xs);
}

/* A project whose site has no favicon: its initial, in lists. */
.aa-initial {
  display: grid;
  place-items: center;
  width: 80%;
  height: 80%;
  margin: auto;
  font-size: var(--ads-text-xs);
  font-weight: var(--ads-weight-bold);
  line-height: 1;
  color: var(--ads-ink-muted);
  border-radius: var(--ads-radius-sm);
  box-shadow: inset 0 0 0 var(--ads-border-width) var(--ads-line);
}

/* The page's foot: the geolocation data's credit, small and out of the way. */
.aa-foot { padding-block: var(--ads-space-4); font-size: var(--ads-text-xs); text-align: end; }
.aa-foot a { color: inherit; }

/* The search box gives way first when the top bar is short of room. */
.ads-topbar .ads-input-icon { flex: 0 1 20rem; min-width: 0; }
.ads-topbar .ads-input-icon .ads-input { width: 100%; }
.ads-topbar > .ads-cluster { flex-wrap: nowrap; }

/* Tables keep one line per row (`ads-table--nowrap`); long values truncate (`ads-truncate`
   with a `title`). Minor columns drop out as the table's room narrows: ADS's
   `ads-col--tertiary` under 30rem, and ours under 75rem, as the overview and the visit
   log have up to ten columns where ADS's `ads-col--secondary` assumes fewer. */
.ads-table .ads-truncate { max-width: 13rem; }
@container (width < 75rem) { .aa-hide-narrow { display: none; } }

/* A button in a table row keeps its size but doesn't make its row taller than the others
   (ADS does this for compact tables only). */
.ads-table:not(.ads-table--compact) td > .ads-btn { margin-block: calc(-1 * var(--ads-space-2)); }

/* List rows in shared columns, for the two lists whose column widths ADS's
   `ads-list--columns` doesn't take (issues, reasons): each row is a subgrid of the list,
   so every column starts at the same place in every row. Cells line up on their first line
   (the status with the title, not with the middle of two lines), and the rows get the
   same vertical padding as the card head's inner rhythm. A ghost button at the end of a
   row gives its padding back, so its text lines up with the card's edge like the rest. */
.ads-list.aa-rows { display: grid; column-gap: var(--ads-space-4); }
.aa-rows > li {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: baseline;
  padding-block: var(--ads-space-4);
}
.aa-rows > li > .ads-btn--ghost:last-child { justify-self: end; margin-inline-end: calc(-1 * var(--ads-space-2)); }
.aa-issues { grid-template-columns: max-content minmax(0, 1fr) max-content; }
.aa-issues > li > :first-child { justify-self: start; }
.aa-reasons { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) max-content; }
.aa-reasons > li { align-items: center; }
@media (max-width: 40em) {
  /* the status above the text, the bar under the label */
  .aa-issues { grid-template-columns: minmax(0, 1fr) max-content; }
  .aa-issues > li > :first-child { grid-column: 1 / -1; justify-self: start; }
  .aa-reasons { grid-template-columns: minmax(0, 1fr) max-content; }
  .aa-reasons > li > .ads-progress { grid-column: 1 / -1; grid-row: 2; }
}

/* A column title that sorts the table: reads as a title, with the order it gives. */
.aa-sort { color: inherit; text-decoration: none; white-space: nowrap; }
.aa-sort:hover { text-decoration: underline; }
.aa-sort__mark { margin-inline-start: .15em; }

/* Stars. On a project's page, a button: the outline, filled once starred. On the
   overview, a starred project's mark: no bigger than the text, smaller than a favicon. */
.aa-star[aria-pressed="true"] { color: var(--ads-warning); }
.aa-star[aria-pressed="true"] .ads-icon, .aa-starred__icon { fill: currentColor; }
.aa-starred { color: var(--ads-warning); }
.aa-starred__icon { width: .75rem; height: .75rem; vertical-align: -.05em; }

/* A disclosure that reads as text (a project's "3 sites"), not a button: no padding to
   push it out of line with the line above, and no height to make its row taller. */
.aa-disclosure {
  display: inline-flex;
  align-items: center;
  gap: var(--ads-space-1);
  padding: 0;
  font: inherit;
  color: var(--ads-ink-muted);
  background: none;
  border: 0;
  cursor: pointer;
}
.aa-disclosure:hover { color: var(--ads-ink); }
.aa-disclosure:focus-visible { outline: 2px solid var(--ads-ring); outline-offset: 2px; border-radius: var(--ads-radius-sm); }
.aa-disclosure .ads-icon { width: 1em; height: 1em; transition: rotate .15s; }
.aa-disclosure[aria-expanded="true"] .ads-icon { rotate: 90deg; }
@media (prefers-reduced-motion: reduce) { .aa-disclosure .ads-icon { transition: none; } }
