/* =============================================================
   Shared responsive layout: single source of truth for how wide
   the content column gets on each screen. Linked in the <head> of
   every dashboard page (render-blocking, so no width flash).

   The whole app used to hard-cap at a 760px mobile column, so on a
   laptop or the 49" office monitor it was a thin strip down the
   middle. This widens the column by screen size and lets the card
   stacks reflow into columns, while phones keep the 760px feel.

   Pure CSS, no JS device detection, no build step. To retune every
   page at once, change the numbers here and nothing else.

   Tiers (viewport width -> content column width):
     phone / iPad portrait   < 1080px   760px   (unchanged)
     laptop                 >= 1080px  1040px
     large laptop / desktop >= 1440px  1240px
     49" office monitor     >= 2000px  1560px
   ============================================================= */

:root { --content-max: 760px; }
/* Above tablet, the dashboard fills the FULL screen width edge to edge - the
   only gutter is each page's own small body padding. Phones keep the 760px
   reading width. (Was 95vw, which left a too-wide margin on big monitors.) */
@media (min-width: 1080px) { :root { --content-max: 100%; } }

/* ---- Bento grid: a single card stack on phones that reflows into an
   ALIGNED multi-column grid on wide screens.

   This used to be CSS multicol (column-count), which is the wrong tool for
   a tile dashboard: it flows top-to-bottom down column 1 THEN column 2, so
   the reading order scrambles on a wide screen (card 5 lands top-right next
   to card 1), and tile heights can't be reasoned about. A grid keeps the
   natural left-to-right, top-to-bottom order, never splits a card, lets
   conditionally-hidden (display:none) cards drop out cleanly, and aligns
   tiles to the top of their row so a short tile doesn't stretch.

   minmax(0,1fr) (not 1fr) lets a tile shrink below its content's intrinsic
   width so long unbroken strings can't blow the column out. Cards drop their
   own margin-bottom inside the grid: `gap` owns the spacing now. ---- */
.dash-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  align-items: start;
  grid-auto-flow: row dense;
}
.dash-cols > * { break-inside: avoid; margin-bottom: 0; }
@media (min-width: 1080px) {
  .dash-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}
@media (min-width: 1500px) {
  .dash-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---- Tile-size hierarchy: a content-heavy tile (the morning briefing, the
   weekly review) spans the full row so it reads as a band, while compact
   status tiles stay one column and `dense` flow packs them tight into the
   gaps. On phones everything is one column so the span is a no-op. ---- */
@media (min-width: 1080px) {
  .tile-wide { grid-column: 1 / -1; }
}

/* ---- Two-up: a pair that stacks on phones and sits side by side on
   wide screens (e.g. Today / Plan tomorrow, water tracker / history). ---- */
@media (min-width: 1080px) {
  .two-up {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    align-items: start;
  }
}

/* ---- The two bars at the top of every page, held from the first paint ----
   nav.js and topbar.js are deferred and insert their bars at the top of
   <body> when they run. Since the font stopped blocking paint (66883c0) the
   first paint usually comes before that, so every page painted without them
   and dropped 102 to 108 px when they landed: the home page's hero row, 0.05
   of layout shift on every load, and more on a slow network. The bars'
   heights live here, each bar holds at least its height (min-height in
   nav.js and topbar.js), and until a bar is in the page an empty block of its
   height stands in for it. topbar.js runs first and inserts above the
   content, then nav.js inserts above the topbar, so the stand-in is both
   heights, then the nav's, then gone. Every page that links this sheet loads
   both scripts (lf-chrome-reserve.test.mjs).
   The heights are the bars' own: nav 4 + 4 + chip + 4 + 4 px + a 1 px rule,
   its top padding growing with a notch as nav.js's does, plus up to 18 px
   more under a status bar so the chips clear iOS 26's top-edge haze
   (Louis, 24/09/2026; 0 on a desktop, which has no inset); topbar 6 + 4 + pill
   + 4 + 6 px + 1. A touch screen gives both 44 px hit rows (36 and 34 px
   chips), and a phone narrower than 481 px shrinks the topbar's pills. */
:root {
  --lf-nav-h: calc(47px + max(4px, env(safe-area-inset-top, 0px) - 4px) + min(18px, env(safe-area-inset-top, 0px)));
  --lf-topbar-h: 55px;
}
@media (max-width: 480px) { :root { --lf-topbar-h: 51px; } }
@media (pointer: coarse) {
  :root { --lf-nav-h: calc(49px + max(4px, env(safe-area-inset-top, 0px) - 4px) + min(18px, env(safe-area-inset-top, 0px))); --lf-topbar-h: 55px; }
}
body::before { content: ''; display: block; height: calc(var(--lf-nav-h) + var(--lf-topbar-h)); }
body:has(> #topbar)::before { height: var(--lf-nav-h); }
body:has(> #dash-nav)::before { content: none; }
