/* ============================================================================
   jac-apps design system
   Editorial house style, taken from the mahjong room board: warm paper ground,
   Fraunces for display, brass accent, generous spacing.

   Everything is a token. Components reference tokens, never raw values, so a
   palette change is one block and every tool follows. If you find yourself
   writing a hex code inside a component, add a token instead.

   Page-specific CSS belongs in the page. This file is only what more than one
   tool needs.
   ========================================================================= */

:root{
  /* --- surfaces ------------------------------------------------------- */
  --paper:      #EEE9DF;   /* page ground */
  --paper-2:    #E6E0D4;   /* recessed: image wells, empty states */
  --card:       #F4F0E8;   /* raised: cards, panels */
  --card-hover: #F7F4ED;

  /* --- ink ------------------------------------------------------------ */
  --ink:        #211E19;   /* primary text, dark furniture */
  --ink-2:      #453F36;   /* body copy */
  --label:      #6E5636;   /* captions, axis labels, meta */
  --muted:      #8A8175;   /* de-emphasised */

  /* --- line ----------------------------------------------------------- */
  --hair:       #CBC2B2;   /* borders, rules */
  --hair-soft:  #DFD7C7;   /* interior dividers, table rows */

  /* --- accent + material ---------------------------------------------- */
  --brass:      #A9863F;   /* the accent. links, active states, underlines */
  --brass-dim:  #C0A267;
  --oak:        #C9B79C;
  --camel:      #C0996A;
  --greige:     #A9A296;

  /* --- status --------------------------------------------------------- */
  /* Warmed to sit on paper. The lab tracker's originals were tuned for a cool
     white ground and read as neon here. */
  --ok:         #5A7D52;
  --ok-bg:      #E2E7DA;
  --warn:       #B8892F;
  --warn-bg:    #F2E8D3;
  --bad:        #A8443A;
  --bad-bg:     #F2E0DC;
  --neutral-bg: #E6E0D4;

  /* "Out of range" is not one thing -- a 2% miss and a 200% miss should not
     look alike. --ok and --bad are the ends; these two are the middle. */
  --sev-mild:   #C9A227;
  --sev-mod:    #C1743A;

  /* --- series ---------------------------------------------------------- */
  /* Categorical chart colours, muted for the paper ground. A canvas cannot use
     var(), so JS reads these with APP.token() -- that is the only way a chart
     stays inside the design system instead of keeping a second palette. */
  --c1: #2F5D7C;   --c2: #A8443A;   --c3: #5A7D52;   --c4: #B8892F;
  --c5: #6B4E7D;   --c6: #2E7D77;   --c7: #A34E72;   --c8: #7A6A4F;

  /* --- chart furniture -------------------------------------------------- */
  /* Translucent, so they sit on whatever surface the chart is drawn over. */
  --grid:      rgba(33,30,25,.07);
  --crosshair: rgba(33,30,25,.32);
  --ok-line:   rgba(90,125,82,.55);    /* reference-range dashes */
  --ok-fill:   rgba(90,125,82,.08);    /* the band between them */
  --bad-line:  rgba(168,68,58,.60);    /* a limit you should not cross */

  /* --- tooltip ---------------------------------------------------------- */
  /* The one place ink and paper invert, so it reads as floating above. */
  --tip-bg:  rgba(33,30,25,.95);
  --tip-ink: #F4F0E8;
  --tip-dim: #B7AE9E;

  --brass-bg: #EFE6D0;   /* tinted ground for a brass-keyed pill */

  /* --- type ----------------------------------------------------------- */
  /* Swap these two for self-hosted woff2 later and nothing else changes. */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-num: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  --fs-xs:   11.5px;
  --fs-sm:   13px;
  --fs-base: 15px;
  --fs-md:   16px;
  --fs-lg:   18px;
  --fs-h3:   21px;
  --fs-h2:   clamp(24px, 4vw, 34px);
  --fs-h1:   clamp(34px, 8vw, 60px);

  /* --- space ---------------------------------------------------------- */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 22px; --s6: 30px; --s7: 44px; --s8: 64px;

  /* --- shape ---------------------------------------------------------- */
  --r-sm: 3px;
  --r:    5px;
  --r-lg: 10px;
  --r-pill: 999px;
  --lift: 0 1px 3px rgba(33,30,25,.07);
  --lift-2: 0 3px 10px rgba(33,30,25,.10);

  --wrap: 960px;
  /* A dense grid of small tiles wants more room than a column of prose does. */
  --wrap-wide: 1180px;
}

/* ============================================================================
   base
   ========================================================================= */
*{ box-sizing:border-box }
html{ -webkit-text-size-adjust:100% }
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--font-ui);
  font-size:var(--fs-md);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  -webkit-tap-highlight-color:transparent;
}
a{ color:inherit }
img{ max-width:100% }

/* viewport-fit=cover in the page's meta tag is what makes these insets real */
.wrap{
  max-width:var(--wrap); margin:0 auto;
  padding-left:max(var(--s5), env(safe-area-inset-left));
  padding-right:max(var(--s5), env(safe-area-inset-right));
}
.wrap.wide{ max-width:var(--wrap-wide) }

h1,h2,h3{ font-family:var(--font-display); font-weight:500; margin:0; letter-spacing:-.01em }
h1{ font-size:var(--fs-h1); line-height:1.0 }
h2{ font-size:var(--fs-h2); line-height:1.1 }
h3{ font-size:var(--fs-h3); line-height:1.15 }
h1 em{ font-style:italic; font-weight:400 }

.label{ font-size:var(--fs-sm); color:var(--label); letter-spacing:.02em }
.meta { font-size:var(--fs-xs); color:var(--muted) }
.note { font-size:var(--fs-sm); color:var(--label) }
.rule { height:1px; background:var(--hair); border:0; margin:0 }
.brassbar{ width:52px; height:2px; background:var(--brass) }
.num  { font-variant-numeric:tabular-nums }

/* ============================================================================
   app bar  -- the shell every tool shares
   ========================================================================= */
.appbar{
  position:sticky; top:0; z-index:50;
  background:color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter:saturate(1.4) blur(8px);
  border-bottom:1px solid var(--hair);
  padding-top:env(safe-area-inset-top);
}
.appbar-in{
  display:flex; align-items:center; gap:var(--s3);
  min-height:52px;
}
.appbar .home{
  display:inline-flex; align-items:center; gap:6px;
  font-size:var(--fs-sm); font-weight:500; color:var(--label);
  text-decoration:none; padding:6px 0;
}
.appbar .home:hover{ color:var(--ink) }
/* Right-alignment is .end's job, not .title's -- a tool with no hub link above
   it still wants its title on the left. */
.appbar .title{
  font-family:var(--font-display); font-size:var(--fs-md); font-weight:500;
  color:var(--ink);
}

/* ============================================================================
   tabs  -- switching views inside one tool. Lives in the app bar, so it stays
   reachable once the masthead has scrolled away.
   ========================================================================= */
.tabs{ display:flex; gap:var(--s5); overflow-x:auto; scrollbar-width:none }
.tabs::-webkit-scrollbar{ display:none }
.tab{
  padding:9px 0; border:0; background:none; cursor:pointer; white-space:nowrap;
  font-family:var(--font-ui); font-size:var(--fs-sm); font-weight:500;
  color:var(--muted); border-bottom:2px solid transparent;
}
.tab:hover{ color:var(--ink-2) }
.tab.on{ color:var(--ink); border-bottom-color:var(--brass) }

/* ============================================================================
   page head  -- heading left, aside right, stacks on narrow
   ========================================================================= */
.head{
  display:flex; align-items:baseline; justify-content:space-between;
  gap:var(--s4); margin-bottom:var(--s5);
}
.head .note{ text-align:right; max-width:30ch }
@media (max-width:640px){
  .head{ flex-direction:column; gap:var(--s1) }
  .head .note{ text-align:left }
}

.section{ padding:var(--s7) 0 }

/* ============================================================================
   cards + grid
   ========================================================================= */
.grid{ display:grid; gap:var(--s4); grid-template-columns:repeat(auto-fill, minmax(240px,1fr)) }
/* many small readings at a glance, rather than a few things to read */
.grid.dense{ gap:var(--s2); grid-template-columns:repeat(auto-fill, minmax(158px,1fr)) }
.grid-2{ display:grid; gap:var(--s5); grid-template-columns:1fr 1fr }
@media (max-width:640px){ .grid-2{ grid-template-columns:1fr } }

.card{
  background:var(--card); border:1px solid var(--hair); border-radius:var(--r);
  padding:var(--s5); min-width:0;
}
.card.pad-0{ padding:0; overflow:hidden }
.card.tight{ padding:var(--s3) var(--s4) }
.card.pending{ border-style:dashed; background:transparent }

/* a card that is itself a link */
a.card{ display:block; text-decoration:none; color:inherit;
        transition:border-color .15s ease, background .15s ease }
a.card:hover{ border-color:var(--brass); background:var(--card-hover) }
a.card:active{ transform:scale(.995) }

.card .ey{ font-size:var(--fs-sm); color:var(--label); margin-bottom:var(--s2) }
.card .spec{ font-size:var(--fs-sm); color:var(--label); margin-top:var(--s1) }
.card p{ font-size:var(--fs-base); color:var(--ink-2); margin:var(--s3) 0 0 }

/* ============================================================================
   stat tiles  -- the lab tracker's summary row, reusable for any metric
   ========================================================================= */
.stats{ display:grid; gap:var(--s2); grid-template-columns:repeat(auto-fit, minmax(112px,1fr)) }
.stat{ background:var(--card); border:1px solid var(--hair); border-radius:var(--r); padding:var(--s3) var(--s4); min-width:0 }
.stat .k{ font-size:var(--fs-xs); color:var(--label); text-transform:uppercase; letter-spacing:.05em; margin-bottom:2px }
.stat .v{ font-size:var(--fs-lg); font-weight:600; font-variant-numeric:tabular-nums; overflow-wrap:anywhere }
.stat .v.sm{ font-size:var(--fs-base); font-weight:500 }

/* big editorial figure, for hero numbers */
.figure .n{ font-family:var(--font-display); font-size:30px; font-weight:500; line-height:1 }
.figure .l{ font-size:var(--fs-sm); color:var(--label); margin-top:2px }

/* ============================================================================
   panels + tables
   ========================================================================= */
.panel{ background:var(--card); border:1px solid var(--hair); border-radius:var(--r); overflow:hidden }
.panel-title{
  font-size:var(--fs-xs); font-weight:700; color:var(--label);
  text-transform:uppercase; letter-spacing:.06em;
  padding:var(--s3) var(--s4); border-bottom:1px solid var(--hair-soft);
}
.panel-title .n{ font-weight:400; text-transform:none; letter-spacing:0; color:var(--muted) }

/* wide tables scroll inside the panel; the page never scrolls sideways */
.tscroll{ overflow-x:auto; -webkit-overflow-scrolling:touch }
table{ width:100%; border-collapse:collapse; font-size:var(--fs-base) }
th{
  padding:var(--s2) var(--s3); text-align:left; white-space:nowrap;
  font-size:var(--fs-xs); font-weight:600; color:var(--label);
  text-transform:uppercase; letter-spacing:.05em;
  border-bottom:1px solid var(--hair); background:var(--card);
}
td{ padding:var(--s3); border-bottom:1px solid var(--hair-soft); color:var(--ink-2) }
tr:last-child td{ border-bottom:none }
td.num, th.num{ text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap }

/* ============================================================================
   badges + pills
   ========================================================================= */
.badge{
  display:inline-block; padding:2px 9px; border-radius:var(--r-pill);
  font-size:var(--fs-xs); font-weight:600; white-space:nowrap;
}
.badge-ok  { background:var(--ok-bg);      color:var(--ok) }
.badge-warn{ background:var(--warn-bg);    color:var(--warn) }
.badge-bad { background:var(--bad-bg);     color:var(--bad) }
.badge-na  { background:var(--neutral-bg); color:var(--muted) }

.pills{ display:flex; gap:var(--s2); flex-wrap:wrap }
.pill{
  padding:6px 14px; border-radius:var(--r-pill); font-size:var(--fs-sm); font-weight:500;
  border:1.5px solid transparent; cursor:pointer; user-select:none; white-space:nowrap;
  background:var(--neutral-bg); color:var(--label);
}
.pill.on{ border-color:var(--ink); color:var(--ink) }
.pill-ok { background:var(--ok-bg);   color:var(--ok) }
.pill-ok.on { border-color:var(--ok) }
.pill-bad{ background:var(--bad-bg);  color:var(--bad) }
.pill-bad.on{ border-color:var(--bad) }
.pill-brass{ background:var(--brass-bg); color:var(--label) }
.pill-brass.on{ border-color:var(--brass) }

/* ============================================================================
   controls
   ========================================================================= */
.bar{ display:flex; flex-wrap:wrap; gap:var(--s2); align-items:center }

.btn{
  padding:8px 14px; border-radius:var(--r); border:1px solid var(--hair);
  background:var(--card); color:var(--ink);
  font-family:var(--font-ui); font-size:var(--fs-sm); font-weight:500; cursor:pointer;
}
.btn:hover{ border-color:var(--brass) }
/* .on = a toggle that is currently engaged. .primary = the one action on the
   page worth pointing at. Different jobs, so different looks. */
.btn.on{ background:var(--ink); color:var(--card); border-color:var(--ink) }
.btn.primary{ background:var(--brass); border-color:var(--brass); color:var(--card) }
.btn.primary:hover{ background:var(--ink); border-color:var(--ink) }
.btn.sm{ padding:5px 11px; font-size:var(--fs-xs) }

/* segmented control -- modes of one view, not separate actions */
.seg{ display:flex; gap:2px; background:var(--neutral-bg); border-radius:var(--r); padding:3px }
.seg button{
  border:0; background:none; cursor:pointer; border-radius:var(--r-sm); padding:5px 12px;
  font-family:var(--font-ui); font-size:var(--fs-sm); font-weight:500; color:var(--label);
}
.seg button.on{ background:var(--card); color:var(--ink); box-shadow:var(--lift) }

/* the board's underlined outbound link */
.buy{
  display:inline-block; font-size:var(--fs-base); font-weight:500;
  color:var(--ink); text-decoration:none;
  border-bottom:2px solid var(--brass); padding-bottom:2px;
}
.buy:hover{ border-color:var(--ink) }

/* checklist -- multi-select when there are too many options for pills */
.checklist{
  max-height:230px; overflow-y:auto; -webkit-overflow-scrolling:touch;
  background:var(--card); border:1px solid var(--hair); border-radius:var(--r);
}
.check{
  display:flex; align-items:center; gap:var(--s3); cursor:pointer;
  padding:9px var(--s4); font-size:var(--fs-base); color:var(--ink-2);
  border-bottom:1px solid var(--hair-soft);
}
.check:last-child{ border-bottom:none }
.check input{ width:17px; height:17px; flex-shrink:0; accent-color:var(--brass) }
.check .p{
  margin-left:auto; font-size:var(--fs-xs); color:var(--muted);
  text-transform:uppercase; letter-spacing:.04em; white-space:nowrap;
}

input[type=text], input[type=search], select{
  padding:9px 11px; border:1px solid var(--hair); border-radius:var(--r);
  background:var(--card); color:var(--ink);
  font-family:var(--font-ui); font-size:var(--fs-md);   /* 16px: stops iOS zooming on focus */
  min-width:0;
}
input:focus, select:focus{ outline:none; border-color:var(--brass) }

/* ============================================================================
   chart shell
   ========================================================================= */
.chart{
  position:relative; width:100%; height:300px;
  background:var(--card); border:1px solid var(--hair); border-radius:var(--r);
  padding:var(--s3); overflow:hidden;
}
@media (min-width:700px){ .chart{ height:380px } }
/* pan-y hands vertical drags back to the page. Never use touch-action:none on a
   full-width canvas -- it freezes scrolling when a thumb lands on it. */
.chart canvas{ touch-action:pan-y }

/* Floating tooltip. Chart.js's own tooltip cannot report series of unequal
   length, so tools resolve their own rows and render them into this. */
.tip{
  position:absolute; z-index:200; pointer-events:none; opacity:0;
  transition:opacity .08s linear;
  background:var(--tip-bg); color:var(--tip-ink);
  border-radius:var(--r); padding:var(--s2) var(--s3);
  font-size:var(--fs-sm); line-height:1.5; box-shadow:var(--lift-2); max-width:78vw;
}
.tip .tip-h{ font-weight:700; margin-bottom:5px }
.tip .tip-r{ display:flex; align-items:center; gap:7px; white-space:nowrap }
.tip .tip-d{ width:8px; height:8px; border-radius:50%; flex-shrink:0 }
.tip .tip-n{ overflow:hidden; text-overflow:ellipsis; max-width:46vw }
.tip .tip-v{ margin-left:auto; font-weight:600; font-variant-numeric:tabular-nums }
.tip .dim{ color:var(--tip-dim); font-weight:400 }

.legend{ display:flex; gap:var(--s4); flex-wrap:wrap; font-size:var(--fs-xs); color:var(--label); margin-bottom:var(--s2) }
.legend span{ display:flex; align-items:center; gap:5px }
.dot{ width:9px; height:9px; border-radius:50%; display:inline-block; flex-shrink:0 }

/* ============================================================================
   swatches
   ========================================================================= */
.swatches{ display:grid; grid-template-columns:repeat(6,1fr); gap:var(--s3) }
@media (max-width:640px){ .swatches{ grid-template-columns:repeat(3,1fr) } }
/* a defined edge, because a chip whose fill matches --paper is otherwise invisible */
.sw .chip{ height:96px; border-radius:var(--r-sm); border:1px solid rgba(33,30,25,.18); box-shadow:var(--lift) }
.sw .nm{ font-size:var(--fs-sm); font-weight:500; margin-top:var(--s2) }
.sw .hx{ font-size:var(--fs-xs); color:var(--label) }

/* ============================================================================
   foldout  -- a section worth keeping but not worth reading. The reasoning
   behind a decision, the route that got there, the build order: a reader who
   wants it should find it, and a reader who does not should not have to scroll
   past it. Native <details>, so it costs no JS, keeps keyboard and screen
   reader behaviour, and the summary IS the heading -- do not put an h2 inside.
   ========================================================================= */
.foldout{ border-top:1px solid var(--hair); padding-top:var(--s5) }
.foldout > summary{
  display:inline-flex; align-items:center; gap:var(--s2);
  padding:8px 16px 8px 14px; border:1px solid var(--hair); border-radius:999px;
  background:var(--card); color:var(--ink);
  font-family:var(--font-ui); font-size:var(--fs-sm); font-weight:500;
  cursor:pointer; list-style:none; user-select:none;
  transition:border-color .15s ease, background .15s ease;
}
/* both, or Safari keeps its own triangle */
.foldout > summary::-webkit-details-marker{ display:none }
.foldout > summary::marker{ content:"" }
.foldout > summary:hover{ border-color:var(--brass); background:var(--card-hover) }
.foldout > summary:focus-visible{ outline:2px solid var(--brass); outline-offset:2px }
.foldout-chev{ color:var(--label); transition:transform .15s ease; font-size:11px }
.foldout[open] > summary .foldout-chev{ transform:rotate(90deg) }
.foldout-tag{
  color:var(--label); font-size:var(--fs-xs); font-weight:400;
  padding-left:var(--s2); border-left:1px solid var(--hair);
}
.foldout-body{ padding-top:var(--s5) }

/* ============================================================================
   misc
   ========================================================================= */
.empty{ padding:var(--s7) var(--s4); text-align:center; color:var(--muted); font-size:var(--fs-base) }
footer{ padding:var(--s7) 0 calc(var(--s7) + env(safe-area-inset-bottom)); color:var(--label); font-size:var(--fs-sm) }

/* Value colouring. Which direction counts as good is the tool's business --
   a rising LDL is bad, a rising balance is not -- so these only define the look. */
.good{ color:var(--ok);  font-weight:600 }
.bad { color:var(--bad); font-weight:600 }
.flat{ color:var(--muted) }

.end{ margin-left:auto }

.hide{ display:none !important }
@media (max-width:640px){ .hide-sm{ display:none !important } }
