/* Today — warm, phone-first design system.
   Light is the primary theme; dark follows the system setting. */

:root {
  --paper: #fbf7f1;
  --paper-2: #f3ece1;
  --surface: #ffffff;
  --surface-2: #fdfaf5;
  --ink: #241e1a;
  --ink-2: #4a3f38;
  --muted: #7d6f66;
  --faint: #a99c92;
  --line: #e8ded1;
  --line-strong: #d9ccbb;
  --terracotta: #b8542f;
  --terracotta-soft: #f6e3d9;
  --amber: #b5761a;
  --amber-soft: #fbeed4;
  --green: #4a7357;
  --green-soft: #e4eee5;
  --blue: #37627f;
  --blue-soft: #e2ecf2;
  --plum: #7a4a6b;
  --plum-soft: #f0e3ec;
  --danger: #a63a2c;
  --shadow-sm: 0 1px 2px rgba(58, 42, 31, .05), 0 1px 1px rgba(58, 42, 31, .04);
  --shadow-md: 0 6px 24px -12px rgba(58, 42, 31, .28), 0 2px 6px -2px rgba(58, 42, 31, .08);
  --radius: 16px;
  --radius-sm: 12px;
  --pad: 14px;
  --serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #17130f;
    --paper-2: #1d1813;
    --surface: #211b16;
    --surface-2: #261f19;
    --ink: #f4ece2;
    --ink-2: #ded2c6;
    --muted: #b0a196;
    --faint: #8a7c71;
    --line: #372e26;
    --line-strong: #453a30;
    --terracotta: #e08861;
    --terracotta-soft: #3a241b;
    --amber: #e2ab5a;
    --amber-soft: #3a2c17;
    --green: #8dbb99;
    --green-soft: #1f2c22;
    --blue: #8fb4cc;
    --blue-soft: #1b2830;
    --plum: #c795b6;
    --plum-soft: #2e2029;
    --danger: #e08a7d;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
    --shadow-md: 0 10px 30px -16px rgba(0, 0, 0, .8);
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

/* No default tap highlight, no mouse-click focus ring: the app has its own
   pressed states, and the browser's blue wash makes every tap look broken. */
* { -webkit-tap-highlight-color: transparent; }
button, a, [role="checkbox"], .chip, .tab, .upday, .dayrow, .datechip {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
button:focus:not(:focus-visible),
a:focus:not(:focus-visible),
[role="checkbox"]:focus:not(:focus-visible) { outline: none; }
button:focus-visible, a:focus-visible, [role="checkbox"]:focus-visible {
  outline: 2px solid var(--blue); outline-offset: 2px;
}

/* Every inline icon gets a sane default size. Without this, an SVG with no
   width/height renders at its 300×150 default with a black fill — which is
   exactly how a calendar glyph became a black brick next to the journal date. */
svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* The app is a fixed-height column: the top bar and the tab bar never move, and
   each page scrolls inside the space between them. That is what lets a page keep
   its own scroll position, and it is the only way four pages can sit side by side
   without the document itself growing. */
html, body { height: 100%; }

body {
  margin: 0;
  display: flex;
  flex-direction: column;
  height: 100dvh;
  min-height: 0;
  overflow: hidden;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
p { margin: 0; }
button { font: inherit; color: inherit; }
a { color: inherit; }

.skip {
  position: absolute; left: -999px; top: 0; background: var(--surface);
  padding: 10px 14px; border-radius: 0 0 12px 0; z-index: 100;
}
.skip:focus { left: 0; }

/* ---------- top bar ---------- */
.topbar {
  position: relative; flex: none; z-index: 30;
  background: color-mix(in srgb, var(--paper) 95%, transparent);
  backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease;
}
.topbar.is-scrolled { border-bottom-color: var(--line); }
.topbar__inner {
  max-width: 720px; margin: 0 auto; padding: 7px 11px 6px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.topbar__left { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.wordmark {
  font-family: var(--serif); font-size: 21px; font-weight: 600; letter-spacing: .01em;
}
.topbar__sub {
  font-size: 13px; color: var(--muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.topbar__actions { display: flex; gap: 4px; }
.iconbtn {
  width: 40px; height: 40px; display: grid; place-items: center;
  background: transparent; border: 0; border-radius: 50%; cursor: pointer;
  color: var(--ink-2); transition: background .18s ease, transform .18s ease;
}
.iconbtn:hover { background: var(--paper-2); }
.iconbtn:active { transform: scale(.94); }
.iconbtn svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.iconbtn.is-spinning svg { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- layout ---------- */
.main {
  position: relative; flex: 1 1 auto; min-height: 0;
  overflow: hidden;
}
.view { display: flex; flex-direction: column; gap: 9px; }

/* The pager: a clipped viewport with four full-width pages side by side.
   `touch-action: pan-y` gives vertical scrolling to the browser and leaves
   horizontal movement to the gesture code — no preventDefault games. */
.pager {
  position: absolute; inset: 0;
  overflow: hidden;
  /* Deliberately NOT `touch-action: pan-y`: touch-action can only be narrowed
     by a descendant, never widened, so pinning the pager to vertical panning
     also froze the weather-hour strip and the next-days row. Nothing here can
     scroll sideways anyway (the pages clip and the document does not scroll), so
     the browser has nothing to claim and the strips keep their own gesture. */
  touch-action: auto;
}
.pager__track {
  display: flex;
  height: 100%;
  width: 100%;
  will-change: transform;
}
.page {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  padding: 2px max(11px, calc((100% - 720px) / 2)) calc(28px + env(safe-area-inset-bottom));
}
.page:focus { outline: none; }
.page:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
.pager.is-dragging .page { cursor: grabbing; }

/* A past day, the day archive and journal browsing are their own route, opened
   over the pager. The pager underneath keeps its scroll position, which is what
   makes "back" feel like a return rather than a rebuild. */
.detail-layer {
  position: absolute; inset: 0; z-index: 20;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  background: var(--paper);
  padding: 4px max(11px, calc((100% - 720px) / 2)) calc(28px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.detail-layer[hidden] { display: none; }
.detail-layer:focus { outline: none; }
body.is-detail .detail-layer { animation: detail-push 240ms cubic-bezier(.22,.61,.24,1); }
@keyframes detail-push { from { opacity: .5; transform: translateX(18px); } }
.detail__back { margin-bottom: 2px; }

body.is-locked .tabbar { display: none; }
body.is-locked .pager { visibility: hidden; }
.auth { max-width: 460px; width: 100%; margin: 8vh auto 0; display: grid; gap: 14px; }
.devnote { font-size: 12px; color: var(--faint); text-align: center; }
.devchip {
  align-self: center; font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--amber); background: var(--amber-soft);
  border-radius: 999px; padding: 3px 8px; margin-right: 4px;
}

.hero { padding: 3px 2px 0; }
.hero__day {
  font-family: var(--serif); font-size: clamp(23px, 6.5vw, 28px); line-height: 1.1;
  letter-spacing: -.015em;
}
.hero__sub { margin-top: 4px; color: var(--muted); font-size: 13.5px; line-height: 1.4; }
/* The day's work is the one fact worth reading at a glance, so it carries ink
   and weight while the rest of the line stays quiet. */
.hero__work { color: var(--ink); font-weight: 650; }
.dot { width: 4px; height: 4px; border-radius: 50%; background: var(--faint); display: inline-block; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: var(--pad);
  overflow: hidden;
}
.card--flat { box-shadow: none; background: var(--surface-2); }
.card__head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 9px;
}
.card__title {
  font-size: 11.5px; font-weight: 650; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted);
}
.card__badge {
  margin-left: auto; font-size: 11.5px; font-weight: 600; color: var(--muted);
  background: var(--paper-2); border-radius: 999px; padding: 2px 8px;
}
.badge-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); }
.badge-dot--terracotta { background: var(--terracotta); }
.badge-dot--green { background: var(--green); }
.badge-dot--amber { background: var(--amber); }
.badge-dot--blue { background: var(--blue); }
.badge-dot--plum { background: var(--plum); }

/* ---------- catch-up ---------- */
.catchup {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--plum-soft); border: 1px solid color-mix(in srgb, var(--plum) 22%, transparent);
  border-radius: var(--radius-sm); padding: 12px 14px;
}
.catchup__text { font-size: 14.5px; color: var(--ink-2); }
.catchup__list { margin: 8px 0 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.catchup__list li { font-size: 13.5px; color: var(--ink-2); display: flex; gap: 8px; }
.catchup__list .k { color: var(--plum); font-weight: 600; }
.catchup__close { margin-left: auto; }

/* ---------- summary strip ---------- */
.strip { display: grid; grid-template-columns: 1.15fr 1fr; gap: 12px; }
@media (max-width: 380px) { .strip { grid-template-columns: 1fr; } }
.tile {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 14px; display: flex; flex-direction: column; gap: 4px; min-height: 92px;
}
.tile__label { font-size: 11px; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); font-weight: 600; }
.tile__value { font-size: 20px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.tile__meta { font-size: 13px; color: var(--muted); }
.tile--work { background: var(--blue-soft); border-color: color-mix(in srgb, var(--blue) 20%, transparent); }
.tile--off { background: var(--surface-2); }
.tile--unknown { background: var(--amber-soft); border-color: color-mix(in srgb, var(--amber) 25%, transparent); }
.tile--weather { background: linear-gradient(160deg, var(--surface), var(--surface-2)); }

/* ---------- briefing ---------- */
.brief__summary {
  font-family: var(--serif); font-size: 17px; line-height: 1.4; color: var(--ink);
  letter-spacing: -.005em;
}
.brief__meta { margin-top: 10px; font-size: 12.5px; color: var(--faint); display: flex; gap: 8px; align-items: center; }
.focus { margin: 12px 0 0; padding: 0; list-style: none; counter-reset: focus; display: grid; gap: 8px; }
.focus li {
  counter-increment: focus; display: grid; grid-template-columns: 26px 1fr; gap: 10px;
  padding-top: 8px; border-top: 1px dashed var(--line);
}
.focus li:first-child { border-top: 0; padding-top: 0; }
.focus li::before {
  content: counter(focus); font-size: 12px; font-weight: 700; color: var(--terracotta);
  background: var(--terracotta-soft); border-radius: 50%; width: 22px; height: 22px;
  display: grid; place-items: center;
}
.focus__title { font-weight: 600; font-size: 15.5px; }
.focus__why { font-size: 13.5px; color: var(--muted); margin-top: 1px; }
.lookout {
  margin-top: 14px; padding: 10px 12px; border-radius: 12px; background: var(--amber-soft);
  font-size: 13.5px; color: var(--ink-2); display: flex; gap: 9px; align-items: flex-start;
}
.lookout svg {
  width: 16px; height: 16px; flex: none; margin-top: 2px;
  fill: none; stroke: var(--amber); stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
}
.brief__empty { color: var(--muted); font-size: 14.5px; }

/* ---------- task rows ---------- */
.rows { display: grid; gap: 2px; margin: -4px; }
.row {
  display: grid; grid-template-columns: 22px 1fr auto; gap: 7px; align-items: start;
  padding: 7px 3px; border-radius: 12px; text-align: left; background: none; border: 0;
  cursor: pointer; width: 100%; transition: background .15s ease;
}
.row:hover { background: var(--surface-2); }
.row:active { background: var(--paper-2); }
.row:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.check {
  width: 22px; height: 22px; border-radius: 50%; border: 1.6px solid var(--line-strong);
  display: grid; place-items: center; background: var(--surface); color: transparent;
  transition: border-color .15s, background .15s, color .15s; flex: none; cursor: pointer;
  position: relative;
}
/* The circle stays small; the touch target does not. */
.check::after {
  content: ""; position: absolute; inset: -10px; border-radius: 50%;
}
.check:hover { border-color: var(--green); color: var(--green); }
/* The tick has to be visible the moment it is pressed, before the request
   returns: a tick that only appears once the list has already lost the row
   looks like nothing happened. */
.check[aria-checked="true"], .check.is-checked {
  background: var(--green); border-color: var(--green); color: var(--paper);
}
.check.is-checked svg { animation: tick .18s cubic-bezier(.2,.9,.3,1.4); }
@keyframes tick { from { transform: scale(.5); opacity: .2; } }
.check svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.row__body { min-width: 0; }
.row__title { font-size: 14.5px; line-height: 1.3; overflow-wrap: anywhere; }
.row__meta { margin-top: 1px; font-size: 12px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 3px 6px; align-items: center; }
.row__labels { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 4px; }
.row__labels .tag { background: transparent; border: 1px solid var(--line); color: var(--muted); font-size: 10.5px; padding: 0 6px; }
.row__chev { color: var(--faint); align-self: center; transition: transform .2s ease; }
.row__chev svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; }
.row[aria-expanded="true"] .row__chev { transform: rotate(90deg); }

.task-group + .task-group { margin-top: 8px; }
.task-group__name {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .09em; color: var(--faint);
  font-weight: 650; margin-bottom: 2px;
}
.overdue-text { color: var(--danger); }
.tag {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600;
  padding: 0 6px; border-radius: 999px; background: var(--paper-2); color: var(--ink-2);
}
.tag--due { background: var(--blue-soft); color: var(--blue); }
.tag--late { background: var(--terracotta-soft); color: var(--danger); }
.tag--rec { background: var(--green-soft); color: var(--green); }

/* An expanding row measures itself without JavaScript: the wrapper is a grid
   whose single row goes from 0fr to 1fr, so the content below moves smoothly
   instead of jumping when a task or message opens. */
.detail { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .24s cubic-bezier(.22,.61,.24,1); }
.detail.is-open { grid-template-rows: 1fr; }
.detail__inner { overflow: hidden; min-height: 0; padding: 4px 0 10px 40px; display: grid; gap: 10px; }
.detail--mail .detail__inner { padding-left: 26px; }
.mail-shell { display: block; }
.detail__facts { display: grid; gap: 4px; font-size: 13.5px; color: var(--ink-2); }
.detail__facts div { display: flex; gap: 8px; }
.detail__facts dt { color: var(--muted); min-width: 84px; }
.detail__facts dd { margin: 0; }
.detail__desc {
  font-size: 14px; line-height: 1.55; color: var(--ink-2); white-space: pre-line;
  padding-left: 12px; border-left: 2px solid var(--line-strong); margin: 0;
}
/* A collapsing row is measured first, so its height can animate to zero. */
.is-removing { pointer-events: none; }
.actions { display: flex; flex-wrap: wrap; gap: 8px; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 40px; padding: 0 13px; border-radius: 999px; border: 1px solid var(--line-strong);
  background: var(--surface); font-size: 13.5px; font-weight: 600; cursor: pointer;
  transition: transform .12s ease, background .15s ease, border-color .15s;
  text-decoration: none;
}
.btn:hover { background: var(--surface-2); }
.btn:active { transform: scale(.98); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn--primary { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn--primary:hover { background: var(--ink-2); }
.btn--ghost { border-color: var(--line); background: transparent; }
.btn--ghost:hover { background: var(--surface-2); }
.btn--danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); background: var(--terracotta-soft); }
.btn--sm { min-height: 40px; padding: 0 11px; font-size: 12.5px; }
.btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- mail ---------- */
.mail { display: grid; gap: 2px; }
.mail__row { grid-template-columns: 10px 1fr auto; }
.mail__pip { width: 7px; height: 7px; border-radius: 50%; background: var(--amber); margin-top: 9px; }
.mail__from { font-size: 13px; color: var(--muted); }
.mail__subject { font-size: 14.5px; line-height: 1.32; font-weight: 550; }
.mail__reason { margin-top: 2px; font-size: 12.5px; color: var(--ink-2); }
.mail__snippet { margin-top: 5px; font-size: 12.5px; color: var(--muted); }
.state-pill { font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
.state-pill--archived { color: var(--green); }
.state-pill--unknown { color: var(--amber); }
.state-pill--failed { color: var(--danger); }

/* ---------- completed ---------- */
/* A collapsed card is one line of text: pad it like one, not like a card full of
   content. The open state still gets its own spacing from the body. */
.card.collapsible { padding-top: 8px; padding-bottom: 8px; }
.collapsible__head {
  display: flex; align-items: center; gap: 10px; width: 100%; background: none; border: 0;
  padding: 4px 0; cursor: pointer; text-align: left; min-height: 40px;
}
.collapsible__chev { margin-left: auto; color: var(--faint); transition: transform .2s; }
.collapsible__chev svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; }
.collapsible[data-open="true"] .collapsible__chev { transform: rotate(180deg); }
.done-item { display: flex; gap: 10px; padding: 8px 0; font-size: 14px; color: var(--muted); align-items: baseline; }
.done-item + .done-item { border-top: 1px solid var(--line); }
.done-item__time { font-variant-numeric: tabular-nums; font-size: 12.5px; color: var(--faint); min-width: 42px; }
.done-item__text { color: var(--ink-2); text-decoration: line-through; text-decoration-color: var(--line-strong); }

/* ---------- filters ---------- */
.filters {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 1px 2px 3px; margin: 0 -2px;
}
.filter {
  display: inline-flex; align-items: center; gap: 5px; min-height: 40px; padding: 0 12px;
  border-radius: 999px; border: 1px solid var(--line-strong); background: var(--surface);
  font-size: 12.5px; font-weight: 600; cursor: pointer; white-space: nowrap; color: var(--ink-2);
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.filter[aria-selected="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.filter__count { font-size: 12px; font-weight: 700; opacity: .7; }

/* ---------- states ---------- */
.state {
  display: grid; gap: 8px; padding: 26px 18px; text-align: center; color: var(--muted);
  background: var(--surface-2); border: 1px dashed var(--line-strong); border-radius: var(--radius-sm);
}
.state__title { color: var(--ink-2); font-weight: 600; font-size: 15px; }
.state__body { font-size: 13.5px; }
.state--error { background: var(--terracotta-soft); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.gap {
  display: flex; gap: 8px; align-items: flex-start; font-size: 13px; color: var(--ink-2);
  background: var(--amber-soft); border-radius: 12px; padding: 9px 11px;
}
.gap__icon { color: var(--amber); flex: none; margin-top: 1px; }
.gap__icon svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; }
.skeleton { border-radius: 12px; background: linear-gradient(90deg, var(--paper-2) 25%, var(--surface-2) 50%, var(--paper-2) 75%); background-size: 200% 100%; animation: shimmer 1.4s infinite; }
@keyframes shimmer { to { background-position: -200% 0; } }

/* ---------- journal ---------- */
.journal__toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.datechip {
  display: inline-flex; align-items: center; gap: 7px; border: 1px solid var(--line);
  background: var(--surface); border-radius: 999px; padding: 0 12px; min-height: 40px;
  font-size: 13.5px; font-weight: 600; cursor: pointer; white-space: nowrap; line-height: 1.2;
}
.datechip svg { width: 15px; height: 15px; color: var(--muted); stroke-width: 1.7; }
.datechip__chev { display: inline-flex; color: var(--faint); }
.datechip__chev svg { width: 13px; height: 13px; }
.datechip { position: relative; cursor: pointer; }
/* The real date input sits invisibly over the chip; the label forwards the tap
   to the native picker, which is the only reliable route on Android. */
.datechip__input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; padding: 0; cursor: pointer;
}

/* ---------- subtasks ---------- */
.subtasks { display: grid; gap: 6px; padding-top: 2px; }
.subtasks__label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted); font-weight: 700;
}
.subtask { display: flex; gap: 10px; font-size: 14px; color: var(--ink-2); align-items: center; }
.subtask__text { font-size: 14px; color: var(--ink-2); }
.check--sm { width: 20px; height: 20px; border-width: 1.5px; }
.check--sm::after { inset: -12px; }
.check--sm svg { width: 11px; height: 11px; }

/* ---------- source status ----------
   The old footer was one flex-wrap sentence: "Calendar 2 min ago · Todoist 1 min
   ago …". As a grid with a dot per source it reads as a panel, and a failure
   shows locally instead of hiding inside the line. */
.status-foot { padding: 2px 6px 6px; }
.status-foot .status { gap: 4px 16px; }
.status-foot .status__item { font-size: 12px; }
.status-foot .status__dot { opacity: .35; }
.status { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 16px; }
@media (max-width: 359px) { .status { grid-template-columns: 1fr; } }
.status__item {
  display: grid; grid-template-columns: 6px 1fr auto; align-items: baseline; gap: 7px;
  font-size: 12.5px; min-width: 0;
}
.status__dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--green);
  opacity: .5; align-self: center;
}
.status__label { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status__time { color: var(--faint); font-variant-numeric: tabular-nums; white-space: nowrap; }
.status__item--failed .status__dot { background: var(--amber); opacity: 1; }
.status__item--failed .status__time { color: var(--danger); }
.card--flat > .card__head { margin-bottom: 7px; }

/* ---------- update prompt ---------- */
.update-bar {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(88px + env(safe-area-inset-bottom)); z-index: 65;
  display: flex; gap: 12px; align-items: center; flex-wrap: nowrap;
  background: var(--ink); color: var(--paper);
  padding: 9px 10px 9px 16px; border-radius: 16px;
  box-shadow: var(--shadow-md); font-size: 13.5px; max-width: 94vw;
  animation: rise .2s ease;
}
.update-bar__text { white-space: nowrap; }
.update-bar .btn { flex: none; }
.update-bar .btn { border-color: transparent; background: color-mix(in srgb, var(--paper) 18%, transparent); color: var(--paper); }
.update-bar .btn:hover { background: color-mix(in srgb, var(--paper) 28%, transparent); }
.journal__editor {
  width: 100%; min-height: 46vh; border: 0; background: transparent; color: var(--ink);
  font-family: var(--serif); font-size: 16.5px; line-height: 1.55; resize: vertical; padding: 0;
  outline: none;
}
.journal__editor::placeholder { color: var(--faint); font-style: italic; }
/* The writing surface uses the space the page actually has, instead of stopping
   at a viewport fraction and leaving a dead area under the card. */
.page > .view { min-height: 100%; }
.page[data-section="journal"] > .view,
.page[data-section="journal"] .read,
.page[data-section="journal"] .card { display: flex; flex-direction: column; flex: 1 1 auto; }
.page[data-section="journal"] .journal__editor { flex: 1 1 auto; min-height: 30vh; }
.savestate { font-size: 12.5px; color: var(--muted); display: flex; gap: 6px; align-items: center; }
.savestate--pending { color: var(--amber); }
.savestate--warning { color: var(--amber); }
.savestate--error { color: var(--danger); }
.savestate--saved { color: var(--green); }
.pulse { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.conflict {
  border: 1px solid color-mix(in srgb, var(--amber) 40%, transparent); background: var(--amber-soft);
  border-radius: var(--radius-sm); padding: 14px; display: grid; gap: 10px;
}
.conflict__cols { display: grid; gap: 10px; }
@media (min-width: 560px) { .conflict__cols { grid-template-columns: 1fr 1fr; } }
.conflict__col { background: var(--surface); border-radius: 10px; padding: 10px; font-size: 13px; white-space: pre-wrap; max-height: 220px; overflow: auto; }
.conflict__label { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-bottom: 6px; font-weight: 700; }

/* ---------- history ---------- */
.daylist { display: grid; gap: 8px; }
.dayrow {
  display: grid; gap: 4px; text-align: left; width: 100%; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 13px 14px; cursor: pointer;
}
.dayrow:hover { border-color: var(--line-strong); }
.dayrow__top { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.dayrow__title { font-weight: 600; font-size: 15px; }
.dayrow__meta { font-size: 12.5px; color: var(--muted); }
.dayrow__summary { font-size: 13.5px; color: var(--muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.upcoming { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(148px, 1fr); gap: 10px; overflow-x: auto; padding: 2px 2px 6px; scrollbar-width: none; scroll-snap-type: x proximity; margin: 0 -6px; }
.upcoming::-webkit-scrollbar { display: none; }
/* A cut-off card at the edge should read as "there is more", not as a mistake. */
.upcoming {
  mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 22px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 22px), transparent 100%);
}
.upday {
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px; background: var(--surface);
  display: grid; gap: 2px; text-align: left; cursor: pointer; min-width: 148px; scroll-snap-align: start;
}
.upday__name { font-size: 12px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); font-weight: 650; }
.upday__shift { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.upday__shift--unknown { color: var(--faint); font-weight: 550; }
.upday__meta { font-size: 12.5px; color: var(--faint); }

/* ---------- tabbar ---------- */
.tabbar {
  position: relative; flex: none; z-index: 40;
  display: flex; justify-content: center; gap: 6px;
  padding: 6px 10px calc(6px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: saturate(140%) blur(16px);
  border-top: 1px solid var(--line);
}
/* One pill slides between the tabs, so the bar and the pages share a single
   piece of motion instead of each animating on its own. pager.js positions it
   from the tabs' real geometry, which keeps the rail layout working too. */
.tabbar__pill {
  position: absolute; left: 0; top: 0; z-index: 0;
  border-radius: 12px; background: var(--terracotta-soft);
  pointer-events: none;
  will-change: transform, width, height;
}
.tab {
  position: relative; z-index: 1;
  flex: 1; max-width: 220px; display: grid; justify-items: center; gap: 2px;
  background: none; border: 0; padding: 5px 4px; border-radius: 12px; cursor: pointer;
  color: var(--muted); font-size: 11px; font-weight: 600; letter-spacing: .01em;
  transition: color .18s ease, transform .12s ease;
}
.tab:active { transform: scale(.96); }
.tab svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.tab.is-active { color: var(--terracotta); }

/* ---------- toasts + sheet ---------- */
.toast-wrap {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(96px + env(safe-area-inset-bottom)); z-index: 60;
  display: grid; gap: 8px; width: min(92vw, 420px);
}
.toast {
  cursor: pointer;
  background: var(--ink); color: var(--paper); border-radius: 14px; padding: 11px 14px;
  font-size: 14px; box-shadow: var(--shadow-md); display: flex; gap: 10px; align-items: center;
  animation: rise .2s ease;
}
.toast--error { background: var(--danger); color: #fff; }
.toast--ok { background: var(--green); color: #fff; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }
.sheet-backdrop {
  position: fixed; inset: 0; background: rgba(24, 16, 10, .42); z-index: 70;
  backdrop-filter: blur(2px); animation: fade .15s ease;
}
@keyframes fade { from { opacity: 0; } }
.sheet {
  position: fixed; z-index: 71; left: 50%; transform: translateX(-50%);
  bottom: 0; width: min(100%, 560px); max-height: 88dvh; overflow: auto;
  background: var(--surface); border-radius: 24px 24px 0 0; padding: 20px 20px calc(24px + env(safe-area-inset-bottom));
  box-shadow: var(--shadow-md); animation: slideup .22s cubic-bezier(.2,.8,.2,1);
}
@media (min-width: 640px) {
  .sheet { bottom: 24px; border-radius: 24px; }
}
@keyframes slideup { from { transform: translate(-50%, 24px); opacity: .6; } }
/* The handle is not decoration: it is the grip for the drag-to-dismiss gesture,
   and it tells the eye the panel can be pulled down. */
.sheet__handle {
  width: 38px; height: 4px; border-radius: 999px; background: var(--line-strong);
  margin: -6px auto 12px; touch-action: none;
}
.sheet__head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; touch-action: none; }
.sheet__head:active { cursor: grabbing; }
.sheet__title { font-family: var(--serif); font-size: 20px; }
.sheet__close { margin-left: auto; }
.field { display: grid; gap: 6px; margin-bottom: 14px; }
.field label { font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); font-weight: 650; }
.field input, .field textarea, .field select {
  font: inherit; font-size: 15px; padding: 11px 12px; border-radius: 12px;
  border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--ink); width: 100%;
}
.field input:focus, .field textarea:focus, .field select:focus { outline: 2px solid var(--blue); outline-offset: 1px; }
.chipset { display: flex; flex-wrap: wrap; gap: 7px; }
.chip {
  border: 1px solid var(--line-strong); background: var(--surface); border-radius: 999px;
  padding: 6px 11px; font-size: 13px; cursor: pointer;
}
.chip[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.sheet__actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 6px; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ---------- outlook device code ---------- */
.olcode {
  margin: 8px 0 10px; padding: 12px 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 22px; letter-spacing: .16em; font-weight: 600;
  color: var(--ink); background: var(--card); border: 1px dashed var(--line-strong);
  border-radius: 12px; text-align: center; user-select: all;
}

/* ---------- outlook folder picker ---------- */
.olselect {
  width: 100%; margin-bottom: 8px; padding: 10px 12px;
  font: inherit; font-size: 14px; color: var(--ink);
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: 10px; appearance: none;
}
.olselect:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---------- grouped mail ---------- */
.mailgroup { border-bottom: 1px solid var(--line); }
.mailgroup:last-child { border-bottom: 0; }
.mailgroup__body { padding-left: 12px; border-left: 2px solid var(--line); margin-left: 14px; }
.catchup__more {
  font: inherit; font-size: 13px; color: var(--ink); text-decoration: underline;
  background: none; border: 0; padding: 0 0 0 4px; cursor: pointer;
}

/* ---------- weather icon and mail time ---------- */
.wicon { display: inline-flex; align-items: center; margin-right: 6px; vertical-align: -2px; color: var(--ink-2); }
.wicon svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.tile__value { display: inline-flex; align-items: center; }
.mail__when { margin-left: 8px; font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }

/* ---------- next hours ---------- */
.tile__range { margin-left: 8px; font-size: 13px; font-weight: 500; color: var(--muted); }
.hours {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 14px;
  background: var(--card);
}
.hour { display: grid; justify-items: center; gap: 2px; }
.hour__time { font-size: 11.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
.hour__temp { font-size: 14.5px; font-weight: 600; color: var(--ink); }
.hour__rain { font-size: 11px; color: var(--blue, #7aa2ff); font-variant-numeric: tabular-nums; }

/* ---------- weather card ---------- */
.wcard { padding: 13px 13px 10px; }
.wcard__top { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.wcard__icon { color: var(--ink-2); align-self: center; }
.wcard__icon svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.wcard__temp { font-size: 34px; font-weight: 600; letter-spacing: -0.02em; line-height: 1; }
.wcard__range { font-size: 14px; color: var(--muted); font-weight: 500; }
.wcard__place { margin-left: auto; font-size: 12.5px; color: var(--faint); }
.wcard__hint { margin-top: 8px; font-size: 13.5px; color: var(--ink-2); }
.whours {
  margin-top: 12px; display: grid; grid-auto-flow: column; grid-auto-columns: 68px;
  gap: 4px; overflow-x: auto; scroll-snap-type: x proximity; padding-bottom: 2px;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.whours::-webkit-scrollbar { display: none; }
.whour {
  scroll-snap-align: start; display: grid; justify-items: center; gap: 2px;
  padding: 4px 0; border-radius: 10px; background: color-mix(in srgb, var(--ink) 4%, transparent);
  /* What a filled icon part must match to disappear into this tile. */
  --wx-behind: color-mix(in srgb, var(--ink) 4%, var(--surface));
}
.whour__time { font-size: 11.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
.whour__icon { color: var(--ink-2); }
.whour__icon svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.whour__temp { font-size: 14px; font-weight: 600; color: var(--ink); }
.wcard__sun { margin-top: 9px; font-size: 12px; color: var(--muted); }
.whour__rain { font-size: 10.5px; color: var(--blue, #7aa2ff); font-variant-numeric: tabular-nums; }

/* Weather is drawn in parts, not tinted as a whole: the sun is amber, cloud a
   grey-blue, rain blue, snow pale, a storm's bolt plum. Partly-cloudy therefore
   reads as a sun *and* a cloud — the earlier single-tone version made "clear" and
   "partly" two slightly different ambers, which on a clear day looked like one
   colour everywhere. */
:root {
  --wx-moon: #8a7c5e;
  --wx-cloud: #77848c;
  --wx-drop: #2f5f7d;
  --wx-drop-soft: #6ba3c4;
  --wx-flake: #6b98b6;
}

.wx-sun { color: var(--amber); }
.wx-cloud { color: var(--wx-cloud); }
/* A cloud that must cover what is behind it. Stroke-only shapes have no depth,
   so this one is filled with whatever surface it sits on — the card by default,
   the hour tile (which carries a 4% ink tint) inside the strip. */
.wx-cloud--front { fill: var(--wx-behind, var(--surface)); }
.wx-drop { color: var(--wx-drop); }
.wx-flake { color: var(--wx-flake); }
.wx-bolt { color: var(--plum); }
.wx-moon { color: var(--wx-moon); }
.wx-star { color: var(--wx-moon); opacity: .65; }
.wx-fog { color: color-mix(in srgb, var(--faint) 45%, var(--ink-2)); }

/* Showers fall lighter than steady rain, so the two do not read as one shape. */
.wx--showers .wx-drop { color: var(--wx-drop-soft); }

@media (prefers-color-scheme: dark) {
  :root {
    --wx-moon: #f0e4cd;
    --wx-cloud: #9aa9b1;
    --wx-drop: #8fb4cc;
    --wx-drop-soft: #c3e0f2;
    --wx-flake: #b3d2e6;
  }
  .wx-fog { color: color-mix(in srgb, var(--faint) 40%, var(--ink-2)); }
}

/* A soft edge tells the eye the hour strip continues, without a scrollbar. */
.whours {
  mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent 100%);
}

/* ---------- column wrappers ----------
   These are inert on a phone: one column, the same 14px rhythm the view already
   had. The desktop block below turns the same markup into two columns, so no
   view has to know which screen it is on. */
.cols { display: grid; gap: 14px; }
.col { display: grid; gap: 14px; align-content: start; min-width: 0; }
.colgrid { display: grid; gap: 14px; align-items: start; }
.read { min-width: 0; }
.read > * + * { margin-top: 14px; }

/* ---------- desktop ----------
   Phone layout first: everything here is additive above 1024px. The bottom tab
   bar becomes a left rail, the day splits into "what is happening" beside "what
   to do", and task lists use two columns instead of one long scroll. */
@media (min-width: 1024px) {
  :root { --rail: 236px; }

  body { padding-bottom: 0; padding-left: var(--rail); }

  .tabbar {
    position: fixed; inset: 0 auto 0 0; width: var(--rail);
    flex-direction: column; justify-content: flex-start; align-items: stretch;
    gap: 3px; padding: 18px 12px;
    border-top: 0; border-right: 1px solid var(--line);
    background: var(--paper-2); backdrop-filter: none;
  }
  .tabbar::before {
    content: "";
    width: 30px; height: 30px; flex: none;
    margin: 2px 0 20px 12px;
    background: url("/icons/icon-192.png") center / contain no-repeat;
    border-radius: 9px;
  }
  .tab {
    flex: 0 0 auto; max-width: none; width: 100%;
    display: flex; align-items: center; justify-items: start;
    gap: 11px; padding: 10px 12px; border-radius: 12px;
    font-size: 14.5px; text-align: left;
  }
  .tab svg { width: 20px; height: 20px; }

  .topbar__inner { max-width: 1120px; padding: 14px 28px 10px; }
  .page, .detail-layer { padding-inline: max(28px, calc((100% - 1120px) / 2)); }
  .hero { padding-top: 8px; }
  .hero__day { font-size: 34px; }

  /* The day reads left to right: context and briefing, then the work. */
  .cols { grid-template-columns: minmax(0, 1.5fr) minmax(320px, 1fr); gap: 18px; align-items: start; }
  .colgrid { grid-template-columns: 1fr 1fr; gap: 16px; }
  /* One card alone, or an odd one left over, spans the width: half a page of
     empty space reads as a broken grid, not as breathing room. */
  .colgrid > :only-child,
  .colgrid > :last-child:nth-child(odd) { grid-column: 1 / -1; }

  /* A little more air than the phone: the space is there, and the phone's
     density would look mean on a 1440-wide window. */
  .card { padding: 16px; }

  /* Long lists read better narrower even when there is room. `width: 100%` is
     load-bearing: inside a column flex container, auto margins make an item
     shrink to fit, which collapsed the journal to its text width. */
  .read { width: 100%; max-width: 780px; margin-inline: auto; }

  /* Denser rows: the pointer replaces the thumb, so padding can shrink. */
  .row { padding: 8px 6px; }
  .detail { padding-left: 46px; }

  .journal__editor { min-height: 56vh; font-size: 17.5px; }

  /* Toasts and the update bar sit in the content area, not over the rail. */
  .toast-wrap { left: auto; right: 28px; bottom: 24px; transform: none; }
  .update-bar { left: auto; right: 28px; transform: none; bottom: 84px; }
  .sheet { bottom: auto; top: 50%; transform: translate(-50%, -50%); }
  @keyframes slideup { from { opacity: 0; } }
}
