@font-face {
  font-family: 'Outfit';
  src: url('fonts/Outfit-Regular.ttf') format('truetype');
  font-weight: 400; font-display: swap;
}
@font-face {
  font-family: 'Outfit';
  src: url('fonts/Outfit-Bold.ttf') format('truetype');
  font-weight: 700; font-display: swap;
}

/* Warm Orbit palette */
:root {
  color-scheme: light dark;
  --bg: light-dark(#f7f3e8, #17222b);
  --fg: light-dark(#2c3540, #eae8d9);
  --muted: light-dark(#8f8b78, #8fa0ab);
  --card: light-dark(#fffdf6, #21313c);
  --line: light-dark(#e8e0cb, #30434f);
  --accent: #33658a;   /* deep sea: done, given */
  --coral: #2a9d8f;    /* teal: actions */
  --sun: #f4d35e;      /* sunshine */
  --lilac: light-dark(#8e7cc3, #b8a9e8);   /* cycle 🌸 */
  --danger: light-dark(#c0392b, #e07b6f);
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  font-family: 'Outfit', system-ui, -apple-system, "Segoe UI", sans-serif;
  background-color: var(--bg);
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27480%27%20height%3D%27480%27%3E%3Cg%20fill%3D%27none%27%3E%3Ccircle%20cx%3D%2752%27%20cy%3D%2764%27%20r%3D%2724%27%20fill%3D%27%232a9d8f%27%20fill-opacity%3D%27.13%27%2F%3E%3Ccircle%20cx%3D%27330%27%20cy%3D%2740%27%20r%3D%2715%27%20fill%3D%27%2333658a%27%20fill-opacity%3D%27.14%27%2F%3E%3Ccircle%20cx%3D%27210%27%20cy%3D%27150%27%20r%3D%2730%27%20fill%3D%27%23f4d35e%27%20fill-opacity%3D%27.18%27%2F%3E%3Ccircle%20cx%3D%27420%27%20cy%3D%27210%27%20r%3D%2719%27%20fill%3D%27%23b8a9e8%27%20fill-opacity%3D%27.15%27%2F%3E%3Ccircle%20cx%3D%2790%27%20cy%3D%27270%27%20r%3D%2712%27%20fill%3D%27%2333658a%27%20fill-opacity%3D%27.12%27%2F%3E%3Ccircle%20cx%3D%27300%27%20cy%3D%27340%27%20r%3D%2725%27%20fill%3D%27%232a9d8f%27%20fill-opacity%3D%27.11%27%2F%3E%3Ccircle%20cx%3D%27150%27%20cy%3D%27420%27%20r%3D%2716%27%20fill%3D%27%23f4d35e%27%20fill-opacity%3D%27.18%27%2F%3E%3Ccircle%20cx%3D%2730%27%20cy%3D%27170%27%20r%3D%279%27%20stroke%3D%27%232a9d8f%27%20stroke-opacity%3D%27.2%27%20stroke-width%3D%273%27%2F%3E%3Ccircle%20cx%3D%27260%27%20cy%3D%27255%27%20r%3D%278%27%20stroke%3D%27%2333658a%27%20stroke-opacity%3D%27.2%27%20stroke-width%3D%273%27%2F%3E%3Ccircle%20cx%3D%27440%27%20cy%3D%27420%27%20r%3D%2710%27%20stroke%3D%27%23f4d35e%27%20stroke-opacity%3D%27.25%27%20stroke-width%3D%273%27%2F%3E%3Cpath%20d%3D%27M362%20152%20L362%20108%20L392%20152%20Z%27%20fill%3D%27%23f4d35e%27%20fill-opacity%3D%27.22%27%2F%3E%3Cpath%20d%3D%27M76%20387%20L76%20352%20L100%20387%20Z%27%20fill%3D%27%232a9d8f%27%20fill-opacity%3D%27.16%27%2F%3E%3Cpath%20d%3D%27M226%2052%20L226%2022%20L247%2052%20Z%27%20fill%3D%27%2333658a%27%20fill-opacity%3D%27.14%27%2F%3E%3Cg%20fill%3D%27%23b8a9e8%27%20fill-opacity%3D%27.18%27%3E%3Ccircle%20cx%3D%27388%27%20cy%3D%27318%27%20r%3D%277%27%2F%3E%3Ccircle%20cx%3D%27402%27%20cy%3D%27310%27%20r%3D%275%27%2F%3E%3Ccircle%20cx%3D%27414%27%20cy%3D%27318%27%20r%3D%275%27%2F%3E%3Ccircle%20cx%3D%27401%27%20cy%3D%27330%27%20r%3D%278%27%2F%3E%3C%2Fg%3E%3Cg%20fill%3D%27%232a9d8f%27%20fill-opacity%3D%27.14%27%3E%3Ccircle%20cx%3D%27158%27%20cy%3D%27218%27%20r%3D%276%27%2F%3E%3Ccircle%20cx%3D%27170%27%20cy%3D%27211%27%20r%3D%274%27%2F%3E%3Ccircle%20cx%3D%27181%27%20cy%3D%27218%27%20r%3D%274%27%2F%3E%3Ccircle%20cx%3D%27169%27%20cy%3D%27228%27%20r%3D%277%27%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E");
  color: var(--fg);
  display: flex; flex-direction: column; min-height: 100dvh;
}

/* ---- top bar ---- */
.topbar {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .6rem .9rem calc(.6rem); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--bg); z-index: 5;
}
.topbar h1 { font-size: 1.05rem; margin: 0; letter-spacing: .05em; }
.topbar-right { margin-left: auto; display: flex; gap: .4rem; align-items: center; }

.tabs { display: flex; gap: .35rem; overflow-x: auto; scrollbar-width: none; }
.tabs button {
  border: 1px solid var(--line); background: var(--card); color: var(--fg);
  border-radius: 999px; padding: .35rem .8rem; font-size: .9rem; white-space: nowrap;
}
.tabs button.active { background: var(--accent); border-color: var(--accent); color: #fff; }

button { cursor: pointer; font: inherit; }
.ghost {
  background: none; border: 1px solid var(--line); color: var(--muted);
  border-radius: .5rem; padding: .3rem .6rem; font-size: .85rem; text-decoration: none;
}
.ghost:hover { color: var(--fg); }
.ghost.danger { color: var(--danger); }
.signout { display: inline-block; }

/* ---- items ---- */
#app { flex: 1; padding: .5rem .9rem 6.5rem; max-width: 640px; width: 100%; margin: 0 auto; }
#items { list-style: none; margin: 0; padding: 0; }
#items li {
  display: flex; align-items: center; gap: .7rem;
  background: var(--card); border: 1px solid var(--line); border-radius: .7rem;
  padding: .65rem .8rem; margin: .45rem 0;
}
#items li.done { opacity: .45; }
#items li.done .txt { text-decoration: line-through; }
.tick {
  width: 1.45rem; height: 1.45rem; border-radius: 50%; flex: none;
  border: 2px solid var(--muted); background: none; color: transparent;
  display: grid; place-items: center; font-size: .9rem; line-height: 1;
}
li.done .tick { background: var(--accent); border-color: var(--accent); color: #fff; }
.txt { flex: 1; overflow-wrap: anywhere; }
.who { font-size: .7rem; color: var(--muted); flex: none; }
.del { background: none; border: none; color: var(--muted); font-size: 1.1rem; padding: .2rem .4rem; }
.del:hover { color: var(--danger); }

.hint { color: var(--muted); text-align: center; margin-top: 2.5rem; }

/* "Working out this month's projection". The dots are animated from
   requestAnimationFrame in energy.js, never CSS: the OS reduced-motion
   setting disables CSS animation outright, and a frozen progress indicator
   looks like a hung page rather than a busy one. */
.octobusy { color: var(--muted); }
.octodot {
  font-style: normal; letter-spacing: .15em;
  color: var(--coral); opacity: .25;
}

/* A write command awaiting a human. Deliberately the loudest thing in the
   dialog: it is the one item here that is asking for a decision. */
.cmdpending {
  margin-top: .6rem; padding: .55rem .65rem;
  border: 1px solid var(--sun); border-radius: .5rem;
  background: light-dark(#fdf7e3, #332d18);
}
.cmdpendhead { font-size: .8rem; font-weight: 700; margin-bottom: .35rem; }
.cmdpendrow {
  display: flex; align-items: center; gap: .5rem;
  padding: .25rem 0; font-size: .78rem;
}
.cmdpendrow b { font-family: ui-monospace, monospace; }
.cmdpendrow span { color: var(--muted); margin-right: auto; }
.cmdpendrow button { padding: .15rem .5rem; font-size: .74rem; }

/* Agent telemetry inside the 🔔 dialog — dense on purpose; it is read when
   something is wrong, not browsed. */
.agenttel { margin-top: .5rem; }
.agenttelrow {
  display: flex; justify-content: space-between; gap: .75rem;
  padding: .18rem 0; font-size: .78rem; border-bottom: 1px solid var(--line);
}
.agenttelrow span { color: var(--muted); }
.agenttelrow b { font-weight: 400; text-align: right; word-break: break-word; }
.agentlog {
  margin: .5rem 0 0; padding: .45rem .55rem; max-height: 11rem; overflow: auto;
  background: var(--bg); border: 1px solid var(--line); border-radius: .4rem;
  font-size: .7rem; line-height: 1.35; white-space: pre; color: var(--muted);
}

/* A cycle-windowed med that has fallen out of scheduling. Louder than the
   neutral "between windows" note it replaces, because it needs an action. */
.cyclestale {
  display: inline-block; margin-top: .25rem;
  padding: .3rem .55rem; border-radius: .45rem;
  border: 1px solid var(--danger);
  background: light-dark(#fdeeec, #3a2320);
  color: var(--danger); font-size: .78rem; line-height: 1.3;
  text-decoration: none;
}
.cyclestale:hover { text-decoration: underline; }

/* Exchange-agent alarm: this replaces three weeks of silence, so it sits at
   the top of the meds page in danger red and does not blend into the hints. */
.agentwarn {
  margin: 0 0 .9rem; padding: .65rem .85rem; border-radius: .6rem;
  border: 1px solid var(--danger);
  background: light-dark(#fdeeec, #3a2320);
  color: var(--danger); font-size: .9rem; line-height: 1.35;
}
.error { color: var(--danger); }

/* ---- bottom add bar ---- */
.addbar {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 5;
  background: var(--bg); border-top: 1px solid var(--line);
  padding: .6rem .9rem calc(.6rem + env(safe-area-inset-bottom));
}
.addbar form { display: flex; gap: .5rem; max-width: 640px; margin: 0 auto; }
.addbar input {
  flex: 1; padding: .65rem .8rem; border-radius: .6rem; font: inherit;
  border: 1px solid var(--line); background: var(--card); color: var(--fg);
}
.addbar button[type=submit] {
  background: var(--accent); color: #fff; border: none; border-radius: .6rem; padding: 0 1.1rem;
}
.listactions { display: flex; gap: .5rem; justify-content: center; margin-top: .5rem; max-width: 640px; margin-inline: auto; }

/* ---- auth pages ---- */
body.auth { display: grid; place-items: center; padding: 1rem; }
.authbox { width: min(92vw, 22rem); text-align: center; }
.authbox h1 { letter-spacing: .06em; }
.authbox form { display: flex; flex-direction: column; gap: .6rem; }
.authbox fieldset { border: 1px solid var(--line); border-radius: .7rem; display: flex; flex-direction: column; gap: .5rem; padding: .8rem; margin: 0; }
.authbox legend { color: var(--muted); font-size: .85rem; padding: 0 .35rem; }
.authbox input {
  padding: .7rem .8rem; border-radius: .6rem; font: inherit;
  border: 1px solid var(--line); background: var(--card); color: var(--fg);
}
.authbox button {
  background: var(--accent); color: #fff; border: none; border-radius: .6rem; padding: .7rem;
}

/* ---- meds ---- */
.membercard {
  background: var(--card); border: 1px solid var(--line); border-radius: .8rem;
  padding: .7rem .9rem; margin: .7rem 0;
}
.membercard h2 { font-size: 1rem; margin: .1rem 0 .5rem; display: flex; align-items: center; gap: .4rem; }
.medrow { border-top: 1px solid var(--line); padding: .55rem 0; }
.medrow:first-of-type { border-top: none; }
.medinfo { display: flex; flex-direction: column; gap: .1rem; }
.medname {
  background: none; border: none; color: var(--fg); text-align: left;
  font: inherit; font-weight: 600; padding: 0; text-decoration: underline dotted var(--muted);
}
.mednotes { font-size: .8rem; color: var(--muted); }
.slots { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .45rem; align-items: center; }
.slot {
  border: 1px solid var(--line); background: var(--bg); color: var(--fg);
  border-radius: .55rem; padding: .4rem .7rem; font-size: .85rem;
  display: flex; flex-direction: column; align-items: center; gap: .15rem;
}
.slot.given { background: var(--accent); border-color: var(--accent); color: #fff; }
.slot.given small { opacity: .9; font-size: .68rem; }
.slot.prn { background: var(--accent); border-color: var(--accent); color: #fff; }
.prnlast { color: var(--muted); }

.loghead { font-size: .9rem; color: var(--muted); margin: 1.4rem 0 .3rem; }
#doselog { list-style: none; padding: 0; margin: 0; font-size: .82rem; color: var(--muted); }
#doselog li { padding: .18rem 0; }

/* ---- dialogs ---- */
dialog {
  border: 1px solid var(--line); border-radius: .9rem; background: var(--card); color: var(--fg);
  width: min(92vw, 24rem); padding: 1rem 1.1rem;
}
dialog::backdrop { background: rgb(0 0 0 / .45); }
/* ---- confirm sheet opened from a reminder: one big button, thumb-sized ---- */
dialog.givesheet { width: min(26rem, calc(100vw - 2rem)); }
.givelist { list-style: none; margin: 0 0 .8rem; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.givelist li { display: flex; justify-content: space-between; gap: .6rem; padding: .55rem .7rem;
  background: var(--bg); border-radius: .5rem; font-size: 1rem; }
.givelist li.done { opacity: .6; }
.givelist .gstate { color: var(--muted); font-size: .8rem; white-space: nowrap; }
.giverow { display: flex; gap: .6rem; align-items: stretch; }
.givebig { flex: 1; font-size: 1.15rem; font-weight: 700; padding: .9rem 1rem; border-radius: .7rem;
  background: #3ecf6e; color: #08210f; border: 0; }
.givebig:disabled { opacity: .7; }
dialog h2 { margin: 0 0 .7rem; font-size: 1.05rem; }
dialog form { display: flex; flex-direction: column; gap: .55rem; }
dialog label { display: flex; flex-direction: column; gap: .25rem; font-size: .85rem; color: var(--muted); }
dialog label.row { flex-direction: row; align-items: center; gap: .5rem; color: var(--fg); }
dialog input, dialog select {
  padding: .55rem .65rem; border-radius: .5rem; font: inherit;
  border: 1px solid var(--line); background: var(--bg); color: var(--fg);
}
.slotpick { display: grid; grid-template-columns: 1fr 1fr; gap: .2rem .6rem; padding-left: 1.4rem; }
.slotopt { font-size: .9rem; }
.dlgbtns { display: flex; gap: .5rem; justify-content: flex-end; margin-top: .5rem; }
.dlgbtns button[type=submit] { background: var(--accent); color: #fff; border: none; border-radius: .55rem; padding: .5rem 1rem; }
.row3 { display: flex; gap: .45rem; }
.emojiin { width: 3.2rem; text-align: center; }
.row3 input[name=name] { flex: 1; }
#peoplelist { list-style: none; padding: 0; margin: 0 0 .7rem; }
.personrow { display: flex; align-items: center; justify-content: space-between; padding: .3rem 0; border-bottom: 1px solid var(--line); }

/* ---- reminders dialog ---- */
.hint2 { color: var(--muted); font-size: .8rem; margin: .1rem 0 .3rem; }
.timesgrid { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem .7rem; }
.agentbox { border: 1px solid var(--line); border-radius: .6rem; padding: .5rem .7rem; }
.agentbox summary { cursor: pointer; color: var(--muted); font-size: .85rem; }
.agentbox input { flex: 1; font-family: ui-monospace, monospace; font-size: .75rem; }

/* ---- custom med times ---- */
.customwrap { padding-left: 1.4rem; display: flex; flex-direction: column; gap: .3rem; align-items: flex-start; }
.timerow { display: flex; gap: .3rem; align-items: center; }
.timerow input { padding: .35rem .5rem; }

/* ---- weekday + cycle controls ---- */
.daysrow { display: flex; gap: .3rem; align-items: center; padding-left: 1.4rem; flex-wrap: wrap; }
.daytoggle { display: inline-flex; align-items: center; gap: .15rem; font-size: .8rem; color: var(--muted); }
.daytoggle input { accent-color: var(--accent); }
.cyclewrap { display: flex; flex-direction: column; gap: .3rem; }
.cyclefields { padding-left: 1.4rem; color: var(--muted); font-size: .85rem; display: flex; gap: .35rem; align-items: center; flex-wrap: wrap; }
.cyclefields input { width: 4rem; }
.cyclechip {
  margin-left: .6rem; font-size: .72rem; border: 1px solid var(--line); border-radius: 999px;
  background: none; color: var(--muted); padding: .15rem .55rem; vertical-align: middle;
}
.cyclehist { list-style: none; padding: 0; margin: .4rem 0 0; }
.timerow select { padding: .35rem .4rem; border-radius: .5rem; border: 1px solid var(--line); background: var(--bg); color: var(--fg); font: inherit; font-size: .85rem; }

/* ---- photos ---- */
.avatar { width: 1.7rem; height: 1.7rem; border-radius: 50%; object-fit: cover; vertical-align: middle; cursor: pointer; }
.medthumb { width: 2.4rem; height: 2.4rem; border-radius: .45rem; object-fit: cover; cursor: pointer; float: left; margin-right: .6rem; }
.medthumbbig { max-width: 100%; max-height: 9rem; border-radius: .6rem; display: block; }
.photorow { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.photodlg { max-width: min(94vw, 34rem); }
.photodlg img { max-width: 100%; max-height: 70vh; border-radius: .5rem; display: block; margin: 0 auto; }
.personname { display: flex; align-items: center; gap: .4rem; }
.personrow { gap: .4rem; }
.personrow .ghost { margin-left: auto; }

/* ---- Warm Orbit accents ---- */
.tabs button.active { background: var(--coral); border-color: var(--coral); }
.addbar button[type=submit], .authbox button, .dlgbtns button[type=submit] { background: var(--coral); }
.slot.prn { background: var(--coral); border-color: var(--coral); }
.cyclechip { color: var(--lilac); border-color: var(--lilac); }
.topbar h1 { display: flex; align-items: center; gap: .45rem; font-weight: 700; letter-spacing: .02em; }
.brandmark { width: 1.5rem; height: 1.5rem; border-radius: .4rem; }
.biglogo { width: 5.5rem; height: 5.5rem; border-radius: 1.25rem; margin-bottom: .6rem; }
.authbox h1 { font-weight: 700; letter-spacing: .02em; }
.topbar, .addbar { background: color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter: blur(6px); }

/* ---- item photos ---- */
.itemthumb { width: 2.2rem; height: 2.2rem; border-radius: .45rem; object-fit: cover; cursor: pointer; flex: none; }
.del.cam { font-size: .85rem; }

/* ---- task groups + due dates ---- */
.grouphead {
  list-style: none; font-size: .78rem; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .08em; margin: .8rem 0 .1rem; padding: 0 .2rem;
}
.itemmain { flex: 1; display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.itemmain .txt { cursor: pointer; }
.duebadge { font-size: .72rem; color: var(--muted); cursor: pointer; }
.duebadge.overdue { color: var(--coral); font-weight: 700; }

/* ---- reorder mode ---- */
.movebtn { font-size: .95rem; padding: .2rem .5rem; }
.active-mode { color: var(--coral); border-color: var(--coral); }

/* ---- calendar ---- */
.daycard h2 { display: flex; align-items: baseline; gap: .5rem; }
.daysub { font-size: .75rem; color: var(--muted); font-weight: 400; }
.calrow {
  display: flex; align-items: center; gap: .6rem;
  border-top: 1px solid var(--line); padding: .5rem 0; font-size: .92rem;
}
.calrow:first-of-type { border-top: none; }
.caltime { font-variant-numeric: tabular-nums; color: var(--muted); width: 3.2rem; flex: none; font-size: .85rem; }
.caltxt { flex: 1; overflow-wrap: anywhere; }
.calmark { color: var(--accent); font-size: .8rem; flex: none; }
.caldone .caltxt { text-decoration: line-through; opacity: .55; }
.caltap { cursor: pointer; }
.caltap:hover .caltxt { color: var(--coral); }

#pastetext { border: 1px solid var(--line); border-radius: .5rem; background: var(--bg); color: var(--fg); font: inherit; padding: .6rem; }

/* ---- energy ---- */
/* 7rem on a phone, 10rem from tablet up. At 7 the rate line ("≈ 43.2p/h at
   3.99p") wraps in a tile barely wider than itself, but 10 is too greedy on a
   375px screen: it drops to ONE tile per row and the card becomes a column of
   six. Measured both. */
.energygrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: .5rem; }
@media (min-width: 640px) {
  .energygrid { grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); }
}
.ecell { background: var(--bg); border: 1px solid var(--line); border-radius: .6rem; padding: .55rem .7rem; display: flex; flex-direction: column; gap: .15rem; position: relative; }
/* In the flow, not absolutely placed. It used to be pinned to the bottom with
   .9rem of padding reserved above it — so the moment the rate line wrapped, the
   two collided. Sitting in the flow it simply cannot overlap, whatever wraps. */
.ecost { align-self: flex-end; margin-top: .1rem; font-size: .72rem; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
.erate { font-size: .72rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.cardchart { display: flex; align-items: flex-end; gap: 3px; height: 56px; margin: .5rem 0 .3rem; }
.cbar { flex: 1; max-width: 3rem; background: #a78bdb; border-radius: 3px 3px 0 0; min-width: 6px; opacity: .85; }
.cbar:hover { opacity: 1; }
/* grid generation mix */
.gridmix { margin-top: .5rem; }
.gmbar { display: flex; height: 10px; border-radius: 5px; overflow: hidden; margin: .35rem 0 .3rem; background: var(--bg); }
.gmseg { height: 100%; }
.gm-renew { background: #3ecf6e; }
.gm-nuclear { background: #4bb5c1; }
.gm-bio { background: #9c7a4d; }
.gm-imp { background: #7c6bbf; }
.gm-fossil { background: #6b7280; }
.obar { flex: 1; max-width: 1.4rem; background: var(--octo-peak); border-radius: 3px 3px 0 0; min-width: 4px; opacity: .85; }
.obar:hover { opacity: 1; }
.obar.obar-part { opacity: .4; }

/* ---- cycle page ---- */
.cy-hero { display: flex; align-items: center; gap: 1rem; margin: .3rem 0 .2rem; flex-wrap: wrap; }
.cy-daybig { font-size: 2.4rem; font-weight: 800; color: var(--coral); line-height: 1; }
.cy-herosub { font-size: .88rem; display: flex; flex-direction: column; gap: .15rem; }
.cy-bleednow { color: #e05d5d; font-weight: 700; }
.cy-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: .5rem; margin: .7rem 0 .2rem; }
.cy-stat { background: var(--bg); border: 1px solid var(--line); border-radius: .6rem; padding: .5rem .7rem; display: flex; flex-direction: column; gap: .1rem; }
.cy-statval { font-size: 1.1rem; font-weight: 700; }
.cy-statlab { font-size: .72rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.cy-statnote { font-size: .7rem; color: var(--muted); }
.cy-active { color: var(--coral); font-weight: 700; }
.cy-strip { display: grid; grid-template-columns: repeat(14, 1fr); gap: 3px; margin: .6rem 0 .2rem; }
.cy-cell {
  text-align: center; font-size: .72rem; padding: .28rem 0; border-radius: .35rem;
  background: var(--bg); border: 1px solid var(--line); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* pink = period, lilac = med window (distinct hues, never confusable) */
.cy-cell.cy-med { background: rgba(124, 107, 191, .3); border-color: #8b7fd4; color: var(--fg); }
.cy-cell.cy-bleed { background: #e0578a; border-color: #f27ba6; color: #fff; font-weight: 700; }
.cy-cell.cy-bleed.cy-past { opacity: .8; }
.cy-askrow {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: .5rem 0 .2rem;
  background: rgba(224, 87, 138, .12); border: 1px solid #e0578a; border-radius: .6rem; padding: .5rem .7rem;
}
.cy-askrow .hint2 { color: var(--fg); }
.memberadd {
  margin-left: auto; background: none; border: 1px solid var(--line); color: var(--coral);
  font-size: 1.05rem; line-height: 1; cursor: pointer; border-radius: .5rem;
  padding: .1rem .45rem .2rem; flex: none;
}
.memberadd:hover { border-color: var(--coral); background: rgba(42, 157, 143, .12); }

/* cycle month calendar */
.cy-cal { margin-top: .9rem; }
.cy-calhead { display: flex; align-items: center; justify-content: center; gap: .8rem; margin-bottom: .4rem; }
.cy-calmonth { font-weight: 700; font-size: .95rem; min-width: 10rem; text-align: center; }
.cy-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.cy-wd { text-align: center; font-size: .68rem; color: var(--muted); text-transform: uppercase; }
.cy-gcell {
  position: relative; aspect-ratio: 1 / 1; border-radius: .4rem;
  background: var(--bg); border: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
}
.cy-gcell.cy-blank { background: none; border: none; }
.cy-gnum { font-size: .82rem; font-variant-numeric: tabular-nums; }
.cy-gday { font-size: .58rem; color: var(--muted); }
.cy-gcell.cy-bleed { background: #e0578a; border-color: #f27ba6; color: #fff; font-weight: 700; }
.cy-gcell.cy-bleed .cy-gday { color: rgba(255, 255, 255, .85); }
.cy-gcell.cy-med { background: rgba(124, 107, 191, .3); border-color: #8b7fd4; }
.cy-gcell.cy-med.cy-bleed { background: linear-gradient(135deg, #e0578a 55%, rgba(124, 107, 191, .55) 55%); }
.cy-gcell.cy-day1 { box-shadow: inset 0 0 0 2px #f4d35e; }
.cy-gcell.cy-pred { opacity: .72; border-style: dashed; }
.cy-gcell.cy-logged .cy-gnum { text-decoration: underline dotted var(--accent); text-underline-offset: 2px; }
.cy-gcell.cy-today { outline: 2px solid var(--coral); outline-offset: -1px; }
.presetrow { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .4rem; }
.presetrow .preset { font-size: .76rem; padding: .2rem .6rem; }
.cy-cell.cy-logged { box-shadow: inset 0 -3px 0 -1px var(--accent); }
.cy-len { max-width: 5rem; }

/* symptom / day log */
.cy-log { margin-top: .7rem; }
.cy-tagrow { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; margin: .4rem 0; }
.cy-taglab { font-size: .72rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; width: 3rem; }
.cy-tag {
  font: inherit; font-size: .78rem; padding: .2rem .6rem; border-radius: 999px; cursor: pointer;
  background: var(--bg); color: var(--muted); border: 1px solid var(--line);
}
.cy-tag:hover { color: var(--fg); }
.cy-tag.on { background: rgba(42, 157, 143, .18); border-color: var(--coral); color: var(--fg); font-weight: 600; }
.cy-tag.on.cy-tagflow { background: rgba(224, 93, 93, .2); border-color: rgba(224, 93, 93, .6); }
.cy-tag.on.cy-tagsym { background: rgba(236, 79, 216, .16); border-color: rgba(236, 79, 216, .5); }
.cy-tagadd { border-style: dashed; }
.cy-symrow { border-top: 1px solid var(--line); padding-top: .5rem; }
.cy-recent { max-height: 12rem; overflow-y: auto; }
.cy-cell.cy-day1 { background: rgba(244, 211, 94, .2); border-color: #f4d35e; color: #f4d35e; font-weight: 700; }
.cy-cell.cy-today { outline: 2px solid var(--coral); outline-offset: -1px; color: var(--fg); }
.cy-cell.cy-past { opacity: .55; }
.cy-form { margin-top: .6rem; }
.cy-form input[type="date"] { flex: 1; }
.cy-hist { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .5rem; }
.cy-chip {
  font-size: .78rem; padding: .16rem .3rem .16rem .55rem; border-radius: 999px;
  border: 1px solid var(--line); color: var(--muted); display: inline-flex; align-items: center; gap: .25rem;
}
.cy-x { background: none; border: none; color: var(--muted); cursor: pointer; font-size: .7rem; padding: 0 .2rem; }
.cy-x:hover { color: #e05d5d; }

/* ---- week planner ---- */
#histwrap { margin-top: 1.2rem; }
.wk-day { border: 1px solid var(--line); border-radius: .6rem; padding: .5rem .7rem; margin-bottom: .5rem; background: var(--card); }
.wk-day.wk-past { opacity: .85; }
.wk-day.wk-today { border-color: var(--coral); }
.wk-head { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; font-weight: 700; font-size: .9rem; margin-bottom: .35rem; }
.wk-score { font-size: .78rem; font-weight: 600; color: #3ecf6e; }
.wk-score.wk-score-miss { color: #e05d5d; }
.wk-chips { display: flex; flex-wrap: wrap; gap: .3rem; }
.wk-chip {
  font-size: .78rem; padding: .16rem .5rem; border-radius: 999px;
  border: 1px solid var(--line); white-space: nowrap;
}
.wk-chip.wk-ok { background: rgba(62, 207, 110, .14); border-color: rgba(62, 207, 110, .4); color: #3ecf6e; }
.wk-chip.wk-miss { background: rgba(224, 93, 93, .14); border-color: rgba(224, 93, 93, .5); color: #e05d5d; font-weight: 600; }
.wk-chip.wk-pend { color: var(--muted); }
/* The energy page uses 98% of the window rather than a fixed ceiling: the old
   1060/1520px caps left a third of a wide monitor empty while the cards stayed
   cramped. Only this page — the list and meds pages keep their 640px reading
   width, because a line of text that wide is harder to read, not easier. */
@media (min-width: 900px) {
  #app.epage { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem; align-items: stretch; max-width: 98vw; }
  #app.epage > .membercard { margin: 0; }
  #app.epage > #sigencard, #app.epage > #trendcard, #app.epage > #histcard { grid-column: 1 / -1; }
}
@media (min-width: 1320px) {
  /* full-screen desktop: three columns, small cards backfill around the big ones */
  #app.epage { grid-template-columns: repeat(3, 1fr); grid-auto-flow: dense; max-width: 98vw; }
  #app.epage > #sigencard { grid-column: span 2; }
}
.elabel { font-size: .72rem; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.eval { font-size: 1.15rem; font-weight: 700; }
.eline { padding: .2rem 0; font-size: .92rem; }
#trendchart { margin-top: .5rem; }
#trendchart svg { width: 100%; height: auto; display: block; }
.tgrid { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 4; }
.tlab { fill: var(--muted); font-size: 11px; }
.tprice { fill: none; stroke: #f4d35e; stroke-width: 2; }
.tpl { fill: #f4d35e; font-size: 11px; font-weight: 700; }
.tsoc { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; }
.tnow { stroke: var(--coral); stroke-width: 1.5; stroke-dasharray: 4 3; }
.okd-price { background: #f4d35e; }
.okd-soc { background: var(--accent); }

/* ---- energy flow scene ---- */
#flowviz { margin-bottom: .6rem; }
#flowviz svg { width: 100%; height: auto; display: block; }
#flowviz .cable { fill: none; stroke: var(--line); stroke-width: 3; stroke-linejoin: round; }
#flowviz .cable.flowing { stroke-dasharray: 7 9; }
#fv-c-solar.flowing { stroke: #f4d35e; }
#fv-c-grid.flowing { stroke: #ff9d2e; }
/* SigenStor LED colours: green = charging, blue = discharging
   (double-id selectors so these beat the base #flowviz rules below) */
#flowviz #fv-c-batt.flowing.fvdis { stroke: #3fa9f5; }
#flowviz #fv-c-batt.flowing.fvcharge { stroke: #3ecf6e; }
#flowviz #fv-l-batt.fvdis { fill: #3fa9f5; }
#flowviz #fv-l-batt.fvcharge { fill: #3ecf6e; }
#flowviz #fv-batt-fill.fvdis { fill: #3fa9f5; }
#flowviz #fv-batt-fill.fvcharge { fill: #3ecf6e; }
#flowviz .fvbox { fill: var(--bg); stroke: var(--line); stroke-width: 2; }
#flowviz .fvroof { fill: var(--bg); stroke: var(--line); stroke-width: 2; stroke-linejoin: round; }
#flowviz .fvpanel { fill: var(--accent); opacity: .55; stroke: var(--line); stroke-width: 1; }
#flowviz .fvwin { fill: #f4d35e; opacity: .35; stroke: var(--line); }
#flowviz .fvdoor { fill: var(--coral); opacity: .5; stroke: var(--line); }
#flowviz .fvfill { fill: var(--coral); opacity: .75; }
#flowviz .fvled { fill: var(--coral); }
#flowviz .fvpole { stroke: var(--line); stroke-width: 3; stroke-linecap: round; }
#flowviz .fvlab { fill: var(--muted); font-size: 12px; }
#flowviz .fvbig {
  fill: #fff; font-size: 19px; font-weight: 700;
  stroke: #17222b; stroke-width: 3px; paint-order: stroke; stroke-linejoin: round;
}
#flowviz .fvval { font-size: 13px; font-weight: 700; }
#flowviz .fvsolar { fill: #f4d35e; }
#flowviz .fvbatt { fill: var(--coral); }
#flowviz .fvgrid { fill: #ff9d2e; }
#flowviz .fvval.fvidle { fill: var(--muted); font-weight: 400; }
.eval.ev-charge { color: #3ecf6e; }
.eval.ev-dis { color: #3fa9f5; }
.eval.ev-solar { color: #f4d35e; }
.eval.ev-car { color: #a78bdb; }
.eval.ev-grid { color: #ff9d2e; }
#flowviz .fvwheel { fill: var(--bg); stroke: var(--line); stroke-width: 2; }
#flowviz .fvcar { fill: #a78bdb; }
#fv-c-car.flowing { stroke: #a78bdb; }
.tnowlab { fill: var(--coral); font-weight: 700; }
:root { --octo-peak: #ec4fd8; --octo-cheap: #f4aef0; }
.histchart { display: flex; align-items: flex-end; gap: 2px; margin: .4rem 0 .6rem; }
.hbar {
  flex: 1; min-width: 4px; border-radius: 3px 3px 0 0; overflow: hidden;
  display: flex; flex-direction: column-reverse;
}
.hbar:hover { filter: brightness(1.15); }
.hseg { width: 100%; }
.hs-peak { background: var(--octo-peak); }
.hs-cheap { background: var(--octo-cheap); }
.hs-stand { background: repeating-linear-gradient(45deg, var(--octo-cheap) 0 3px, rgba(244, 174, 240, .3) 3px 6px); }
.histhead { display: flex; align-items: center; justify-content: space-between; gap: .6rem; flex-wrap: wrap; }
.oklegend { display: flex; gap: .8rem; font-size: .78rem; color: var(--muted); }
.oklegend span { display: inline-flex; align-items: center; gap: .3rem; }
.okdot { width: .7rem; height: .7rem; border-radius: 3px; display: inline-block; }
.okd-peak { background: var(--octo-peak); }
.okd-cheap { background: var(--octo-cheap); }
.okd-stand { background: repeating-linear-gradient(45deg, var(--octo-cheap) 0 3px, rgba(244, 174, 240, .3) 3px 6px); }
.histmode button {
  font: inherit; font-size: .8rem; padding: .2rem .7rem; cursor: pointer;
  background: var(--bg); color: var(--muted); border: 1px solid var(--line);
}
.histmode button:first-child { border-radius: .5rem 0 0 .5rem; }
.histmode button:last-child { border-radius: 0 .5rem .5rem 0; margin-left: -1px; }
.histmode button.on { background: var(--octo-peak); border-color: var(--octo-peak); color: #fff; font-weight: 700; }
.histtable { max-height: 22rem; overflow-y: auto; margin-top: .5rem; }
.hmonth {
  position: sticky; top: 0; background: var(--card); font-weight: 700; font-size: .9rem;
  padding: .45rem 0 .3rem; border-bottom: 1px solid var(--line); color: var(--accent);
}
.hday { border-top: 1px solid var(--line); padding: .3rem 0; }
.hday:first-of-type { border-top: none; }
/* Export line under a day: the grid's amber, matching the trend chart's
   exporting band and the GRID tile, so the same colour means the same thing
   everywhere on the page. */
.hexp { font-size: .7rem; color: #ff9d2e; margin-top: .1rem; }
.hstrip { display: flex; height: 5px; border-radius: 3px; overflow: hidden; margin-top: .2rem; background: var(--bg); }
/* flex-basis:0 is load-bearing here. .hseg sets width:100% for the vertical
   bars, and in this flex ROW that becomes each segment's basis - three
   segments then want 300% of the strip, free space goes negative, flex-grow
   is ignored entirely, and flex-shrink divides them into equal thirds
   whatever the numbers say. Basis 0 hands the width back to flex-grow. */
.hstrip .hseg { height: 100%; flex-basis: 0; min-width: 0; }
.hrow { display: flex; gap: .6rem; font-size: .9rem; }
.hdate { flex: 1; }
.hkwh { width: 6rem; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
.hcost { width: 5rem; text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.mtd {
  margin-left: auto; font-size: .74rem; font-weight: 600; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ---- scannable day rows (headroom / charging / car sessions) ---- */
.drow {
  display: grid; grid-template-columns: 3.6rem 1fr 4.2rem; gap: .45rem;
  align-items: center; padding: .22rem 0; font-size: .82rem;
}
.drow-dim { opacity: .72; }
.dlab { color: var(--muted); white-space: nowrap; }
.dtrack { background: var(--bg); border-radius: .3rem; height: 1.05rem; overflow: hidden; position: relative; }
/* Several bursts on ONE track. Absolutely placed rather than laid out in flow,
   because each segment's position is its real clock time, not its distance
   from the one before it. */
.dseg { position: absolute; top: 0; height: 100%; border-radius: .3rem; min-width: 2px; }
.dbar {
  display: block; height: 100%; border-radius: .3rem; min-width: 2px;
  font-size: .65rem; color: #fff; line-height: 1.05rem; text-align: right; padding-right: .2rem;
}
/* The car charged when it should not have. Loud enough to be noticed on a
   glance at the page, which is the only way it gets caught the same day. */
.carpeak {
  background: rgba(224, 93, 93, .12); border: 1px solid rgba(224, 93, 93, .45);
  color: #ffb4b4; border-radius: .5rem; padding: .45rem .6rem;
  font-size: .8rem; font-weight: 600; margin: .3rem 0 .5rem;
}
.carpeak-now { border-color: var(--coral); color: #fff; background: rgba(224, 93, 93, .3); }

/* ---- Octopus card: hierarchy instead of a list of equal lines ---- */
.octotariff { font-weight: 600; margin-bottom: .45rem; color: var(--text); }
/* Two columns, always: the tiles are actual | projected pairs, and an auto-fit
   grid would put three across on a wide screen and break every pairing. */
.energygrid.octostats { margin-bottom: .5rem; grid-template-columns: 1fr 1fr; }
.octostats .eval { font-size: 1.05rem; }
.ev-export { color: #ff9d2e; }                 /* the grid's amber, as everywhere else */
.octochip {
  display: inline-block; padding: .25rem .55rem; border-radius: .5rem;
  background: var(--bg); border: 1px solid var(--line);
  font-size: .78rem; font-weight: 600; margin-bottom: .45rem;
}
.octochip-on { border-color: rgba(62, 207, 110, .5); color: #3ecf6e; }
.octorates { margin-bottom: .5rem; }

.db-head { background: var(--accent); }
/* Export bars in the grid's amber, matching the trend chart's exporting band,
   the per-day export line and the GRID tile. */
.db-exp { background: #ff9d2e; }
/* Energy used by the house as it arrived, rather than stored first. */
.db-house { background: var(--accent); }
.okd-house { background: var(--accent); }
/* the same purple and amber the car and export use everywhere else */
.okd-car { background: #a78bdb; }
/* metered Shelly plugs, carved out of "house" on the Where it went card */
.db-plugs, .okd-plugs { background: #2ec4c4; }
.db-none { background: var(--line); }
.db-charge { background: #3ecf6e; }
.db-car { background: #a78bdb; }
.db-live { outline: 2px solid var(--coral); outline-offset: -2px; }
/* ---- Plugs card ---- */
/* device names need more room than "Sat 3" */
.drow-wide { grid-template-columns: 7.5rem 1fr 4.2rem; }
.drow-wide .dlab { overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.drow-click { cursor: pointer; border-radius: .3rem; }
.drow-click:hover { background: var(--bg); }
.plug-new { font-style: italic; }
.plughead { font-size: .78rem; color: var(--muted); margin: .7rem 0 .2rem; font-weight: 600; }
.oklegend.pluglegend { flex-wrap: wrap; gap: .3rem .8rem; margin-bottom: .3rem; }
.dval { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.dsub { grid-column: 2 / -1; font-size: .7rem; color: var(--muted); margin-top: -.15rem; }
.daxis {
  display: flex; justify-content: space-between; font-size: .62rem; color: var(--muted);
  margin-left: 4.05rem; margin-right: 4.65rem; margin-top: .15rem;
}
.ecost { font-size: .68rem; letter-spacing: -.01em; }

/* overnight charge curve */
.chargegraph { margin: .2rem 0 .5rem; }
.chargegraph svg { width: 100%; height: auto; display: block; }
.cgArea { fill: rgba(62, 207, 110, .28); stroke: #3ecf6e; stroke-width: 1.2; }
.cgSoc { fill: none; stroke: #3fa9f5; stroke-width: 2; stroke-linejoin: round; }
.cgLab { fill: var(--muted); font-size: 9px; }
.cgSocLab { fill: #3fa9f5; font-weight: 700; }
.cgKwLab { fill: #3ecf6e; }
.tchg { fill: rgba(62, 207, 110, .3); stroke: #3ecf6e; stroke-width: 1.2; }
.tchglab { fill: #3ecf6e; font-size: 10px; }
.okd-chg { background: rgba(62, 207, 110, .55); border: 1px solid #3ecf6e; }
/* Export in the grid's own amber — the same colour the flow scene and the GRID
   tile already use for power crossing the meter, so it needs no learning. */
.texp { fill: rgba(255, 157, 46, .26); stroke: #ff9d2e; stroke-width: 1.2; }
.texplab { fill: #ff9d2e; font-size: 10px; }
.okd-exp { background: rgba(255, 157, 46, .55); border: 1px solid #ff9d2e; }
.db-thin { background: repeating-linear-gradient(45deg, var(--line) 0 4px, transparent 4px 8px); }
