/* Dosina - single stylesheet. Dark theme by default; the light one comes in with
   data-theme="light" on <html>. Who decides the theme is the app (js/app.js): with
   "System" chosen in You it resolves the system preference and writes the
   attribute; the inline script in index.html does it before the first paint. The
   light tokens are defined ONCE, here. */

:root {
  color-scheme: dark;
  --bg: #0e1420;
  --surface: #151d2c;
  --surface-2: #1d2637;
  --text: #e7ecf4;
  --muted: #a9b6c9;
  --line: #2c3648;
  --accent: #2dd4bf;
  --accent-ink: #04231c;
  --accent-dark: #0b5d53;   /* dark end of the DOSINA brand gradient */

  --safe: #2fbf8f;
  --caution: #e8c33c;      /* yellow: different from the orange of --unsafe */
  --caution-text: #e8c33c; /* the yellow as TEXT only reads on a dark background */
  --unsafe: #e2683c;
  --dangerous: #d93b45;
  --neutral: #7c8ca6;
  --info: #4a90d9;

  /* The timeline names each phase in the colour of its bar, so every hue used as words
     needs its -text twin: on the dark card the raw hue already passes AA, so here the
     twin is the same value (the light theme is where it has to darken). */
  --neutral-text: #7c8ca6;
  --safe-text: #2fbf8f;
  --info-text: #4a90d9;
  --unsafe-text: #e2683c;

  /* Ink of the filled severity labels (AA contrast >= 4.5) */
  --sev-ink-dark: #0d1a16;
  --sev-ink-light: #ffffff;

  --radius: 12px;      /* cards and rows */
  --radius-sm: 8px;    /* chips, fields, buttons (the criterion you set) */
  --radius-xs: 4px;    /* labels, badges and marks */
  --pad: 14px;
  --chrome: 58px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
}

:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f7f8fa;
  --surface: #ffffff;
  --surface-2: #edf0f5;
  --text: #101826;
  --muted: #4c586b;
  --line: #d5dbe4;
  --accent: #0f766e;
  --accent-ink: #ffffff;
  --accent-dark: #06302c;   /* dark end of the brand gradient, light theme */
  --neutral: #6b7a90;
  /* On white the filled yellow does not read as text: dark variant. */
  --caution-text: #7a5c00;
  /* Same rule for the timeline names: each hue darkens until it passes AA as words
     (6.0:1 or better on the white card; the raw hues run 1.7:1 to 4.4:1). */
  --neutral-text: #4f5d73;
  --safe-text: #0f6b4f;
  --info-text: #1b5fa0;
  --unsafe-text: #9c3a12;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  -webkit-text-size-adjust: 100%;
}

/* 100vh BEFORE 100dvh: the last declaration wins. */
#app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.content {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
}

.view {
  padding: var(--pad);
  padding-top: max(var(--pad), env(safe-area-inset-top, 0px));
  padding-bottom: calc(var(--pad) + 8px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 720px;
  margin: 0 auto;
  /* The brand slot (.brandslot) is anchored to this box, not to the header:
     that way the brand falls in the same place on every page. */
  position: relative;
}

.view__head { display: flex; flex-direction: column; gap: 6px; }
/* The title reserves the width of the brand (38px high by the proportion of the SVG). */
.view__title { margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -0.3px; padding-right: 202px; }
/* DOSINA brand slot: it is created by the shell (paintBrandmark in js/app.js) inside
   the container of EACH view, so the brand is drawn once for the whole
   app. Glued to the top-right corner of the content area: top edge
   in the top margin, last letter in the right margin. */
.brandslot {
  position: absolute;
  top: max(var(--pad), env(safe-area-inset-top, 0px));
  right: var(--pad);
  display: block;
  height: 38px;
}
.brandmark { display: block; height: 38px; }
.brandmark svg { display: block; height: 38px; width: auto; }
.brandmark text { font: 800 15px/1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
.brandmark stop:first-child { stop-color: var(--accent); }
.brandmark stop:last-child { stop-color: var(--accent-dark); }
/* On mobile (portrait) the brand moves up 4px, into the gap of the top margin, so that
   it is glued to the top edge. On PC (landscape) it stays in the margin. */
@media (orientation: portrait) {
  .brandslot { top: calc(max(var(--pad), env(safe-area-inset-top, 0px)) - 4px); }
}
.byline { margin: 0; color: var(--accent); font-weight: 600; font-size: 16px; letter-spacing: 0.2px; }
.hint { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.4; }

/* ------------------------------------------------------------------ cards */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.card__title { margin: 0 0 2px; font-size: 16px; font-weight: 700; color: var(--text); }
.body-text { margin: 0; font-size: 15px; line-height: 1.5; white-space: pre-line; color: var(--text); }
.value { font-size: 16px; font-weight: 600; color: var(--accent); }
.tiny { font-size: 13px; line-height: 1.45; margin: 0; }
.muted { color: var(--muted); }
.footnote { font-size: 12.5px; line-height: 1.45; color: var(--muted); padding: 0 2px 6px; }
.src { margin: 0; font-size: 13px; color: var(--muted); word-break: break-word; }

.kv { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; }
.kv__k { color: var(--muted); }
.kv__v { font-weight: 600; text-align: right; }

/* The timeline card goes bold, the weight the dose rows already use: its names carry a
   -text hue, which is dimmer than --muted at 14px, so the colour needs the weight to be
   readable. Total has no colour (it is the sum, not a phase) and goes bold all the same,
   so the card reads as one block. */
.card--timeline .kv__k,
.card--timeline .kv__v { font-weight: 700; }

.bullets { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.bullets li { position: relative; padding-left: 16px; font-size: 14.5px; line-height: 1.45; }
.bullets li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 7px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--dot, var(--accent));
}

.callout {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  background: color-mix(in srgb, var(--callout) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--callout) 38%, transparent);
  border-radius: var(--radius-sm);
  padding: 10px;
}
.callout__icon { color: var(--callout); font-size: 15px; line-height: 1.3; }
.callout__text { font-size: 13.5px; line-height: 1.45; }

.pill {
  display: inline-block;
  border: 1px solid color-mix(in srgb, var(--pill, var(--accent)) 45%, transparent);
  color: var(--pill, var(--accent));
  border-radius: var(--radius-xs);
  padding: 2px 9px;
  font-size: 12px;
  font-weight: 600;
  margin: 2px 4px 2px 0;
  white-space: nowrap;
}
.pill--filled { background: color-mix(in srgb, var(--pill, var(--accent)) 16%, transparent); }

/* Severity label: filled with the level colour and readable ink.
   Green (safe), yellow (caution), orange (unsafe) and red (dangerous). */
.sevbadge {
  display: inline-block;
  background: var(--sev, var(--neutral));
  color: var(--sev-ink, var(--sev-ink-dark));
  border-radius: var(--radius-xs);
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2px;
  white-space: nowrap;
}

.sevlegend { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.sevlegend__arrow { color: var(--muted); font-size: 11px; }

/* -------------------------------------------------------------- controls */

.search {
  width: 100%;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-size: 16px;
  font-family: inherit;
}
.search:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

.chips { display: flex; gap: 8px; flex-wrap: wrap; }
/* The strip is grabbed and dragged with the mouse: open hand, closed while dragging. */
.chips--scroll {
  overflow-x: auto;
  flex-wrap: nowrap;
  padding-bottom: 4px;
  scrollbar-width: none;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}
.chips--scroll::-webkit-scrollbar { display: none; }
.chips--scroll[data-drag='on'] { cursor: grabbing; }
.chips--scroll .chip { cursor: pointer; }

/* PC vs mobile layout: ONLY by orientation. No min-width and no pointer: a
   phone can have more pixels than a PC window, and the pointer changes if
   you plug a mouse in over Bluetooth. Landscape = PC, portrait = mobile. */
@media (orientation: landscape) {
  .view { max-width: 820px; }
}

.chip {
  flex: 0 0 auto;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--muted);
  border-radius: var(--radius-sm);
  padding: 7px 13px;
  font-size: 13.5px;
  font-family: inherit;
  font-weight: 600;
}
.chip--on { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

.btn {
  width: 100%;
  padding: 13px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
}
.btn--primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

.linkbtn {
  background: none;
  border: none;
  color: var(--accent);
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 600;
  padding: 8px 0 0;
  text-align: left;
  align-self: flex-start;
}

.range { width: 100%; accent-color: var(--accent); }
.field { display: flex; flex-direction: column; gap: 4px; }
.rowline { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.rowline > span { display: flex; flex-direction: column; gap: 2px; }
.switch { width: 46px; height: 28px; accent-color: var(--accent); flex: 0 0 auto; }

/* ------------------------------------------------------------------ list */

.list { display: flex; flex-direction: column; gap: 8px; }
.row {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px;
  font-family: inherit;
  color: var(--text);
}
.row__main { display: flex; flex-direction: column; gap: 3px; }
/* The name and its pill ("Popular") are separate items: the name is not glued to it. */
.row__name { font-size: 16.5px; font-weight: 700; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.row__aliases { font-size: 12.5px; color: var(--muted); }
.row__pills { margin-top: 4px; }
.empty { color: var(--muted); text-align: center; padding: 28px 0; font-size: 15px; }

.suggest { display: flex; flex-direction: column; gap: 2px; }
.suggest__item {
  display: flex; flex-direction: column; gap: 2px;
  text-align: left; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 9px 11px; font-family: inherit; color: var(--text);
}
.suggest__name { font-size: 15px; font-weight: 600; }

/* Mix row: the name and its delete button are a single piece, with the
   red bin on the right so that it reads as "this can be removed". */
.pick {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 4px 4px 4px 10px;
}
.pick__name {
  flex: 1; text-align: left; background: none; border: none; color: var(--text);
  font-family: inherit; font-size: 15.5px; font-weight: 600; padding: 12px 0;
  cursor: pointer;
}
.pick__x {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border: 1px solid color-mix(in srgb, var(--dangerous) 50%, transparent);
  background: color-mix(in srgb, var(--dangerous) 12%, transparent);
  color: var(--dangerous);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.pick__x:hover { background: color-mix(in srgb, var(--dangerous) 22%, transparent); }
.pick__x:focus-visible { outline: 2px solid var(--dangerous); outline-offset: 1px; }
.pick__x svg { display: block; }

/* --------------------------------------------------------------- detail */

.detail__head { display: flex; align-items: flex-start; gap: 8px; }
/* The name block reserves the width of the brand, like the view titles. */
.detail__headtext { padding-right: 202px; }
.detail__name { margin: 0; font-size: 22px; font-weight: 700; }
.backbtn {
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text);
  border-radius: var(--radius-sm); width: 38px; height: 38px; font-size: 20px; font-family: inherit; line-height: 1;
  cursor: pointer;
}
.detail__body { display: flex; flex-direction: column; gap: 12px; }

.dose { display: flex; flex-direction: column; gap: 5px; padding: 4px 0; }
.dose__top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.dose__level { font-size: 14px; font-weight: 700; }
.dose__value { font-size: 16px; font-weight: 700; }
.dose__bar { height: 5px; border-radius: 2px; background: color-mix(in srgb, var(--c) 22%, transparent); position: relative; overflow: hidden; }
.dose__bar::after { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--w); background: var(--c); border-radius: 2px; }

.dosecheck { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.dosecheck__out { display: flex; flex-direction: column; gap: 6px; }

.timeline { display: flex; height: 10px; border-radius: 3px; overflow: hidden; margin-top: 4px; }
.timeline__seg { height: 100%; }

.combo { display: flex; flex-direction: column; gap: 3px; padding: 6px 0; border-top: 1px solid var(--line); }
.combo:first-of-type { border-top: none; }
.combo__head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.combo__title, .combo__name { font-size: 15px; font-weight: 700; }
.combo__left { display: flex; flex-direction: column; gap: 2px; }
.combo__note { margin: 0; font-size: 13.5px; color: var(--muted); line-height: 1.45; }

.numbers { display: flex; flex-direction: column; gap: 4px; }
.numbers__row { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
/* The country name is read at a glance: normal text and bigger. */
.numbers__region { font-size: 15px; color: var(--text); }
.numbers__num { font-size: 17px; font-weight: 700; color: var(--dangerous); }

/* ------------------------------------------------------------------- nav */

.nav {
  flex: 0 0 auto;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border-top: 1px solid var(--line);
  background: var(--surface);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.navbtn {
  background: none;
  border: none;
  border-top: 2px solid transparent;
  color: var(--muted);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  padding: 12px 2px;
}
.navbtn--on { color: var(--accent); border-top-color: var(--accent); }

/* On mobile (portrait) the menu is 5px taller: easier to tap. It is spread
   between top and bottom so that the bar of the active tab stays glued to the edge. */
@media (orientation: portrait) {
  .navbtn { padding-top: 14.5px; padding-bottom: 14.5px; }
}

/* ------------------------------------------------------------- ads */

.ad {
  flex: 0 0 auto;
  min-height: var(--chrome);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 6px 12px;
  /* It is the bottom edge element: it takes the safe area of the phone. */
  padding-bottom: max(6px, env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-top: 1px solid var(--line);
}
.ad__label { font-size: 11px; letter-spacing: 0.6px; color: var(--muted); opacity: 0.7; }
.ad__slot { font-size: 13px; color: var(--muted); }

/* -------------------------------------------------------- 18+ gate */

/* Confirmed on a previous visit: never flicker. */
html[data-age-confirmed="yes"] .gate { display: none !important; }

.gate {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  padding-top: max(20px, env(safe-area-inset-top, 0px));
  padding-bottom: max(20px, env(safe-area-inset-bottom, 0px));
  background: var(--bg);
  overflow-y: auto;
}

.gate__card {
  width: 100%;
  max-width: 440px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 22px 18px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: left;
}

.gate__mark {
  align-self: flex-start;
  border: 1px solid var(--accent);
  color: var(--accent);
  border-radius: var(--radius-xs);
  padding: 3px 12px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.6px;
}
.gate__title { margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -0.2px; }
.gate__text { margin: 0; font-size: 15px; line-height: 1.5; color: var(--text); }
.gate__text--small { font-size: 13.5px; color: var(--muted); }
.gate .btn { margin-top: 4px; }
.gate #gate-no { margin-top: 0; }

/* ------------------------------------------------------ consumption log */

.log__body,
.log__days { display: flex; flex-direction: column; gap: 12px; }

.log__pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

.log__entry {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}
.log__entry:first-of-type { border-top: none; padding-top: 0; }

.log__head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.log__time { font-size: 13.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.log__name { font-size: 16px; }
.log__meta { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.log__amount { font-size: 14.5px; font-weight: 600; }
.log__note { margin: 0; font-size: 13.5px; color: var(--muted); }

.log__actions,
.log__noteedit,
.log__redose { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.log__noteedit .search { flex: 1 1 100%; }
.log__redose { align-items: center; }
.log__redoseinput { width: 92px; flex: 0 0 auto; text-align: center; }

.chipbtn {
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  min-height: 40px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}
.chipbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* The browser <button>s do NOT show a hand cursor: on desktop you have to
   ask for it explicitly, in the bottom menu as well. */
.navbtn,
.btn,
.chip,
.row,
.suggest__item,
.linkbtn { cursor: pointer; }

/* Rescue card if the module does not start (see the inline script in index.html). */
.bootfail {
  max-width: 480px;
  margin: 0 auto;
  padding: 24px 18px;
  padding-top: max(24px, env(safe-area-inset-top, 0px));
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.bootfail__title { margin: 0; font-size: 20px; font-weight: 700; }
.bootfail__text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--muted); }

.pill--tag { text-transform: none; }

/* ------------------------------------- donations: tap-to-copy + the toast */

/* The address is a button, so reset what a browser paints for one: it still has
   to read as the value of its row, only now it is a real tap target. */
.addr {
  background: none;
  border: 0;
  margin: 0;
  padding: 2px 0;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
  min-height: 24px;
}
.addr:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The confirmation of the copy: it flies up from the bottom edge, waits a couple
   of seconds and leaves. ONE node, reused, so two quick taps cannot stack two
   copies. It clears the bottom menu (--chrome) and the phone's safe area. */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--chrome) + env(safe-area-inset-bottom, 0px) + 14px);
  z-index: 50;
  max-width: min(320px, calc(100vw - 32px));
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .38);
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 12px) scale(.96);
}
.toast--on { animation: toast-fly 2400ms ease forwards; }

@keyframes toast-fly {
  0%   { opacity: 0; transform: translate(-50%, 14px) scale(.96); }
  12%  { opacity: 1; transform: translate(-50%, 0) scale(1); }
  85%  { opacity: 1; transform: translate(-50%, 0) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -12px) scale(1); }
}

/* Motion is the message here, not a decoration: with reduced motion the same
   notice appears in place instead of flying. */
@media (prefers-reduced-motion: reduce) {
  .toast--on { animation: toast-fade 2400ms linear forwards; }
  @keyframes toast-fade {
    0%   { opacity: 0; }
    8%   { opacity: 1; }
    88%  { opacity: 1; }
    100% { opacity: 0; }
  }
}

/* Off-screen textarea used by the legacy copy path (no Clipboard API). */
.clipshim { position: fixed; top: 0; left: -9999px; width: 1px; height: 1px; opacity: 0; }
