/* ============================================================================
   LiveOS Design System — ui.css
   V1.1 · 2026-08-20 · requires tokens.css  (V1.1: critic-corrected)

   Components extracted from the shipped V19/V20 modules. Every rule below
   already exists in production somewhere; this file is the deduplicated,
   named version of it. Module-specific one-offs were deliberately left out —
   a component earns a place here by appearing in three or more modules.

   Rule: if you need a component that isn't here, build it in the module,
   ship it, and promote it here on its third appearance. Do not speculatively
   add components.
   ========================================================================== */

/* ── reset + page ─────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--b3);
  font-weight: var(--w-regular);
  line-height: var(--body-lh);
  -webkit-font-smoothing: antialiased;
}

::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--grey-300); border-radius: var(--r-pill); }

.wrap { max-width: var(--wrap-max); margin: 0 auto; padding: 20px var(--gutter) 96px; }


/* ── HERO ─────────────────────────────────────────────────────────────────
   Photographic ground + 50% black scrim. The scrim is not optional: it is
   what guarantees white type stays legible on an unknown image. */
.hero {
  position: relative;
  border-radius: var(--r-lg);
  padding: var(--sp-10);
  margin-bottom: 32px;
  display: flex; align-items: stretch; gap: 32px;
  background-position: center; background-size: cover; background-repeat: no-repeat;
  background-image: linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5));
}
.hero > * { position: relative; z-index: 1; }
.hero-title { font-size: var(--h1); font-weight: var(--w-semibold); letter-spacing: -.03em; line-height: 1; color: var(--white); }
.hero-sub   { font-size: var(--b1); color: rgba(255,255,255,.78); margin-top: var(--sp-3); max-width: 52ch; }
.hero-legend { margin-top: var(--sp-5); display: flex; flex-wrap: wrap; gap: 18px; }

.legend-item {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--b3); font-weight: var(--w-medium);
  letter-spacing: .05em; text-transform: uppercase;
  color: rgba(255,255,255,.55);
}
.legend-icon {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: var(--ctrl-sm); height: var(--ctrl-sm);
  border-radius: 50%; border: 1px solid currentColor;
}
.legend-icon svg { width: 60%; height: 60%; stroke-width: 1; }
.legend-icon svg * { vector-effect: non-scaling-stroke; }


/* ── GRID + CARD ──────────────────────────────────────────────────────────
   Cards flow two-up on desktop, full width on mobile. Flex, not grid, so a
   trailing odd card centers instead of stranding a half-width gap. */
.grid { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-4); }

.card {
  background: var(--surface);
  border-radius: var(--r-md);
  padding: 13px;
  display: flex; flex-direction: column;
  min-width: 0;
  flex: 0 1 calc(50% - var(--sp-4) / 2);
}
.card.full { flex-basis: 100%; }

/* Dark-card variant — the head/body pair IS the card, so the wrapper drops its
   own surface and padding. Without this the ink block sits inside a grey frame
   and any short body leaves a dead grey band underneath. */
.card.dark { background: transparent; padding: 0; }

/* Dark card — LiveOS's signature container. Head band and body share the
   ink ground; the -1px margin closes the seam the border radius opens up. */
.card-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  height: var(--head-h); padding: 0 14px;
  border-radius: var(--r-sm);
  background-color: var(--ink-900);
  cursor: pointer; list-style: none;
}
.card-head::-webkit-details-marker { display: none; }
.card-title { font-size: var(--b2); font-weight: var(--w-semibold); color: var(--white); }

.card-body {
  position: relative;
  padding: 14px; margin-top: -1px;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  background-color: var(--ink-900); color: var(--white);
  display: flex; flex-direction: column; gap: 10px;
}

.card-icon {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; align-self: center;
  width: calc(var(--b3) * 1.9); height: calc(var(--b3) * 1.9);
  border-radius: 50%;
  border: 1px solid var(--white); color: var(--white);
}
.card-icon svg { width: 60%; height: 60%; stroke-width: 1; }
.card-icon svg * { vector-effect: non-scaling-stroke; }


/* ── STAT TILE ────────────────────────────────────────────────────────────
   Label-first: label reads before value (BOS Design-Standards §1.1). */
.stat-tile {
  position: relative; display: flex; align-items: center; gap: 10px;
  background: var(--grey-300);
  border-radius: var(--r-sm);
  padding: 10px 12px; min-width: 0;
}
.stat-tile-icon {
  width: var(--ctrl-lg); height: var(--ctrl-lg); border-radius: 50%;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  background: rgba(0,0,0,.08);
}
.stat-tile-icon svg { width: var(--ctrl-lg-icon); height: var(--ctrl-lg-icon); stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.stat-tile-label { font-size: var(--b3); color: var(--muted); font-weight: var(--w-medium); }
.stat-tile-value { font-size: var(--b2); font-weight: var(--w-semibold); }

.stat-tile.good    .stat-tile-icon { background: var(--rate-6); color: var(--white); }
.stat-tile.caution .stat-tile-icon { background: var(--rate-2); color: var(--white); }

/* on a dark card the tile drops its own ground — the card is the ground */
.stat-tile.on-dark { background: transparent; padding: 0; }
.stat-tile.on-dark .stat-tile-label { color: rgba(255,255,255,.55); }
.stat-tile.on-dark .stat-tile-value { color: var(--white); }


/* ── ROW ITEMS + PILLS ────────────────────────────────────────────────────
   Name pill is ink, score pill is grey — the pair reads as label→value. */
.item-row  { display: flex; align-items: center; gap: var(--sp-2); background: transparent; }

.item-name, .item-score {
  flex-shrink: 0;
  height: calc(var(--b3) * 1.9);
  padding: 0 calc(var(--b3) * .85);
  border-radius: var(--r-pill);
  font-size: var(--b3);
  font-weight: var(--w-semibold);   /* ceiling is 600 — never 700 */
  letter-spacing: -.01em;
  display: inline-flex; align-items: center;
}
.item-name  { background: var(--ink-900); color: var(--white); }
.item-score { background: var(--grey-300); color: var(--ink); gap: calc(var(--b3) * .5); }

/* score dot — carries the rating hue, always inside a labeled pill so hue is
   never the only channel */
.score-dot {
  width: var(--dot-score); height: var(--dot-score);
  border-radius: 50%; flex-shrink: 0; opacity: .9;
}
.score-dot.r1 { background: var(--rate-1); }
.score-dot.r2 { background: var(--rate-2); }
.score-dot.r3 { background: var(--rate-3); }
.score-dot.r4 { background: var(--rate-4); }
.score-dot.r5 { background: var(--rate-5); }
.score-dot.r6 { background: var(--rate-6); }
.score-dot.r7 { background: var(--rate-7); }

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: var(--r-pill);
  background: var(--grey-300); color: var(--ink);
  font-size: var(--b3); font-weight: var(--w-medium);
}


/* ── ITEM SCAFFOLDING + ESSENCE BLOCK ────────────────────────────────────
   The essence block is the most common component in the build — an expandable
   summary under an item row. It appears in 11 of 17 modules. */
.item-list { margin-top: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-4); position: relative; }
.item-list.two-up { display: grid; grid-template-columns: repeat(2, 1fr); }

.item-title   { display: inline-flex; align-items: baseline; gap: 6px; min-width: 0; flex-wrap: wrap; }
.item-actions { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }

.essence { flex: 1; min-width: 0; }
.essence-body { display: flex; flex-direction: column; gap: 10px; margin: 8px 0 4px; }
.essence-bullets {
  list-style: disc; margin: 0; padding-left: var(--sp-4);
  display: flex; flex-direction: column; gap: 4px;
}
/* the expand/collapse control — same geometry as .btn-icon, muted by default */
.essence-btn {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: var(--ctrl-md); height: var(--ctrl-md);
  border: none; cursor: pointer; border-radius: 50%;
  background: var(--grey-300); color: var(--muted);
  transition: background var(--dur-micro) ease, color var(--dur-micro) ease;
}
.essence-btn:hover { background: var(--muted); color: var(--white); }
.essence-btn svg { width: var(--ctrl-md-icon); height: var(--ctrl-md-icon); }

.section-label {
  font-size: var(--b3); font-weight: var(--label-w);
  text-transform: uppercase; letter-spacing: var(--label-ls); color: var(--muted);
}

.footer { padding: 10px 14px; }


/* ── CONTROLS ─────────────────────────────────────────────────────────────
   Three sizes only (--ctrl-sm/md/lg). Never a fourth. Never a bare px. */
.btn-icon {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: var(--ctrl-md); height: var(--ctrl-md);
  border-radius: 50%; border: none; cursor: pointer;
  background: var(--grey-200); color: var(--ink);
  transition: background var(--dur-micro) ease, color var(--dur-micro) ease;
}
.btn-icon:hover { background: var(--grey-300); }
/* glyph is deliberately one tier below the button: a 9px mark in a 24px target,
   hairline stroke. Verbatim from .topbar-btn (app-shell) and .essence-btn. */
.btn-icon svg { width: var(--ctrl-sm-icon); height: var(--ctrl-sm-icon); stroke: currentColor; fill: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; }

.btn-icon.ghost { background: transparent; border: 1px solid var(--grey-400); color: var(--muted); }
.btn-icon.ghost:hover { background: var(--grey-200); border-color: var(--muted); color: var(--ink); }

.btn-icon.sm { width: var(--ctrl-sm); height: var(--ctrl-sm); }
.btn-icon.sm svg { width: calc(var(--ctrl-sm-icon) * .8); height: calc(var(--ctrl-sm-icon) * .8); }
.btn-icon.lg { width: var(--ctrl-lg); height: var(--ctrl-lg); }
.btn-icon.lg svg { width: var(--ctrl-lg-icon); height: var(--ctrl-lg-icon); }

/* segmented view toggle */
.view-toggle {
  display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0;
  padding: 2px; border-radius: var(--r-pill); background: var(--grey-200);
}
.view-btn {
  border: none; cursor: pointer; background: transparent; color: var(--muted);
  padding: 4px 12px; border-radius: var(--r-pill);
  font-family: var(--font); font-size: var(--b4); font-weight: var(--w-medium);
  text-transform: uppercase; letter-spacing: var(--label-ls);
  transition: background var(--dur-micro) ease, color var(--dur-micro) ease;
}
.view-btn.active { background: var(--ink-900); color: var(--white); }

/* standalone pill toggle — more common than the segmented group (6 modules) */
.view-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 12px; border-radius: var(--r-pill);
  border: none; cursor: pointer;
  background: var(--grey-200); color: var(--muted);
  font-family: var(--font); font-size: var(--b4); font-weight: var(--w-medium);
  text-transform: uppercase; letter-spacing: var(--label-ls);
  transition: background var(--dur-micro) ease, color var(--dur-micro) ease;
}
.view-pill.active { background: var(--ink-900); color: var(--white); }

/* horizontally scrollable control strip inside a card — scrollbar hidden */
.card-ctrl-row {
  display: flex; flex-wrap: nowrap; align-items: center; justify-content: space-between;
  gap: 6px; margin-bottom: var(--sp-3);
  overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
}
.card-ctrl-row::-webkit-scrollbar { display: none; }


/* ── GRAPH / DATA VIZ ─────────────────────────────────────────────────────
   Marks, not controls — sized off --bar-track-* and --dot-scale on purpose. */
.graph { position: relative; color: var(--ink); }

.graph-track-row {
  position: relative; display: flex; align-items: flex-end; gap: 6px;
  width: 100%; height: var(--bar-track-h-lg);
}
.graph-track-row::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  border-top: 1px dashed var(--grey-400); pointer-events: none;
}
.graph-track-row.sm { height: var(--bar-track-h-sm); }

/* NAME COLLISION, resolved in favour of production (V1.2):
   in the shipped modules `.graph-line` and `.graph-bars` are VIEW CONTAINERS
   toggled against each other by a parent state class — not bar rows.
   A bar row is `.graph-track-row`. Do not reuse `.graph-bars` for a row. */
.graph-line, .graph-bars {
  display: none; flex-direction: column; gap: 8px;
  width: 100%; height: 100%;
}
.graph:not([data-view="bars"]) .graph-line { display: flex; }
.graph[data-view="bars"]   .graph-bars { display: flex; }

/* A track is an empty column. The FILL is a separate absolutely-positioned
   element inside it — a track alone renders no data. */
.bar-track {
  position: relative;
  width: var(--bar-track-w-lg); height: 100%;
  border-radius: var(--r-pill);
  background: var(--grey-300); flex-shrink: 0;
}
.graph-track-row.sm .bar-track { width: var(--bar-track-w-sm); }

/* THE COLUMN WRAPPER. A fixed-width track inside a flex row does NOT line up
   with the flex:1 label columns below it — the bars bunch to the left. Every
   track sits inside a .graph-day. Omitting it is the defect this file shipped
   with in V1.1; only a screenshot catches it. */
.graph-day {
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-end;
  flex: 1; min-width: 0; height: 100%;
}

.bar-pill-fill {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: var(--dot-scale);
  border-radius: var(--r-pill);
}

.scale-dot {
  width: var(--dot-scale); height: var(--dot-scale);
  border-radius: 50%; background: var(--grey-300); flex-shrink: 0;
}
.card-body .scale-dot { background: rgba(255,255,255,.16); }
.card-body .graph      { color: rgba(255,255,255,.55); }

.graph-label { font-size: var(--b4); color: var(--muted); }


/* ── APP SHELL ────────────────────────────────────────────────────────────
   Sidebar collapses to width 0 rather than unmounting, so the transition
   slides rather than reflowing. */
.shell { display: flex; height: 100vh; position: relative; }

.sidebar {
  width: var(--sidebar-w); flex-shrink: 0;
  background: var(--surface);
  display: flex; flex-direction: column;
  height: 100vh; overflow-y: auto; overflow-x: hidden;
  padding: 0 14px 20px;
  border-right: var(--divider);
  transition: width var(--dur-micro) ease, padding var(--dur-micro) ease, border-color var(--dur-micro) ease;
}
.sidebar.collapsed { width: 0; padding-left: 0; padding-right: 0; border-right-color: transparent; }

/* the header band matches --topbar-h exactly so the sidebar title and the
   topbar toggle share one baseline. Gap below is margin, never padding:
   border-box padding would eat the band and break that alignment. */
.sidebar-header { min-height: var(--topbar-h); display: flex; align-items: center; }

.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--r-md);
  text-decoration: none; color: var(--ink);
  font-size: 13px; font-weight: var(--w-medium); white-space: nowrap;
  transition: background var(--dur-micro) ease, color var(--dur-micro) ease;
}
.nav-item svg { width: var(--ctrl-sm); height: var(--ctrl-sm); stroke: var(--muted); flex-shrink: 0; transition: stroke var(--dur-micro) ease; }
.nav-item:hover { background: var(--grey-200); }
.nav-item.active { background: var(--ink); color: var(--white); }
.nav-item.active svg { stroke: var(--white); }

.topbar { height: var(--topbar-h); display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }

.main { flex: 1; height: 100vh; overflow: hidden; position: relative; background: var(--bg); display: flex; flex-direction: column; }
.main iframe { width: 100%; height: 100%; border: none; display: block; }




/* ============================================================
   V1.2 — SHARED VOCABULARY THE FIRST PASS MISSED
   Every rule below is lifted from the shipped modules, majority body wins.
   The module count in each comment is how many of the 20 modules use it.
   ============================================================ */

/* --- icon glyph inside any circular control (9 modules) -------------- */
.essence-btn .oi,
.item-add-btn .oi,
.lede-toggle-btn .oi,
.dash-toggle-btn .oi { width: var(--ctrl-md-icon); height: var(--ctrl-md-icon); }

/* --- item secondary line (8 modules) --------------------------------- */
.item-current {
  font-size: var(--b3); font-weight: var(--w-regular); color: var(--muted);
}
.card-head .item-name,
.card-head .item-current { align-self: center; }
.card-head .item-current { color: rgba(255,255,255,.55); }

/* --- add button (5 modules) ------------------------------------------ */
.item-add-btn {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  width: var(--ctrl-md); height: var(--ctrl-md);
  border-radius: 50%;
  background: transparent; border: 1px solid var(--grey-400);
  color: var(--muted);
  transition: background var(--dur-micro) ease, border-color var(--dur-micro) ease;
}
.item-add-btn:hover { background: var(--white); border-color: var(--muted); }

/* --- numbered marker (4 modules) ------------------------------------- */
.item-num {
  flex-shrink: 0;
  width: var(--ctrl-md); height: var(--ctrl-md);
  border-radius: 50%;
  background: var(--grey-400); color: var(--ink);
  font-size: var(--b3); font-weight: var(--w-semibold);
  display: inline-flex; align-items: center; justify-content: center;
  align-self: center;
}
.card-head .item-num { background: rgba(255,255,255,.14); color: var(--white); }
.item-title.wraps .item-num { align-self: flex-start; margin-top: 2px; }

/* --- chapter block + its pill title (4 / 3 modules) ------------------- */
.chapter {
  display: flex; flex-direction: column; gap: 8px;
  background: transparent;
  border: 1px solid var(--grey-400); border-radius: var(--r-sm);
  padding: 12px 14px;
}
.chapter-title {
  display: inline-block; align-self: flex-start;
  font-size: var(--b3); font-weight: var(--w-semibold); color: var(--ink);
  text-transform: uppercase; letter-spacing: .06em;
  background: var(--grey-400); border-radius: var(--r-pill);
  padding: 4px 10px;
}

/* --- svg chart holder (4 modules) ------------------------------------ */
.chart-wrap { display: flex; align-items: center; justify-content: center; }
.chart-wrap svg { width: 100%; height: auto; display: block; max-width: 160px; }

/* --- graph sizes + overlay (4 / 3 modules) --------------------------- */
.graph-lg { display: block; width: 100%; }
.graph-sm { display: block; width: 100%; color: var(--white); }
.graph-sm .bar-track { width: var(--bar-track-w-sm); height: auto; flex: 1; min-height: 0; }
.graph-sm .bar-value, .graph-sm .bar-date { color: rgba(255,255,255,.62); }
.graph-connector {
  position: absolute; inset: 0; overflow: visible; pointer-events: none;
}
.graph-caption { font-size: var(--b3); color: var(--muted); }

/* --- graph axis labels (3 modules) ----------------------------------- */
.bar-value-row, .bar-date-row { display: flex; gap: 6px; width: 100%; }
.bar-value {
  flex: 1; text-align: center;
  font-size: var(--b4); font-weight: var(--w-medium); color: var(--muted);
  white-space: nowrap;
}
.bar-date {
  flex: 1; display: flex; flex-direction: row;
  align-items: center; justify-content: center; gap: 3px;
  font-size: var(--b4); line-height: 1.2; color: var(--muted);
  white-space: nowrap;
}
.card-body .bar-value, .card-body .bar-date { color: rgba(255,255,255,.55); }

/* --- segmented toggle (3 modules) ------------------------------------ */
.spark-toggle {
  display: inline-flex; background: var(--grey-400);
  border-radius: var(--r-pill); padding: 2px; gap: 2px; flex-shrink: 0;
}
.spark-toggle button {
  border: none; background: transparent; cursor: pointer;
  font-family: var(--font); font-size: var(--b3);
  font-weight: var(--w-medium); color: var(--muted);
  padding: 2px 10px; border-radius: var(--r-pill);
}
.spark-toggle button.active { background: var(--ink-900); color: var(--white); }
.card-ctrl-row .spark-toggle { padding: 1.5px; gap: 1.5px; }
.card-ctrl-row .spark-toggle button {
  padding: 2px 6px; font-size: calc(var(--b3) * .88); white-space: nowrap;
}

/* --- scale-dot on state (3 modules) ---------------------------------- */
.scale-dot.on, .bar-dot.on, .pg-scale-dot.on { opacity: 1; }

/* --- shadow bullet (3 modules) --------------------------------------- */
.essence-bullets li.shadow { color: var(--func-danger); }

/* ── MOBILE ───────────────────────────────────────────────────────────────
   Sidebar becomes an overlay drawer; cards go full width. */
@media (max-width: 640px) {
  .wrap  { padding: 14px 14px 76px; }
  .hero  { padding: 28px; margin-bottom: 22px; flex-direction: column; gap: var(--sp-5); }
  .hero-legend { gap: 13px; }
  .card  { flex-basis: 100%; padding: 9px; }
  .card-head { gap: 12px; position: relative; }
  .item-list.two-up { grid-template-columns: 1fr; }
  .essence-body { gap: 8px; margin: 6px 0 2px; }
  .graph-track-row { gap: 4px; }
  .footer { padding: 10px 14px; }
}

/* the shell's drawer switch is a LAYOUT change, not a scale change — it fires
   at its own breakpoint (767px), matching app-shell. */
@media (max-width: 767px) {
  .sidebar {
    position: fixed; top: 0; left: 0; z-index: 20;
    width: var(--sidebar-w); padding: 20px 14px;
    transform: translateX(-100%);
    transition: transform .22s ease;
  }
  .sidebar.open { transform: translateX(0); box-shadow: 8px 0 24px rgba(0,0,0,.12); }
  .main { width: 100%; }
}
