/* ============================================================================
   eplankton — base.css
   reset · ground · typography scale · layout primitives · a11y
   ----------------------------------------------------------------------------
   Depends on tokens.css (loaded first). Every colour, size and font here comes
   from a token. Translucency is produced with color-mix() over tokens so that
   no raw colour value is ever introduced; each such declaration is preceded by
   a solid token fallback.

   Direction: "a light data console — calm chrome, loud numbers." The ground is
   a flat soft grey field; cards are white with a hairline. No ambient bloom,
   no glow that is not a focus ring. The display face is Google Sans 600 in
   SENTENCE CASE with negative tracking; uppercase belongs to the small label eyebrows
   alone.

   Additions beyond CONTRACT §9 (smallest things consistent with it, noted per
   the contract preamble):
     .display-sm/.display-2xl/.display-3xl   — the remaining --ds-* steps
     .editorial (+ .editorial.light)          — the editorial face at 400 / 300
     .page-sub .stack.tight/.loose .row.tight — spacing modifiers
     .link .sr-only                           — prose link + a11y label
     .shell-nav.rail / .shell-nav.bottom      — the two collapsed nav geometries
   ========================================================================== */

/* ---------------------------------------------------------------- 1. reset */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background-color: var(--bg);
  scroll-behavior: smooth;
  height: 100%;
  /* Unsmoothed, text renders heavy on light grounds. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  margin: 0;
  min-height: 100%;
  /* Flat soft grey field. No radial bloom: on a light ground a tinted bloom
     reads as a smudge, and the direction wants the chrome silent. */
  background-color: var(--bg);
  color: var(--text-primary);
  font-family: var(--font-body);
  /* Numbers line up in columns everywhere, as in Google's own consoles. */
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-base);
  line-height: 1.5;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd, pre {
  margin: 0;
}

ul, ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

img, svg, video, canvas, picture {
  display: block;
  max-width: 100%;
}

img { height: auto; border: 0; }

svg { fill: currentColor; }

a {
  color: inherit;
  text-decoration: none;
}

button {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  line-height: inherit;
  cursor: pointer;
  text-align: inherit;
}

input, select, textarea {
  margin: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
}

textarea { resize: vertical; }

table {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
}

th, td { text-align: left; padding: 0; }

fieldset { margin: 0; padding: 0; border: 0; }

legend { padding: 0; }

hr {
  height: 0;
  margin: var(--s5) 0;
  border: 0;
  border-top: 1px solid var(--line);
}

code, pre, kbd, samp {
  font-family: var(--font-mono);
  font-size: .94em;
}

summary { cursor: pointer; list-style: none; }
summary::-webkit-details-marker { display: none; }

[hidden] { display: none !important; }

::placeholder { color: var(--text-muted); opacity: 1; }

/* ------------------------------------------------- 2. selection & scrollbar */

::selection {
  background: var(--accent-wash);
  color: var(--text-primary);
}

/* Scrollbars for the light ground: the thumb is a slightly darkened hairline,
   never a dark slab, and the track stays the surface it sits on. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }

::-webkit-scrollbar-thumb {
  background-color: var(--line-strong);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: var(--r-full);
}

::-webkit-scrollbar-thumb:hover {
  background-color: var(--text-faint);
  background-clip: padding-box;
}

/* --------------------------------------------------------------- 3. focus */

a, button, input, select, textarea, summary, [tabindex], [role="button"],
[role="tab"], [role="option"], [contenteditable="true"] {
  outline: none;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible,
[role="tab"]:focus-visible,
[role="option"]:focus-visible,
[contenteditable="true"]:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  position: relative;
  z-index: 3;
}

/* The route outlet (<main> in the shell, #app on the public pages) is focused
   only by script — after an in-app navigation, and from the skip link — as
   the place reading starts, not a control: no ring, and none of the ring's
   stacking, which would lift the whole page over the topbar's menus. */
main[tabindex]:focus-visible,
#app[tabindex]:focus-visible {
  box-shadow: none;
  position: static;
  z-index: auto;
}

/* ---------------------------------------------------------- 4. typography */

/* The display face: Google Sans 600, SENTENCE CASE, negative tracking.
   `text-transform: none` is set explicitly so no ancestor or older rule can
   push these back into the uppercase of the previous direction. Line-height
   tightens as the size grows (1.2 -> 1.08). */
.display,
.display-sm, .display-md, .display-lg, .display-xl,
.display-2xl, .display-3xl {
  font-family: var(--font-display);
  font-weight: 600;
  font-style: normal;
  text-transform: none;
  letter-spacing: var(--track-display);
  line-height: 1.2;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  margin: 0;
}

.display     { font-size: var(--fs-xl); }
.display-sm  { font-size: var(--ds-sm); }
.display-md  { font-size: var(--ds-md);  line-height: 1.18; }
.display-lg  { font-size: var(--ds-lg);  line-height: 1.14; }
.display-xl  { font-size: var(--ds-xl);  line-height: 1.1; }
.display-2xl { font-size: var(--ds-2xl); line-height: 1.08; }
.display-3xl { font-size: var(--ds-3xl); line-height: 1.08; }

/* The ONLY uppercase utility in the system. */
.eyebrow {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--fs-eyebrow);
  font-weight: 400;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: var(--track-eyebrow);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.eyebrow.accent { color: var(--accent); }

.mono {
  font-family: var(--font-ui);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -.005em;
}

/* Error dumps and other preformatted .mono blocks stay in the code face. */
pre.mono { font-family: var(--font-mono); }

.num {
  font-family: var(--font-ui);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "zero" 1;
  letter-spacing: -.01em;
  color: var(--text-primary);
}

/* The editorial face (Google Sans; a serif until the move to Google's UI
   faces). Used sparingly — the landing hero's thesis line and pull quotes
   only, never in the app shell, and never for a number. Google Sans has no
   300, so .light renders at 400. */
.editorial {
  font-family: var(--font-editorial);
  font-weight: 400;
  font-style: normal;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.35;
  color: var(--text-primary);
}

.editorial.light { font-weight: 300; }

.lede {
  font-size: var(--fs-lg);
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 68ch;
  text-wrap: pretty;
}

.muted { color: var(--text-secondary); }
.dim   { color: var(--text-muted); }

.truncate {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.taxon {
  font-family: var(--font-body);
  color: var(--text-primary);
  letter-spacing: .004em;
}

.taxon-path {
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  line-height: 1.45;
  color: var(--text-muted);
  word-break: break-word;
  overflow-wrap: anywhere;
}

.link {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.link:hover { border-bottom-color: var(--accent); }

/* Inside running text a link is underlined at rest: its colour alone does not
   set it apart from the words around it (WCAG 1.4.1). */
p .link { border-bottom-color: currentColor; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The first tab stop of the shell: out of sight until it has focus, then
   over the top bar's corner. Position and stacking are restated on focus
   because the focus rule above sets its own. */
.skip-link {
  position: fixed;
  top: var(--s2);
  left: var(--s2);
  z-index: 130;
  padding: var(--s2) var(--s3);
  border-radius: var(--r-md);
  background: var(--surface-1);
  color: var(--accent);
  box-shadow: var(--shadow-2);
  text-decoration: none;
  transform: translateY(calc(-100% - var(--s4)));
}

.skip-link:focus,
.skip-link:focus-visible {
  position: fixed;
  z-index: 130;
  transform: none;
  box-shadow: var(--ring), var(--shadow-2);
}

/* --------------------------------------------------- 5. layout primitives */

.shell {
  display: grid;
  grid-template-columns: var(--nav-w) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
  width: 100%;
}

.shell-nav {
  position: sticky;
  top: 0;
  align-self: start;
  z-index: 35;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  width: 100%;
  height: 100vh;
  height: 100dvh;
  padding: var(--s4) var(--s3);
  background: var(--surface-1);
  border-right: 1px solid var(--line);
  overflow-x: hidden;
  overflow-y: auto;
}

.shell-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  position: relative;
}

/* icon rail — sidebar below 1080px */
.shell-nav.rail {
  padding: var(--s4) var(--s2);
  align-items: center;
}

.shell:has(> .shell-nav.rail) { --nav-w: 64px; }

/* bottom bar — below 720px */
.shell-nav.bottom {
  position: fixed;
  inset: auto 0 0 0;
  top: auto;
  z-index: 60;
  flex-direction: row;
  align-items: center;
  justify-content: space-around;
  gap: 0;
  width: auto;          /* left/right insets size it — 100% would overshoot a scrollbar */
  max-width: 100%;
  height: calc(58px + env(safe-area-inset-bottom, 0px));
  padding: 0 var(--s2) env(safe-area-inset-bottom, 0px);
  border-right: 0;
  border-top: 1px solid var(--line);
  background: var(--surface-1);
  overflow: visible;
}

.shell:has(> .shell-nav.bottom) { grid-template-columns: minmax(0, 1fr); }
.shell:has(> .shell-nav.bottom) .shell-main { padding-bottom: 74px; }

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: var(--s3);
  height: var(--topbar-h);
  min-height: var(--topbar-h);
  padding: 0 var(--s7);
  border-bottom: 1px solid var(--line);
  /* Solid white, hairline underneath. No blur, no tint: the topbar is chrome
     and chrome is silent in this direction. */
  background: var(--surface-1);
}

.page {
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--s6) var(--s7) var(--s10);
  min-width: 0;
}

.page.narrow { max-width: 860px; }

.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s5);
  flex-wrap: wrap;
  padding-bottom: var(--s4);
  margin-bottom: var(--s6);
  border-bottom: 1px solid var(--line);
}

.page-title {
  font-family: var(--font-display);
  font-weight: 600;
  text-transform: none;
  letter-spacing: var(--track-display);
  font-size: clamp(20px, 3.4vw, var(--ds-md));
  line-height: 1.18;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  margin: 0;
}

.page-sub {
  margin-top: var(--s2);
  color: var(--text-secondary);
  font-size: var(--fs-small);
  max-width: 72ch;
}

.page-actions {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
}

.grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--grid-gap, var(--s4));
  align-items: start;
}

.grid.tight { --grid-gap: var(--s3); }

.grid.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.span-2    { grid-column: span 2; }
.span-3    { grid-column: span 3; }
.span-full { grid-column: 1 / -1; }

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap, var(--s4));
  min-width: 0;
}

.stack.tight { --stack-gap: var(--s2); }
.stack.loose { --stack-gap: var(--s7); }

.row {
  display: flex;
  align-items: center;
  gap: var(--row-gap, var(--s3));
  flex-wrap: wrap;
  min-width: 0;
}

.row.tight  { --row-gap: var(--s2); }
.row.nowrap { flex-wrap: nowrap; }
.row.top    { align-items: flex-start; }

.spread {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-width: 0;
}

.scroll-x {
  overflow-x: auto;
  overflow-y: hidden;
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}

.sticky-sub {
  position: sticky;
  top: var(--topbar-h);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
  padding: var(--s3) 0;
  margin-bottom: var(--s4);
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}

/* ------------------------------------------------------ 6. state hooks */

[aria-busy="true"] {
  cursor: progress;
}

[data-state] { --state-color: var(--text-muted); }
[data-state="classified"] { --state-color: var(--seq-300); }
[data-state="validated"]  { --state-color: var(--status-good); }

[data-severity="good"]     { --severity-color: var(--status-good); }
[data-severity="warning"]  { --severity-color: var(--status-warning); }
[data-severity="serious"]  { --severity-color: var(--status-serious); }
[data-severity="critical"] { --severity-color: var(--status-critical); }

/* --------------------------------------------------------- 7. responsive */

@media (max-width: 1180px) {
  .grid.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid.cols-4 > .span-3 { grid-column: 1 / -1; }
}

@media (max-width: 1080px) {
  .shell { --nav-w: 64px; }
  .shell-nav { padding: var(--s4) var(--s2); align-items: center; }
}

@media (max-width: 900px) {
  .grid.cols-3,
  .grid.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .span-3 { grid-column: 1 / -1; }
  .page { padding: var(--s6) var(--s6) var(--s9); }
  .topbar { padding: 0 var(--s6); }
}

@media (max-width: 720px) {
  .shell {
    --nav-w: 0px;
    grid-template-columns: minmax(0, 1fr);
  }
  .shell-main { padding-bottom: 74px; }
  .sticky-sub { top: 0; }
}

@media (max-width: 640px) {
  .grid,
  .grid.cols-2,
  .grid.cols-3,
  .grid.cols-4 { grid-template-columns: minmax(0, 1fr); }
  .span-2, .span-3, .span-full { grid-column: 1 / -1; }
  .page { padding: var(--s4) var(--s3) var(--s9); }
  .page-head {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--s3);
    margin-bottom: var(--s5);
  }
  .topbar { padding: 0 var(--s3); gap: var(--s2); }
  .sticky-sub { padding: var(--s2) 0; }
}

@media (max-width: 420px) {
  .page { padding: var(--s4) var(--s3) var(--s9); }
  .display-xl  { font-size: var(--ds-lg); }
  .display-2xl { font-size: var(--ds-xl); }
  .display-3xl { font-size: var(--ds-2xl); }
}

/* ---------------------------------------------------- 8. reduced motion */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------ 9. print */

@media print {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .shell-nav, .topbar, .page-actions { display: none; }
  .page { max-width: none; padding: 0; }
}
