/* ============================================================
   modydash — shared design tokens
   Vision UI navy. One palette for the dashboard and every module.

   Every colour below is measured, not eyeballed, against the three
   surfaces it is actually drawn on. Contrast on page / card-start /
   card-end:

     ink     19.55 / 19.35 / 19.33     muted   8.67 / 8.58 / 8.57
     accent   7.87 /  7.79 /  7.78     good    7.32 / 7.24 / 7.24
     warn    11.13 / 11.01 / 11.00     bad     6.42 / 6.36 / 6.35
     water    9.35 /  9.25 /  9.24

   All clear WCAG AA for normal text. --edge clears 3.0 against the card
   for interactive borders (WCAG 1.4.11). Re-measure if you change any of
   them; see docs/DECISIONS.md.
   ============================================================ */

/* Self-hosted so the page still makes zero external requests. Plus Jakarta
   Sans, SIL OFL, latin subset, variable 200-800 in one 27KB file. */
@font-face{
  font-family:'Plus Jakarta Sans';
  font-style:normal;
  font-weight:200 800;
  font-display:swap;
  src:url('/assets/fonts/plus-jakarta-sans-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
    U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,
    U+FEFF,U+FFFD;
}

:root{
  /* surfaces */
  --page:#030C1D;
  --card:linear-gradient(127.09deg,rgba(6,11,40,.94) 19.41%,rgba(10,14,35,.49) 76.65%);
  --card-solid:#060B27;      /* flattened equivalent, for measuring against */
  --raised:#0A1030;          /* inset panels, controls, table stripes */
  --line:#31406E;            /* card hairline — decorative, 1.92 */
  --edge:#4E5E89;            /* interactive borders — 3.03, WCAG 1.4.11 */

  /* text */
  --ink:#FFFFFF;
  --muted:#A0AEC0;

  /* signal. Reserved: never decorative.
     good = open / ahead / under the limit
     warn = wet / tight / near the limit
     bad  = closed / behind / over the limit */
  --accent:#4FA9FF;
  --good:#01B574;
  --warn:#FFB547;
  --bad:#FF5B5B;
  --water:#5BC0DE;
  --tile:#006FF9;            /* icon tile fill; white text on it clears 4.52 */

  /* form */
  --radius:20px;
  --radius-sm:12px;
  --shadow:0 20px 27px rgba(0,0,0,.28);
  --sans:'Plus Jakarta Sans',ui-sans-serif,system-ui,-apple-system,"Segoe UI",
    Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;

  /* rhythm */
  --gap:clamp(10px,1.4vh,18px);
  --pad:clamp(14px,1.8vh,22px);
  --micro:clamp(11px,1.15vh,13px);
  --small:clamp(13px,1.5vh,15px);
  --body:clamp(14px,1.7vh,17px);
}

/* ---------- primitives shared by every page ---------- */

/* Reset lives here so a new page cannot forget it. Without it the default
   body margin pushes a 100dvh shell 8px past the viewport and the document
   scrolls, which is the one thing this site must never do. */
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%;overflow:hidden;background:var(--page);color:var(--ink);
  font-family:var(--sans);font-size:var(--body);-webkit-font-smoothing:antialiased;
  overscroll-behavior:none}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
/* Any author rule setting display beats the UA's [hidden]{display:none}, which
   silently breaks every hidden toggle. Settle it once, here. */
[hidden]{display:none!important}

.v-card{
  background:var(--card);
  border:1px solid var(--line);
  border-radius:var(--radius);
  box-shadow:var(--shadow);
}

/* 44px minimum on anything you press. This screen is read and operated at
   arm's length, in motion. See the project CLAUDE.md. */
.v-btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 16px;
  background:var(--raised);border:1px solid var(--edge);
  border-radius:var(--radius-sm);
  color:var(--ink);font-family:var(--sans);font-size:var(--micro);
  font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  text-decoration:none;cursor:pointer;touch-action:manipulation;
  transition:background-color .12s ease,border-color .12s ease;
}
.v-btn:hover{border-color:var(--accent)}
.v-btn[aria-pressed="true"],.v-btn.on{
  background:var(--tile);border-color:var(--tile);color:#fff}

:where(a,button,select,input,[tabindex]):focus-visible{
  outline:2px solid var(--accent);outline-offset:2px}

::-webkit-scrollbar{width:6px;height:6px}
::-webkit-scrollbar-thumb{background:var(--edge);border-radius:3px}
::-webkit-scrollbar-track{background:transparent}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition:none!important;animation:none!important}
}

/* ---------- shared left navigation ----------
   Markup is injected by /assets/nav.js into an empty
   <nav class="sidenav" id="sidenav"></nav>. Every page uses the same shell
   grid: a fixed nav column, then whatever that page puts beside it. */

/* minmax(0,1fr) not auto: an implicit auto row grows to its content, so a
   tall instrument would push the shell past 100dvh and scroll the document.
   The min-height:0 lets the flex/grid children inside actually shrink. */
.shell{height:100dvh;display:grid;grid-template-columns:236px 1fr;
  grid-template-rows:minmax(0,1fr)}
.shell > *{min-height:0;min-width:0}
.sidenav{display:flex;flex-direction:column;gap:var(--gap);padding:var(--pad);min-height:0}
.sidenav .brand{display:flex;align-items:center;gap:10px;padding:2px 6px 0}
.sidenav .brand-mark{width:26px;height:26px;border-radius:8px;background:var(--tile);
  display:grid;place-items:center;flex-shrink:0}
.sidenav .brand-name{font-size:var(--small);font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  font-family:var(--sans);color:var(--ink)}
.side-rule{height:1px;background:linear-gradient(90deg,transparent,var(--line),transparent)}
.side-nav{display:flex;flex-direction:column;gap:6px;overflow-y:auto;min-height:0}
.side-link{display:flex;align-items:center;gap:12px;min-height:46px;padding:0 12px;
  border-radius:var(--radius-sm);color:var(--muted);text-decoration:none;
  font-family:var(--sans);font-size:var(--small);font-weight:600;letter-spacing:0;
  text-transform:none;transition:background-color .12s ease,color .12s ease}
.side-link .ico{width:30px;height:30px;border-radius:9px;background:var(--raised);
  display:grid;place-items:center;flex-shrink:0;color:var(--accent)}
.side-link:hover{color:var(--ink)}
.side-link[aria-current="page"]{background:var(--card);border:1px solid var(--line);
  color:var(--ink);box-shadow:var(--shadow)}
.side-link[aria-current="page"] .ico{background:var(--tile);color:#fff}
/* The wake toggle sits above the dashboard's region panel and below the links
   on every other page. Same target size and shape as a nav row. */
.side-wake{margin-top:auto;display:flex;align-items:center;gap:12px;min-height:46px;
  padding:0 12px;border:1px solid var(--line);border-radius:var(--radius-sm);
  background:transparent;color:var(--muted);font-family:var(--sans);
  font-size:var(--small);font-weight:600;cursor:pointer;width:100%;
  transition:background-color .12s ease,color .12s ease}
.side-wake .ico{width:30px;height:30px;border-radius:9px;background:var(--raised);
  display:grid;place-items:center;flex-shrink:0;color:var(--muted)}
.side-wake:hover{color:var(--ink)}
.side-wake[aria-pressed="true"]{background:var(--card);color:var(--ink);box-shadow:var(--shadow)}
.side-wake[aria-pressed="true"] .ico{background:var(--tile);color:#fff}
.side-wake:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* ---------- "what is that dot", shared by every instrument ----------
   The mark keeps whatever size its instrument wants; the hit target is an
   invisible disc over it, sized by the page in its own viewBox units to land
   near the 44px floor. See assets/pick.js. */
.pick-hit{fill:transparent;cursor:pointer}
.pick-hit:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.pick-mark.pick-on{stroke:var(--ink);stroke-width:1.5}
.pick-readout{position:absolute;right:1rem;top:.9rem;max-width:15rem;text-align:right;
  background:var(--raised);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:.5rem .65rem;pointer-events:none;z-index:2}
.pick-title{font-family:var(--mono);font-size:.85rem;color:var(--ink);
  font-variant-numeric:tabular-nums;line-height:1.25}
.pick-title.bad{color:var(--bad)} .pick-title.warn{color:var(--warn)}
.pick-title.good{color:var(--good)}
.pick-lines{font-family:var(--mono);font-size:.7rem;color:var(--muted);margin-top:.25rem;
  line-height:1.45}

.side-foot{padding:var(--pad);border-radius:var(--radius);
  background:var(--card);border:1px solid var(--line)}
.side-foot .k{font-size:var(--micro);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);font-family:var(--sans)}
.side-foot .v{font-size:var(--small);font-weight:700;margin-top:4px;font-family:var(--sans)}
/* When both are present the toggle keeps the auto margin and the panel follows
   it, so the pair sits at the bottom rather than the toggle floating alone. */
.side-wake + .side-foot{margin-top:var(--gap)}

/* Narrow or portrait (the windowed browser): the rail stays on the left, always
   visible, and shrinks to icons only. It never moves to a top strip. */
@media (max-aspect-ratio:1/1),(max-width:820px){
  .shell{grid-template-columns:76px 1fr}
  .sidenav{padding:var(--gap) 8px}
  .side-link{justify-content:center;padding:0}
  .side-link span:not(.ico){display:none}
  .side-wake{justify-content:center;padding:0}
  .side-wake span:not(.ico){display:none}
  .side-rule,.side-foot,.sidenav .brand-name{display:none}
  .sidenav .brand{justify-content:center;padding:2px 0 0}
}
