/*
 * Ember, light. The default, and the only block that states every token —
 * a hue is a short list of overrides on top of this, and a brightness is
 * another. No component knows which is on.
 *
 * The ladder (--r1 to --r5) is not decoration: it is how far down the
 * escalation something has gone. It stays a warm ramp in every hue, because
 * recolouring urgency to match a chosen accent trades a meaning for a mood.
 * Each hue moves only its far end, and only far enough to stay legible.
 */
:root {
  --bg: #f5f0e6;
  --bg-soft: #ebe4d6;
  --card: #fbf8f1;
  --card-hi: #f1ebdf;
  --line: #ddd4c2;
  --line-soft: #e8e0d0;
  /* --dim carries the item's name now, in the small-caps line above the voice.
     It was the faintest token in the palette when it only had to recede, and
     every value here clears 4.5:1 on its own ground because of that move. */
  --text: #292521;
  --muted: #6b6257;
  --dim: #766c5d;

  --accent: #a8462a;
  --accent-soft: #8a3822;
  --good: #1f5c3a;

  /* The same three colours again as bare channels, because a tint of the
     accent is written a dozen ways across this file and rgba() cannot take a
     hex. Without these, changing the scheme would recolour the solid accent
     and leave every wash behind it the old terracotta. */
  --accent-rgb: 168, 70, 42;
  --good-rgb: 31, 92, 58;
  --bad-rgb: 148, 48, 31;
  --warm-rgb: 168, 128, 42;

  /* Text that has to stay legible on a coloured ground, and the two hovers.
     Held here so a dark brightness can flip them; a scheme that does not say
     otherwise gets exactly this. */
  --on-accent: #fbf8f1;
  --accent-hi: #94301f;
  --btn-hi: #efe8db;
  --text-good: #1a4e31;
  --text-bad: #8a3822;
  --text-hot: #7a2318;
  --text-error: #94301f;

  --r1: #a8802a;
  --r2: #b5642a;
  --r3: #a8462a;
  --r4: #94301f;
  --r5: #7a2318;

  /* The voice is set in a serif at reading size; everything that is interface
     rather than speech stays in the sans. Two roles, named rather than
     repeated down the file. */
  /*
   * One stack, three answers, and each one is chosen rather than arrived at.
   *
   * ui-serif is a Safari generic: Chrome ignores it entirely, which means it
   * does nothing on Android and nothing on desktop Chrome either. Measured
   * rather than assumed — `ui-serif` alone renders at exactly the width of the
   * generic `serif` in Chrome.
   *
   * So the rest of the list is not decoration:
   *   iOS / macOS Safari  ui-serif    New York, drawn for screens
   *   macOS Chrome        Charter
   *   Windows             Georgia
   *   Android             Noto Serif  named, not left to the generic
   *
   * Iowan Old Style, which this named before, is a book face from 1990 and read
   * like one at interface sizes.
   */
  --serif: ui-serif, "New York", Charter, Georgia, "Noto Serif", serif;
  /* system-ui leads because it is the one generic every engine implements:
     SF on Apple, Roboto on Android, Segoe on Windows. ui-sans-serif is Safari
     only and -apple-system is for Safari versions older than that. */
  --sans: system-ui, ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  /*
   * A third role, for the small uppercase labels above a card and over a tier:
   * they are signposts rather than sentences, and a monospace at 11px with
   * letter-spacing reads as one. The handoff named Geist Mono; this stays with
   * the platform's own the way the other two stacks do, so the app keeps
   * loading no fonts at all — which is also why it renders instantly offline.
   */
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Roboto Mono", monospace;

  --radius: 16px;
  --shadow: 0 10px 30px rgba(0, 0, 0, .10);
}

/*
 * Three edges, derived rather than stated, so every hue in light and dark gets
 * one without a value of its own — and a hue added later cannot forget.
 *
 *   --edge   what a control is drawn with: a button, an input, a tick box. It
 *            has to be seen to be used, so it is held to 3:1 by
 *            test/contrast.test.mjs on every ground.
 *   --track  the unfilled part of a bar, so the filled part reads as a share.
 *   --rule   the border of a card or a sheet. It only has to be there, which
 *            is why it stays close to --line.
 *
 * --line and --line-soft are left alone: they are still the hairlines inside a
 * card, where a stronger colour would read as a grid.
 */
:root {
  --edge: color-mix(in srgb, var(--text) 58%, var(--card));
  --track: color-mix(in srgb, var(--text) 30%, var(--card));
  --rule: color-mix(in srgb, var(--line) 62%, var(--text));
}

/*
 * A browser without color-mix (Safari before 16.2, Chrome before 111) cannot
 * read the three above, and a border whose colour cannot be read is not drawn
 * at all — every button and field would lose its edge. Those browsers get plain
 * colours instead: Ember's, one set per brightness. test/contrast.test.mjs
 * measures this set against every hue too, so it cannot drift into unreadable.
 */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  :root { --edge: #857a6a; --track: #b3a78f; --rule: #b8ab94; }
  :root[data-bright="dark"] { --edge: #8a7e6e; --track: #5c5245; --rule: #544a3d; }
}

* { box-sizing: border-box; }

/* Must beat the ID-level display rules below. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  font-size: 16px;
  line-height: 1.5;
}

body {
  min-height: 100dvh;
  background-image:
    radial-gradient(900px 500px at 15% -10%, rgba(var(--accent-rgb), .10), transparent 70%),
    radial-gradient(700px 400px at 100% 0%, rgba(var(--warm-rgb), .06), transparent 60%);
  background-attachment: fixed;
}

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -0.015em; }
p { margin: 0; }
button, input { font: inherit; color: inherit; }

/*
 * Keyboard focus, for everything. The rules further down that remove an outline
 * are all on text fields, which show focus with their own border and glow; a
 * button, a tab, a tick box or a link had nothing, so somebody using a keyboard
 * could not tell where they were. Nothing here shows for a mouse or a tap.
 */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* An icon from the sprite in index.html: as tall as the words beside it, and
   the colour of them. */
.ico {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  vertical-align: -0.25em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.muted { color: var(--muted); }
/* Body copy, everywhere. This one rule is most of the app's prose. */
.small { font-size: calc(13px * var(--k)); line-height: 1.5; }
.center { text-align: center; }

/* ----------------------------- screens ----------------------------- */

.screen[hidden] { display: none; }

#auth, #setup {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100dvh;
  padding:
    calc(24px + var(--safe-top))
    calc(24px + var(--safe-right))
    calc(24px + var(--safe-bottom))
    calc(24px + var(--safe-left));
}

.card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 20px;
  padding: 30px;
  box-shadow: var(--shadow);
}
.card.narrow { width: 100%; max-width: 400px; }

.logo {
  font-size: 26px;
  text-align: center;
  background: linear-gradient(100deg, var(--accent-soft), var(--accent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.tagline {
  text-align: center;
  color: var(--muted);
  font-size: 14px;
  margin: 8px 0 24px;
}
.setup-msg {
  margin: 18px 0 14px;
  padding: 14px 16px;
  border-radius: 12px;
  background: rgba(var(--accent-rgb), .1);
  border: 1px solid rgba(var(--accent-rgb), .3);
  font-size: 14px;
  line-height: 1.55;
}

/* ------------------------------ forms ------------------------------ */

.tabs {
  display: flex;
  gap: 4px;
  background: var(--bg-soft);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 4px;
  margin-bottom: 22px;
}
.tab {
  flex: 1;
  padding: 9px 12px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.tab.is-active { background: var(--card-hi); color: var(--text); }

.field { display: block; margin-bottom: 15px; }
.field > span {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 7px;
}
.field input {
  width: 100%;
  padding: 12px 14px;
  background: var(--bg-soft);
  border: 1px solid var(--edge);
  border-radius: 11px;
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.field input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .16);
}

/* A password with a way to see it. The wrapper is a span inside the label, and
   the label text above it is styled as `.field > span`, so it takes the label's
   look back to plain rather than inheriting it. */
.field > .pw-wrap {
  display: block;
  position: relative;
  margin: 0;
  font: inherit;
  letter-spacing: normal;
  text-transform: none;
  color: inherit;
}
.pw-wrap input { padding-right: 48px; }
.pw-toggle {
  position: absolute;
  top: 50%;
  right: 2px;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.pw-toggle:hover { color: var(--text); }
.pw-toggle[aria-pressed="true"] { color: var(--text); }

.error {
  margin: 4px 0 14px;
  color: var(--text-error);
  font-size: 13.5px;
  line-height: 1.5;
}
.error[hidden] { display: none; }

.notice {
  margin: 4px 0 14px;
  padding: 2px 0 2px 14px;
  border-radius: 0;
  background: none;
  border: 0;
  border-left: 2px solid var(--good);
  color: var(--text-good);
  font-size: 13.5px;
  line-height: 1.55;
}
.notice[hidden] { display: none; }

/* remember me */

.remember {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  margin: 2px 0 16px;
  cursor: pointer;
  user-select: none;
}
.remember input {
  appearance: none;
  flex-shrink: 0;
  width: 20px; height: 20px;
  margin-top: 1px;
  border: 1px solid var(--edge);
  border-radius: 6px;
  background: var(--bg-soft);
  cursor: pointer;
  transition: background .15s, border-color .15s;
  position: relative;
}
.remember input:checked {
  background: var(--accent);
  border-color: var(--accent);
}
.remember input:checked::after {
  content: '';
  position: absolute;
  left: 6px; top: 2px;
  width: 5px; height: 10px;
  border: solid var(--on-accent);
  border-width: 0 2px 2px 0;
  transform: rotate(42deg);
}
.remember input:focus-visible { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .2); }
.remember > span { display: block; min-width: 0; }
.remember strong { font-size: 14.5px; font-weight: 600; display: block; }
.remember em {
  display: block;
  font-style: normal;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--dim);
  margin-top: 2px;
}

/* a button that reads as a link */

.linkish {
  background: none;
  border: 0;
  padding: 0;
  color: var(--accent-soft);
  font-size: 13.5px;
  font-weight: 550;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(240, 168, 130, .35);
}
.linkish:hover { color: var(--accent); text-decoration-color: currentColor; }

.prompt-actions {
  display: flex;
  align-items: center;
  /* Wide enough that the two invisible reaches below do not meet: the link
     stretches 6px past itself and the × stretches 8px, and an overlap is a tap
     answered by whichever element happens to paint last. */
  gap: 16px;
  flex-shrink: 0;
}

/* notification help */

.help-step {
  display: flex;
  gap: 13px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
}
.help-step:last-child { border-bottom: 0; }
.help-num {
  flex-shrink: 0;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--card-hi);
  border: 1px solid var(--line);
  font-size: 12.5px;
  font-weight: 650;
  color: var(--accent-soft);
}
.help-step p { font-size: 14.5px; line-height: 1.5; }
.help-step .sub { font-size: 13px; color: var(--muted); margin-top: 3px; }
.help-state {
  padding: 13px 15px;
  border-radius: 12px;
  font-size: 14px;
  line-height: 1.55;
  margin-bottom: 4px;
}
.help-state.bad {
  background: rgba(var(--bad-rgb), .13);
  border: 1px solid rgba(var(--bad-rgb), .35);
  color: var(--text-bad);
}
.help-state.good {
  background: rgba(var(--good-rgb), .1);
  border: 1px solid rgba(var(--good-rgb), .3);
  color: var(--text-good);
}
kbd {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 6px;
  background: var(--card-hi);
  border: 1px solid var(--line);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
}

/* ----------------------------- buttons ----------------------------- */

.btn {
  border: 1px solid var(--edge);
  background: var(--card-hi);
  border-radius: 11px;
  padding: 11px 18px;
  font-weight: 600;
  font-size: 14.5px;
  cursor: pointer;
  transition: transform .12s, background .15s, border-color .15s, opacity .15s;
}
.btn:hover { background: var(--btn-hi); }
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .5; cursor: default; }
.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.btn.primary:hover { background: var(--accent-hi); }
.btn.ghost { background: transparent; color: var(--muted); }
.btn.block { width: 100%; margin-top: 6px; }
.btn.small {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 8px 14px;
  font-size: 13.5px;
  border-radius: 9px;
}

/* Glyphs, not buttons. Three boxed squares in the corner were the only
   containers left on the day screen once the cards went. */
/* 44 is the smallest square a thumb reliably hits, and these three are the
   app's only navigation. The glyph stays the size it was — what grew is the
   room around it, not the drawing. */
.icon-btn {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--dim);
  font-size: 15px;
  cursor: pointer;
  transition: color .15s;
}
.icon-btn:hover { color: var(--text); }

/* ---------------------------- the app bar --------------------------- */

/*
 * Where you are, and the one thing that is not a place.
 *
 * Sticky rather than fixed: it scrolls with the page for its first few pixels
 * and then stays, which keeps the greeting on screen when you land and gets it
 * out of the way once you are reading a list. It sits outside the three
 * screens because it is chrome — switching tabs must not redraw it.
 */
.appbar {
  position: fixed;
  left: 50%;
  bottom: 0;
  z-index: 40;
  width: 100%;
  max-width: 640px;
  transform: translateX(-50%);
  padding: 0 var(--safe-right) var(--safe-bottom) var(--safe-left);
  background: var(--card);
  border: 1px solid var(--rule);
  border-bottom: 0;
  border-radius: 18px 18px 0 0;
}
.appbar[hidden] { display: none; }

/* Four places and a plus, in five equal columns so the plus is the middle one
   on every width. */
.tabs.is-pill,
#tabs {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: center;
  height: var(--bar-h);
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}
.tab-pill {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 56px;
  padding: 6px 2px;
  border: 0;
  border-radius: 12px;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: color .15s;
}
/* The plus is not a tab, so it is not in the tab list; the tabs skip its column
   instead, and it sits over the gap. */
.tab-pill[data-tab="app"] { grid-column: 1; }
.tab-pill[data-tab="people"] { grid-column: 2; }
.tab-pill[data-tab="lists"] { grid-column: 4; }
.tab-pill[data-tab="me"] { grid-column: 5; }
.tab-pill .ico { width: 22px; height: 22px; }
.tab-pill:hover { color: var(--text); }
.tab-pill.is-active { color: var(--accent-soft); }

/* Somebody is waiting to hear that you saw their day. One meaning, one dot, and
   deliberately not a number: four unseen days would read as more pressing than
   one. It sits on the icon, where a badge does. */
.tab-dot {
  position: absolute;
  top: 8px;
  left: calc(50% + 9px);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}

/* The list never nags, so it gets a number rather than a dot: three to get is
   a fact you can act on or ignore. */
.tab-count {
  position: absolute;
  top: 5px;
  left: calc(50% + 9px);
  font-size: 11px;
  font-weight: 650;
  color: var(--dim);
}

/* Adding is the one action that is not a place, so it is the one round thing. */
.tab-add {
  position: absolute;
  top: calc((var(--bar-h) - 48px) / 2);
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(var(--accent-rgb), .3);
}
.tab-add .ico { width: 24px; height: 24px; stroke-width: 2; }

/* A screen that is not the day still says what it is. */
.screen-title {
  font-size: 26px;
  letter-spacing: -.02em;
  margin-bottom: 4px;
}

.lists-screen {
  max-width: 640px;
  margin: 0 auto;
  padding:
    calc(14px + var(--safe-top))
    calc(18px + var(--safe-right))
    calc(var(--bar-h) + 40px + var(--safe-bottom))
    calc(18px + var(--safe-left));
}

/* Me: the week, then settings, then the two buttons that used to sit at the foot
   of the day. */
.me-screen {
  max-width: 640px;
  margin: 0 auto;
  padding:
    calc(14px + var(--safe-top))
    calc(18px + var(--safe-right))
    calc(var(--bar-h) + 40px + var(--safe-bottom))
    calc(18px + var(--safe-left));
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.week {
  padding: 14px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.week-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.week-head .eyebrow { margin: 0; }
.week-days { display: flex; justify-content: space-between; margin-top: 10px; }
.week-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--dim);
}
.week-cell {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--track);
  color: var(--on-accent);
}
.week-cell .ico { width: 18px; height: 18px; stroke-width: 2; }
.week-cell.done { background: var(--good); }
.week-cell.part { background: var(--r1); }
.week-cell.missed { background: var(--r4); }
.week-cell.today { outline: 2px solid var(--text); outline-offset: 2px; }
#weekLine { margin-top: 10px; }

.me-group {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.me-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 52px;
  padding: 0 14px;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: calc(16px * var(--k));
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.me-row:last-child { border-bottom: 0; }
.me-row:hover { background: var(--card-hi); }
.me-label { flex: 1; min-width: 0; }
.me-value { font-size: calc(13px * var(--k)); font-weight: 400; color: var(--muted); }
.me-chev { flex: none; color: var(--dim); font-size: 15px; }
.me-screen .foot { margin-top: 12px; }
.lists-screen .shop { margin-top: 18px; }
.lists-screen #supplies { margin-top: 24px; }
.lists-empty { margin-top: 18px; line-height: 1.6; }

/* ------------------------------- app ------------------------------- */

/*
 * The notch, the home indicator, and the rounded corners of every phone made
 * since 2017.
 *
 * index.html asks for viewport-fit=cover and the manifest installs this
 * standalone — so there is no browser chrome to sit under the notch on the
 * app's behalf, and every edge is the app's own problem. Held as variables
 * because five different things pin themselves to an edge and each one needs
 * the same answer; env() falls back to 0 on a phone without insets and on
 * every desktop, so this costs nothing where it is not needed.
 */
:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/*
 * How big the day reads, chosen on the device it is read on.
 *
 * One multiplier rather than a second set of sizes: the day's type and its row
 * rhythm move together, so Small fits more rows without the words and the
 * spaces between them drifting out of proportion with each other — which is
 * what makes a "compact mode" look squashed rather than smaller.
 *
 * It is deliberately narrow in what it touches: the day's own content. Tap
 * targets, the tab bar and everything in a sheet keep their sizes, because a
 * 44px target is a property of the thumb and not of the type.
 *
 * `--narrow` multiplies on top for phones under 420px, where the same step
 * down was already being made by hand.
 */
:root {
  --scale: 1;
  --narrow: 1;
  --k: var(--scale);
  /* How much of the screen the on-screen keyboard is covering. Set from the
     visual viewport in app.js; zero everywhere there is no keyboard. */
  --keyboard: 0px;
  /* The bottom bar, without the safe area under it. Everything fixed to the
     bottom edge stacks above this. */
  --bar-h: 64px;
}
:root[data-size="small"] { --scale: .88; }
:root[data-size="large"] { --scale: 1.12; }

.app {
  max-width: 640px;
  margin: 0 auto;
  /* The bottom clears the bar, which is fixed over this — or the last row and
     the foot sit underneath it, visible and not clickable. */
  padding:
    calc(14px + var(--safe-top))
    calc(18px + var(--safe-right))
    calc(40px + var(--bar-h) + var(--safe-bottom))
    calc(18px + var(--safe-left));
}

/* Date over greeting, as one block. The date is the way into the month, so it
   is a button — but it is set as the quiet line it reads as, not as a control
   with a box round it. */
/* The head of the day stays put while the list under it scrolls, so how much is
   done and what needs saying are never scrolled away. It is pulled up over the
   screen's own top padding so that it starts at the top edge and keeps the safe
   area for itself. It is the same width as the list beneath it, so nothing
   scrolls past its sides; and it wears the page's own gradient, fixed to the
   window the way the page's is, so there is no seam where it stops. */
.day-head {
  position: sticky;
  top: 0;
  z-index: 20;
  margin: calc(-14px - var(--safe-top)) 0 0;
  padding: calc(6px + var(--safe-top)) 0 6px;
  background-color: var(--bg);
  background-image:
    radial-gradient(900px 500px at 15% -10%, rgba(var(--accent-rgb), .10), transparent 70%),
    radial-gradient(700px 400px at 100% 0%, rgba(var(--warm-rgb), .06), transparent 60%);
  background-attachment: fixed;
}
.topbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}
.topbar-l {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 0;
  /* The space above the day moves with the day: at Small the point is to fit
     more rows, and a fixed gap under the greeting is a row's worth of it. */
  margin: 0 0 calc(4px * var(--k));
}
/* The greeting goes once the day is being read; the count stays. Height and
   opacity rather than display:none, so it goes and comes back rather than
   jumping. */
:root.is-scrolled .topbar-l {
  max-height: 0;
  margin-bottom: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
}
.topbar-l {
  max-height: 200px;
  opacity: 1;
  transition: max-height .18s ease, opacity .14s ease, margin-bottom .18s ease;
}

.today-date {
  position: relative;
  display: flex;
  align-items: center;
  /* 36 tall, and 44 to the finger: the reach below is what a phone screen can
     spare, since this is the top of the day and the day is what it is for. */
  min-height: 36px;
  padding: 2px 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
}
.today-date::after { content: ''; position: absolute; top: -4px; bottom: -4px; left: 0; right: 0; }
.today-date .eyebrow { display: block; }
.today-date:hover .eyebrow { color: var(--text); }
.topbar h1 {
  font-family: var(--serif);
  font-style: italic;
  font-size: calc(28px * var(--k));
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -.01em;
}

/* The app admitting it has stopped working. Loud enough to be believed,
   quiet enough not to be mistaken for a nag — it is not asking for anything. */
.tick-warning {
  margin: 0 0 16px;
  padding: 11px 13px;
  border-left: 3px solid var(--r4);
  background: rgba(var(--bad-rgb), .07);
  border-radius: 0 6px 6px 0;
  font-size: calc(13.5px * var(--k));
  line-height: 1.5;
  color: var(--text-bad);
}
.tick-warning[hidden] { display: none; }

/* Unconfirmed address. A line, not a wall — what waits on it is the mail, and
   the app says exactly that. */
.verify-line {
  margin: 0 0 16px;
  font-size: calc(13.5px * var(--k));
  line-height: 1.55;
  color: var(--muted);
}
.verify-line[hidden] { display: none; }
.verify-line .linkish { font-size: inherit; }



/* The greeting block's own rules live with the block, above. What was here was
   the top bar from before the redesign — one line, date inline beside the
   greeting, and a row of icon buttons on the right — and it was still winning
   on any screen wider than 420px, where the narrow-phone block does not reach.
   So the redesigned greeting only ever appeared on small phones, and the text
   size could not move it. The markup for all three of these is gone. */

.eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 4px;
}

/* A slow pulse, for something that is happening right now. */
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .35; transform: scale(.8); }
}

/* ----------------------------- prompt ------------------------------ */

/* An offer, not a debt — so a hairline above and below rather than the heavy
   rule the standing-debt banner gets. Still no fill: on paper, a tint behind
   text is the thing that reads as an advert. */
.prompt {
  display: flex;
  align-items: baseline;
  gap: 14px;
  justify-content: space-between;
  background: none;
  border: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  padding: 12px 0;
  margin-bottom: 22px;
}
.prompt[hidden] { display: none; }
.prompt strong { font-size: 14.5px; }
/* A filled button here was the loudest thing on the page, sitting above an item
   four hours overdue. An offer does not outrank a debt. */
.prompt .btn {
  flex-shrink: 0;
  border: 0;
  border-radius: 0;
  background: none;
  padding: 0 0 2px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 650;
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* ------------------------------ tiers ------------------------------ */

/*
 * The tier is the card, and the item is a row inside it.
 *
 * A card does two jobs — it decorates and it bounds — and the counter-note
 * layout dropped both to buy reading room. This keeps the second job and pays
 * for it once per tier instead of once per item: five items used to cost five
 * borders, ten paddings and four gaps, which is most of where a screenful of
 * five non-negotiables went.
 */
.tier { margin-bottom: 4px; }
.tier[hidden] { display: none; }
/* A signpost over a run of rows, not a bar across the top of a box. */
.tier-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: calc(18px * var(--k)) 2px calc(6px * var(--k));
  margin: 0;
  border: 0;
  background: none;
  color: var(--dim);
  font-family: var(--mono);
  font-size: calc(11px * var(--k));
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-align: left;
}
/* The ones that are not let go are the ones worth finding at a glance. */

.items { display: flex; flex-direction: column; }

/* ------------------------------ item ------------------------------- */

/*
 * An entry, not a card.
 *
 * A card did two jobs — it decorated, and it bounded. Dropping it for prose at
 * reading size threw away the second along with the first, and a hairline plus
 * an equal margin is not enough structure once one entry's line wraps to three
 * and the next runs to two.
 *
 * So each entry opens with a printed mark, and the space below an entry is
 * smaller than the space above the next one — the gap belongs to what follows
 * it rather than floating between two things. Landmark and rhythm, no box.
 */
.item {
  position: relative;
  padding-bottom: 9px;
}
.item + .item { margin-top: 22px; }

/* The mark. It separates AND it says how late this is: the same stroke does
   both jobs, so lateness costs no extra line on the entry. */
.item-mark {
  width: 26px;
  height: 3px;
  background: var(--dim);
  margin-bottom: 11px;
  transition: width .2s, background .2s;
}
.item.r1 .item-mark { background: var(--r1); }
.item.r2 .item-mark { background: var(--r2); }
.item.r3 .item-mark { background: var(--r3); width: 33px; }
.item.r4 .item-mark { background: var(--r4); width: 40px; }
.item.r5 .item-mark { background: var(--r5); width: 48px; height: 4px; }
.item.done .item-mark { background: var(--good); }
.item.done { opacity: .72; }
.item.skipped { opacity: .55; }
.item.skipped .item-mark { background: var(--track); }

/* Label and time step back into a small-caps line above the voice. */
.item-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
}
.item-label {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
}
.item-when {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: .06em;
  color: var(--dim);
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

/* The voice. The largest thing on the entry, at a size meant for reading
   rather than skimming — which is the whole of this design. */
.item-line {
  font-family: var(--serif);
  font-size: 16.5px;
  line-height: 1.44;
  color: var(--text);
}
.item.r3 .item-line, .item.r4 .item-line { color: var(--text); }
.item.r5 .item-line { color: var(--text); }
.item.done .item-line { color: var(--muted); }

/* Badges lose their pills. They are asides on a printed entry, not chips. */
.badges {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 8px;
  font-family: var(--sans);
}
.badge {
  font-size: 11px;
  letter-spacing: .03em;
  color: var(--dim);
}
.badge.streak { color: var(--muted); }
.badge.rung { color: var(--r4); }
.item.r5 .badge.rung { color: var(--r5); }

/* Controls the size of a signature. An answer needs a word and a rule under
   it, not a filled button — and the two answers are not equals, so the rule
   under "Done" is twice the weight of the one under "Couldn't do it". */
.item-actions {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 12px;
  flex-wrap: wrap;
  font-family: var(--sans);
}
/* Small underlined words rather than buttons, on purpose — but the words were
   also the whole target, and twelve-pixel text is 22px tall. The type is
   unchanged; the box around it is now 44. The rule moves from the element's
   bottom border onto the text, or it would sit a finger's width below it. */
.item-actions .btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  border: 0;
  border-radius: 0;
  background: none;
  padding: 0;
  font-size: 12px;
  font-weight: 550;
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 4px;
}
.item-actions .btn:hover { color: var(--text); text-decoration-color: var(--dim); }
.item-actions .btn.primary,
.item-actions .btn:not(.ghost):not(.danger) {
  color: var(--good);
  font-weight: 650;
  /* The rule is on the word, not on the button's bottom edge — the box is now
     44px tall and a border would draw a line a finger's width below the text. */
  text-decoration-thickness: 2px;
  text-decoration-color: var(--good);
}
.item-actions .btn.danger { color: var(--r5); text-decoration-color: rgba(var(--bad-rgb), .45); }

/* skip confirmation — deliberately more work than just doing the thing */

.item.skip-mode {
  border-left-color: var(--r3);
  background: linear-gradient(90deg, rgba(var(--accent-rgb), .09), transparent 60%);
}
.item.skip-mode.tier1 {
  border-left-color: var(--r5);
  background: linear-gradient(90deg, rgba(var(--bad-rgb), .13), transparent 65%);
}

.skip-q { font-size: 15.5px; font-weight: 600; margin-bottom: 5px; }
/* A question about the item, where a tally of failures used to be. Bordered
   rather than tinted red: it is an offer to change something, not a telling
   off. */
.skip-ask {
  margin: 0 0 12px;
  padding: 10px 11px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 11px;
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
.skip-ask-q { font-size: 14px; font-weight: 600; color: var(--text); }
.skip-ask-sub { font-size: 13px; color: var(--muted); margin-top: 2px; }
.skip-ask-acts { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
/* Said quietly rather than as a warning. It is a fact about where the words go,
   and colouring it like a stakes line would read as a reason not to be honest —
   which is the one outcome this whole field cannot afford. */
.skip-shared {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
  margin-bottom: 7px;
}
.skip-reason {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--edge);
  border-radius: 10px;
  font-size: 14.5px;
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.skip-reason:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .16);
}
.skip-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.skip-actions .btn { flex: 1 1 auto; }

.btn.danger {
  background: transparent;
  border-color: rgba(var(--bad-rgb), .45);
  color: var(--text-error);
}
.btn.danger:hover:not(:disabled) {
  background: rgba(var(--bad-rgb), .14);
  border-color: rgba(var(--bad-rgb), .7);
}

/* counter */
/* The numbers matter; the box around them never did. Tabular figures so a
   tally does not shuffle sideways as it climbs. */
.counter {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--sans);
  font-variant-numeric: tabular-nums;
}
.counter button {
  width: 44px; height: 44px;
  border: 0;
  background: transparent;
  color: var(--dim);
  font-size: 18px;
  line-height: 1;
  border-radius: 0;
  cursor: pointer;
  transition: background .14s, color .14s;
}
.counter button:hover { background: var(--card-hi); color: var(--text); }
.counter .val {
  min-width: 66px;
  text-align: center;
  font-size: 14.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.counter .val small { color: var(--dim); font-weight: 500; }

/* A rule that fills, not a pill. Two pixels, square ends — the same stroke
   vocabulary as the mark that opens the entry. */
.bar {
  height: 2px;
  border-radius: 0;
  background: var(--track);
  overflow: hidden;
  margin-top: 12px;
}
.bar > i {
  display: block;
  height: 100%;
  border-radius: 0;
  background: var(--accent);
  transition: width .35s cubic-bezier(.2, .8, .3, 1);
}
.item.done .bar > i { background: var(--good); }

/* ------------------------------ sheet ------------------------------ */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(8, 6, 5, .72);
  backdrop-filter: blur(5px);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Above the keyboard rather than behind it: iOS Safari leaves the layout
     viewport alone and draws the keyboard over it. Zero when there is none. */
  padding: 0 0 var(--keyboard);
}
.sheet[hidden] { display: none; }
.sheet-inner {
  position: relative;
  width: 100%;
  max-width: 620px;
  /* The sheet rises from the bottom edge, so the home indicator crosses its
     last line and the safe area has to come out of the height as well as the
     padding — otherwise the bottom of a long sheet is unreachable. */
  max-height: min(
    calc(88dvh - var(--safe-bottom)),
    calc(100dvh - var(--safe-bottom) - var(--keyboard) - 16px)
  );
  overflow-y: auto;
  background: var(--bg-soft);
  border: 1px solid var(--rule);
  border-bottom: 0;
  border-radius: 22px 22px 0 0;
  padding: 26px 22px calc(34px + var(--safe-bottom));
  animation: rise .28s cubic-bezier(.2, .9, .3, 1);
}
@keyframes rise { from { transform: translateY(28px); opacity: .4; } }
.sheet-close {
  position: absolute;
  top: 16px; right: 18px;
  width: 32px; height: 32px;
  border: 0;
  border-radius: 9px;
  background: var(--card);
  color: var(--muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
/* The sheet is text, so it answers to the text size like everything else —
   which is also the only way somebody changing that setting can see it work:
   the day is behind the sheet they are standing in. */
#sheetBody { font-size: calc(15px * var(--k)); }
#sheetBody .small { font-size: calc(13px * var(--k)); }
.sheet h2 { font-size: calc(21px * var(--k)); margin-bottom: 6px; }
.sheet h3 {
  font-size: calc(12.5px * var(--k));
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--dim);
  margin: 24px 0 11px;
}

.score-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line-soft);
}
.score-row .name { flex: 1; font-size: 14.5px; min-width: 0; }
/* A week you did it, on something you have since taken off the roster. The
   credit stands; the row says why it is here. */
.score-row.gone .name { color: var(--muted); }
.score-gone {
  display: block;
  font-size: 11.5px;
  font-style: normal;
  color: var(--dim);
}
.score-row .track {
  width: 96px;
  height: 6px;
  border-radius: 3px;
  background: var(--line-soft);
  overflow: hidden;
  flex-shrink: 0;
}
.score-row .track > i { display: block; height: 100%; border-radius: 3px; }
.score-row .num {
  width: 46px;
  text-align: right;
  font-size: 13.5px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.verdict {
  font-size: 15px;
  line-height: 1.6;
  color: var(--muted);
  margin: 10px 0 4px;
}
.big-pct { font-size: 40px; font-weight: 700; letter-spacing: -.03em; }

.quiet-times {
  display: flex;
  gap: 10px;
  margin: 12px 0 4px;
}
.quiet-times label { flex: 1; min-width: 0; }
.quiet-times span {
  display: block;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 6px;
}
.quiet-times input {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--edge);
  border-radius: 10px;
  outline: none;
  font-variant-numeric: tabular-nums;
}
.quiet-times input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .16);
}

.quiet-summary {
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
  margin: 2px 0 4px;
}
.quiet-summary.warn {
  color: var(--accent-soft);
  font-weight: 550;
}

/* A statement, with a rule marking its tone. Fills went with the cards; a
   left rule says the same thing without turning a sentence into a notice. */
.setting-status {
  padding: 2px 0 2px 14px;
  border-radius: 0;
  background: none;
  border: 0;
  border-left: 2px solid var(--rule);
  margin-bottom: 10px;
}
.setting-status.good { border-left-color: var(--good); }
.setting-status.good strong { color: var(--text-good); }
.setting-status.warn { border-left-color: var(--accent); }
.setting-status.warn strong { color: var(--accent); }
.setting-status strong { font-size: 14.5px; }
.setting-status .small { margin-top: 4px; }

.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
}
.toggle-row p { font-size: 14.5px; }
.switch {
  position: relative;
  width: 46px; height: 27px;
  flex-shrink: 0;
  border: 0;
  border-radius: 20px;
  background: var(--edge);
  cursor: pointer;
  transition: background .2s;
}
.switch::before {
  content: '';
  position: absolute;
  top: -9px;
  bottom: -9px;
  left: 0;
  right: 0;
}
.switch::after {
  content: '';
  position: absolute;
  top: 3px; left: 3px;
  width: 21px; height: 21px;
  border-radius: 50%;
  background: #fff;
  transition: transform .2s cubic-bezier(.2, .9, .3, 1);
}
.switch.on { background: var(--accent); }
.switch.on::after { transform: translateX(19px); }

/* ----------------------------- calendar ---------------------------- */

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* Clear of the sheet's close button, which is absolutely positioned in the
     top right and would otherwise swallow taps meant for "next month". */
  padding-right: 46px;
  margin-bottom: 18px;
}
.cal-head h2 { font-size: 19px; }
.cal-head .icon-btn { position: relative; width: 34px; height: 34px; font-size: 19px; }
.cal-head .icon-btn::after {
  content: '';
  position: absolute;
  top: -5px;
  bottom: -5px;
  left: 0;
  right: 0;
}
.cal-head .icon-btn:disabled { opacity: .3; cursor: default; }

.cal-stats {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}
.cal-stats > div {
  flex: 1;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 12px;
  padding: 11px 12px;
  min-width: 0;
}
.cal-stats strong {
  display: block;
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -.02em;
}
.cal-stats em {
  display: block;
  font-style: normal;
  font-size: 11.5px;
  color: var(--dim);
  margin-top: 1px;
}

.cal-grid-head,
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}
.cal-grid-head {
  margin-bottom: 6px;
}
.cal-grid-head span {
  text-align: center;
  font-size: 11px;
  font-weight: 650;
  color: var(--dim);
  letter-spacing: .05em;
}

.cal-cell {
  position: relative;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: 9px;
  background: var(--line-soft);
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  padding: 0;
  transition: transform .12s, border-color .15s;
}
.cal-cell.pad { background: none; cursor: default; }
/* Still tappable, just empty: a day with no data has something to say, and a
   button that does nothing is indistinguishable from a broken one. */
.cal-cell.blank { background: none; border: 1px dashed var(--line-soft); color: var(--dim); }
.cal-cell:disabled { cursor: default; }
.cal-cell:not(:disabled):hover { transform: scale(1.08); }
.cal-cell.pre:hover, .cal-cell.future:hover { transform: scale(1.04); }

.cal-cell.l0 { background: rgba(var(--bad-rgb), .28); color: var(--text-bad); }
.cal-cell.l1 { background: rgba(var(--accent-rgb), .3); color: #f3c7b4; }
.cal-cell.l2 { background: rgba(var(--warm-rgb), .32); color: #f5dcae; }
.cal-cell.l3 { background: rgba(var(--good-rgb), .32); color: #bfe6cf; }
.cal-cell.l4 { background: rgba(var(--good-rgb), .62); color: #0f1a13; font-weight: 650; }

.cal-cell.today { border-color: var(--accent); }
.cal-cell.picked { border-color: var(--text); }
.cal-dot {
  position: absolute;
  bottom: 4px;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: .6;
}

.cal-legend {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 14px;
  font-size: 11.5px;
  color: var(--dim);
}
.cal-legend .cal-cell {
  width: 13px;
  height: 13px;
  aspect-ratio: auto;
  border-radius: 4px;
  cursor: default;
}

.cal-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14.5px;
}
.cal-row:last-child { border-bottom: 0; }
.cal-mark {
  flex-shrink: 0;
  width: 18px;
  text-align: center;
  font-weight: 700;
}
.cal-row.done .cal-mark { color: var(--good); }
.cal-row.skipped .cal-mark { color: var(--accent-soft); }
.cal-row.missed { color: var(--dim); }
.cal-row.missed .cal-mark { color: var(--dim); }
.cal-row.pending { color: var(--muted); }
.cal-row.pending .cal-mark { color: var(--dim); }

.cal-today-tag {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 20px;
  background: rgba(var(--accent-rgb), .15);
  border: 1px solid rgba(var(--accent-rgb), .3);
  color: var(--accent-soft);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  vertical-align: middle;
}
.cal-label { min-width: 0; }
.cal-why { color: var(--dim); font-size: 13px; }

/* Adding to a day you tapped, from inside the calendar. Small and inline:
   this is one line about one day, not a form. */
.cal-add {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}
.cal-add input {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--edge);
  border-radius: 10px;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  outline: none;
}
.cal-add input:focus { border-color: var(--accent); }
.cal-add input::placeholder { color: var(--dim); }
.cal-add .btn { flex-shrink: 0; }

.cal-tier { margin-top: 14px; }
.cal-tier-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.cal-tier-row .btn { flex: 1; min-width: 0; padding: 8px 10px; font-size: 12.5px; }

.cal-import {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line-soft);
}
.cal-import .small { margin-top: 8px; }

/* ------------------------- calendar import -------------------------- */

.imp-paste { margin: -6px 0 16px; }
.imp-paste summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  cursor: pointer;
  font-size: 13px;
  color: var(--dim);
  margin-bottom: 4px;
}
.imp-paste textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  line-height: 1.5;
  resize: vertical;
}
.imp-paste textarea:focus { outline: none; border-color: var(--accent); }

.imp-row {
  display: flex;
  align-items: center;
  gap: 10px;
  /* The whole row is the label, so the row is the tap target — and a list of
     things to tick is tapped once per line. */
  min-height: 44px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14.5px;
  cursor: pointer;
}
.imp-row input { flex-shrink: 0; accent-color: var(--accent); }

.imp-hard {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  margin: 12px 0 4px;
  font-size: 13.5px;
  color: var(--muted);
  cursor: pointer;
}
.imp-hard input { flex-shrink: 0; accent-color: var(--accent); }

.prompt-dismiss {
  width: 28px; height: 28px;
  flex-shrink: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--dim);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  transition: color .15s, background .15s;
}
.prompt-dismiss:hover { color: var(--text); background: var(--card-hi); }

.foot {
  display: flex;
  justify-content: center;
  gap: 22px;
  margin-top: 34px;
}
/* Signing out is not something the day screen should offer as a button. */
.foot .btn {
  border: 0;
  border-radius: 0;
  background: none;
  padding: 0 4px;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--dim);
  /* Signing out reads as a link rather than a button, and the rule under it is
     the whole of that. It is set on the text: this is a .btn.small, so the box
     is 44px tall now and a bottom border would draw the line a finger's width
     below the word. */
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 4px;
}
.foot .btn:hover { color: var(--text); }

/* ------------------------------ toast ------------------------------ */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--bar-h) + 26px + var(--safe-bottom));
}
.toast {
  transform: translateX(-50%);
  z-index: 90;
  background: var(--card-hi);
  border: 1px solid var(--rule);
  border-radius: 12px;
  padding: 12px 18px;
  font-size: calc(14px * var(--k));
  box-shadow: var(--shadow);
  max-width: calc(100vw - 36px);
  animation: rise .2s ease-out;
}
.toast[hidden] { display: none; }
.toast.bad { border-color: rgba(var(--accent-rgb), .5); color: var(--text-bad); }



@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* --------------------------- roster editor -------------------------- */

.roster-list {
  border-top: 1px solid var(--line-soft);
  margin-top: 14px;
}
.roster-row {
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--line-soft);
}
.roster-open {
  flex: 1;
  min-width: 0;
  display: block;
  text-align: left;
  background: none;
  border: 0;
  padding: 14px 0;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.roster-open.static { cursor: default; }
.roster-open:hover .roster-name { color: var(--accent-soft); }
.roster-name {
  display: block;
  font-size: 15px;
  font-weight: 600;
}
.roster-meta {
  display: block;
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--muted);
}
.roster-row.off .roster-name,
.roster-row.off .roster-meta { color: var(--dim); }
.switch.small { width: 38px; height: 22px; }
.switch.small::after { width: 16px; height: 16px; }
.switch.small.on::after { transform: translateX(16px); }

.roster-actions { margin-top: 20px; }
.empty-note {
  margin-top: 18px;
  padding: 18px;
  border: 1px dashed var(--rule);
  border-radius: 14px;
  font-size: 14px;
  color: var(--muted);
  line-height: 1.6;
}
.linkish.back {
  display: inline-block;
  margin-bottom: 12px;
  font-size: 13px;
}
.linkish.block-link {
  display: block;
  width: 100%;
  text-align: center;
  margin-top: 16px;
}
/* It is already the full width of what it sits in, so the reach below it has
   nowhere to go sideways: six pixels each way made the settings sheet scroll
   horizontally, which reads as the whole screen not fitting the phone. Height
   is the axis a thumb misses on anyway. */
.linkish.block-link::after { left: 0; right: 0; }

/* Choosing in words rather than numbers. */
.choice-group { display: grid; gap: 8px; }
.choice {
  display: block;
  width: 100%;
  text-align: left;
  padding: 13px 15px;
  border: 1px solid var(--edge);
  border-radius: 13px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.choice:hover { border-color: var(--dim); }
.choice strong { display: block; font-size: 14.5px; font-weight: 600; }
.choice span {
  display: block;
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.45;
}
.choice.picked {
  border-color: var(--accent);
  background: var(--card-hi);
}
.choice.picked strong { color: var(--accent-soft); }

/* ---------------------------- setup screen -------------------------- */

.templates { display: grid; gap: 9px; }
.template {
  display: block;
  width: 100%;
  text-align: left;
  padding: 14px 16px;
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.template:hover { border-color: var(--accent); background: var(--card-hi); }
.template:disabled { opacity: .5; cursor: default; }
.template strong { display: block; font-size: 15px; font-weight: 600; }
.template span {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.5;
}
.template em {
  display: block;
  margin-top: 7px;
  font-size: 12px;
  font-style: normal;
  color: var(--dim);
}

.describe-box { position: relative; }
.describe-box textarea {
  width: 100%;
  padding: 13px 50px 13px 14px;
  border: 1px solid var(--edge);
  border-radius: 13px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 14.5px;
  line-height: 1.55;
  resize: vertical;
}
.describe-box textarea:focus {
  outline: none;
  border-color: var(--accent);
}
.mic {
  position: absolute;
  top: 9px; right: 9px;
  width: 34px; height: 34px;
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--bg-soft);
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.mic:hover { color: var(--text); border-color: var(--dim); }
.mic.listening {
  border-color: var(--accent);
  color: var(--accent-soft);
  animation: pulse 1.4s ease-in-out infinite;
}
@keyframes pulse { 50% { box-shadow: 0 0 0 6px rgba(var(--accent-rgb), .13); } }
.mic-hint { margin-top: 7px; }
.mic-hint[hidden] { display: none; }

.disclosure {
  margin-top: 12px;
  padding: 11px 13px;
  border: 1px solid var(--line-soft);
  border-radius: 11px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--muted);
}

.or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 24px 0 4px;
  color: var(--dim);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .08em;
}
.or::before, .or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line-soft);
}

/* ------------------------- the category menu ------------------------ */

.picked-count {
  display: inline-block;
  min-width: 20px;
  padding: 1px 6px;
  margin-left: 6px;
  border-radius: 10px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 11.5px;
  font-weight: 600;
  vertical-align: middle;
}

.tick-list { display: grid; gap: 7px; margin-top: 14px; }
.tick {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  text-align: left;
  padding: 13px 15px;
  border: 1px solid var(--edge);
  border-radius: 13px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.tick:hover:not(:disabled) { border-color: var(--dim); }
.tick-box {
  flex-shrink: 0;
  width: 21px; height: 21px;
  margin-top: 1px;
  border: 2px solid var(--edge);
  border-radius: 6px;
  transition: background .15s, border-color .15s;
}
.tick.on { border-color: var(--accent); background: var(--card-hi); }
.tick.on .tick-box {
  background: var(--accent);
  border-color: var(--accent);
  position: relative;
}
.tick.on .tick-box::after {
  content: '';
  position: absolute;
  left: 6px; top: 2px;
  width: 5px; height: 10px;
  border: solid var(--on-accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.tick-text { min-width: 0; }
.tick-text strong { display: block; font-size: 14.5px; font-weight: 600; }
.tick-text span {
  display: block;
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--muted);
}
.tick.already { opacity: .45; cursor: default; }

/* Sticky, because ticking six things and then hunting for the button is a
   small cruelty. */
.pick-bar {
  position: sticky;
  bottom: 0;
  /* The negative margin pulls this out to the sheet's own padding edge, so it
     has to grow by exactly what the sheet's bottom padding grew by, or the bar
     stops short of the edge and the gradient shows a seam. */
  margin: 20px -22px calc(-34px - var(--safe-bottom));
  padding: 14px 22px calc(22px + var(--safe-bottom));
  background: linear-gradient(to top, var(--bg-soft) 70%, transparent);
}
.pick-bar .btn { margin-top: 0; }

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

.shop {
  margin-top: 30px;
  padding: 16px 16px 14px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--bg-soft);
}
.shop-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.shop-head h2 {
  font-size: calc(12.5px * var(--k));
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--dim);
  font-weight: 600;
}
.shop-count { font-size: calc(12.5px * var(--k)); color: var(--muted); }
.shop-add { display: flex; gap: 8px; }
.shop-add input {
  flex: 1;
  min-width: 0;
  padding: 10px 13px;
  border: 1px solid var(--edge);
  border-radius: 11px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 14.5px;
}
.shop-add input:focus { outline: none; border-color: var(--accent); }
.shop-add .btn { margin-top: 0; flex-shrink: 0; }

.shop-items:not(:empty) { margin-top: 6px; }
.shop-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line-soft);
}
.shop-item:last-child { border-bottom: 0; }
.shop-tick {
  flex-shrink: 0;
  width: 20px; height: 20px;
  border: 2px solid var(--edge);
  border-radius: 6px;
  background: none;
  cursor: pointer;
  position: relative;
}
.shop-item.got .shop-tick { background: var(--good); border-color: var(--good); }
.shop-item.got .shop-tick::after {
  content: '';
  position: absolute;
  left: 5px; top: 1px;
  width: 5px; height: 10px;
  border: solid var(--bg);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.shop-text { flex: 1; min-width: 0; font-size: calc(14.5px * var(--k)); }
.shop-item.got .shop-text {
  color: var(--dim);
  text-decoration: line-through;
}
.shop-remove {
  flex-shrink: 0;
  border: 0;
  background: none;
  color: var(--dim);
  font-size: 17px;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
}
.shop-remove:hover { color: var(--accent); }
#shopClear { margin-top: 10px; font-size: 13px; }

/* A mic on the shopping list, where it needs no key and no server. */
.shop-field { position: relative; flex: 1; min-width: 0; }
.shop-field input { width: 100%; padding-right: 44px; }
.mic.small {
  /* The field is 44px tall and the glyph is 30; the reach helper above makes
     up the difference without moving the drawing. */
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 30px; height: 30px;
  font-size: 14px;
}
.mic.small.listening { animation: pulse 1.4s ease-in-out infinite; }


/* The reach helper, applied where the drawing has to stay small.
   Only the two that sit in normal flow are made relative — the mic and the
   sheet close are already absolutely positioned, and relative would drop each
   of them back into the flow it was lifted out of. */
.prompt-dismiss,
.item-more,
.open-caret,
.foot .btn,
.linkish { position: relative; }
.mic.small::after,
.prompt-dismiss::after,
.sheet-close::after,
.item-more::after,
.open-caret::after,
.foot .btn::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(44px, 100%);
  height: max(44px, 100%);
  transform: translate(-50%, -50%);
}

/* A plain link in a paragraph gets the same reach as a .linkish button, for
   the same reason: the privacy link on the sign-in card is a 16px-tall target
   otherwise, and it is the one link on that screen somebody is reaching for
   on purpose. Scoped to the app's own copy so the document pages, which are
   set at reading size already, are left alone. */
.app a[href],
#sheetBody a[href],
.card a[href],
.lists-screen a[href],
.people-screen a[href] { position: relative; }
.app a[href]::after,
#sheetBody a[href]::after,
.card a[href]::after,
.lists-screen a[href]::after,
.people-screen a[href]::after {
  content: '';
  position: absolute;
  top: -14px;
  bottom: -14px;
  left: 0;
  right: 0;
}

/* A link in a sentence cannot be 44px tall without pushing the sentence apart,
   so it reaches sideways and down rather than centring a square on itself —
   the text stays exactly where it was set. */
.linkish::after {
  content: '';
  position: absolute;
  top: -14px;
  bottom: -14px;
  left: -6px;
  right: -6px;
}

/* The tabs on the sign-in card were 39px: close enough to look right and not
   close enough to hit. */
.tab { min-height: 44px; }

/* --------------------------- the start panel ------------------------ */

/* What a new account sees instead of somebody else's routine. */
.start {
  margin: 4px 0 8px;
  padding: 26px 22px 22px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
}
.start h2 {
  font-size: 20px;
  line-height: 1.3;
}
.start-line {
  margin-top: 8px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--muted);
}
.start-actions {
  display: grid;
  gap: 9px;
  margin-top: 20px;
}
.start-actions .btn { margin-top: 0; }
.start .linkish.block-link { margin-top: 16px; font-size: 13px; }


/* ------------------------- reach without redrawing ------------------------- */

/*
 * Some controls cannot get bigger without moving what they sit inside: the
 * microphone lives inside the text field, the × inside a one-line prompt, the
 * close button in the corner of a sheet. A thumb still needs 44px of them.
 *
 * So the drawing stays the size it was and an invisible square is stretched
 * past its edges. Nothing moves, nothing is repainted, and what a finger lands
 * on is the size the platform asks for.
 */

/* ------------------------- talk, don't tick ------------------------- */

/* The microphone is the front door of setup, not a button in a corner. */
.talk {
  text-align: center;
  padding: 22px 0 6px;
}
.talk-btn {
  width: 84px; height: 84px;
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: var(--card);
  color: var(--accent-soft);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
  transition: border-color .15s, background .15s, transform .1s;
}
.talk-btn:hover { border-color: var(--accent); background: var(--card-hi); }
.talk-btn:active { transform: scale(.96); }
.talk-btn.listening {
  border-color: var(--accent);
  background: var(--card-hi);
  animation: listening 1.6s ease-in-out infinite;
}
@keyframes listening {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), .34); }
  70% { box-shadow: 0 0 0 18px rgba(var(--accent-rgb), 0); }
}
.talk-hint {
  margin-top: 12px;
  font-size: 14.5px;
  color: var(--text);
}
.talk-eg {
  margin: 8px auto 0;
  max-width: 330px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--dim);
}

.heard-back {
  margin-top: 8px;
  padding: 13px 15px;
  border-left: 2px solid var(--rule);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--muted);
}

/* Examples on the start panel — one thing each, never a routine. */
.start-eg-label {
  margin-top: 20px;
  font-size: 12.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--dim);
}
.start-egs {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 10px;
}
.eg {
  padding: 8px 13px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--muted);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.eg:hover { border-color: var(--accent); color: var(--text); }
.eg::before { content: '+ '; color: var(--accent-soft); }

/* A day with something already booked on it — the reason to look ahead. */
.cal-cell.booked {
  background: none;
  border: 1px solid var(--accent);
  color: var(--accent-soft);
}
.cal-cell.booked::after {
  content: '';
  position: absolute;
  bottom: 4px; left: 50%;
  transform: translateX(-50%);
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--accent);
}
.cal-row.booked .cal-mark { color: var(--accent-soft); }

/* ---------------------------- the add sheet ---------------------------- */

/*
 * One line to write on, what was made of it, one question, one button. The
 * question is the same one a reminder from a friend is asked, so the three
 * answers are shared: a row of choices at the size of the answer, not the size
 * of the reasoning.
 */
.add-title {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 600;
  padding-right: 40px;
}
.add-form { margin-top: 12px; }
.add-field { position: relative; }
.add-field input {
  width: 100%;
  min-height: 48px;
  padding: 10px 46px 10px 14px;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: var(--card);
  color: var(--text);
  font-family: var(--serif);
  /* 16px is the floor below which iOS Safari zooms the page on focus. */
  font-size: max(16px, calc(17px * var(--k)));
}
.add-field input::placeholder { color: var(--dim); font-family: var(--sans); font-size: 15px; }
.add-field input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .16);
}
/* Always a line tall, so the sheet does not jump as words are understood. */
.add-read {
  min-height: 1.4em;
  margin-top: 8px;
  font-size: 13.5px;
  color: var(--accent-soft);
}
.add-read.bad { color: var(--text-error); }
.add-q {
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--muted);
}
.add-form .btn.block { margin-top: 14px; min-height: 48px; }
.add-form .btn:disabled { opacity: .5; cursor: default; }
.add-more { display: block; margin: 14px auto 0; }
/* With the keyboard up there is a third of a small phone left. What is left is
   what the sheet is for; the way to the menu comes back with the keyboard down. */
.kb-up .add-more { display: none; }
.kb-up .sheet-inner { padding-top: 18px; padding-bottom: 14px; }
.kb-up .add-form { margin-top: 8px; }
.kb-up .add-form .btn.block { margin-top: 10px; }
.tier-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin-top: 6px;
}
.tier-btn {
  min-height: 44px;
  padding: 8px 6px;
  border: 1px solid var(--edge);
  border-radius: 11px;
  background: var(--bg-soft);
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.tier-btn:hover { border-color: var(--dim); }
.tier-btn.picked {
  border-color: var(--accent);
  background: var(--card-hi);
  color: var(--accent-soft);
}

/* --------------------- changing or removing an item ------------------ */

.item-more {
  flex-shrink: 0;
  margin-left: 6px;
  width: 28px; height: 24px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--dim);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.item-more:hover { color: var(--text); background: var(--card-hi); }

.toast-action {
  margin-left: 14px;
  border: 0;
  background: none;
  color: var(--accent-soft);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.toast-action:hover { color: var(--accent); }

/* ---------------------- one person who knows ----------------------- */

/* The standing line on the day screen. Quiet, but never dismissable: if
   somebody is being told how your day went, that should be a thing you can
   see rather than a thing you have to remember. */
/* A question, not an alarm.
   Nothing is wrong and nothing is leaking — somebody simply agreed to less than
   the app now shares, and the app is being straight about it. Red would say
   there has been a breach; grey would say it does not matter. So it borrows the
   accent for its edge and nothing else. */
.change-notice {
  margin: 0 0 16px;
  padding: 14px 16px;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 12px;
  background: var(--bg-soft);
}
.change-notice.quiet {
  border-left-color: var(--rule);
  color: var(--muted);
}
.notice-head {
  margin: 0 0 6px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text);
}
.notice-body {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}
/* What they will be told, in the words they will be told it in. */
.notice-list,
.notice-changes {
  margin: 10px 0 0;
  padding-left: 18px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}
.notice-list li,
.notice-changes li { margin-bottom: 5px; }

.notice-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 12px;
}

/* Somebody suggested something for your list.
   Shaped like the change notice on purpose — it is the same kind of thing: a
   prompt that says its piece once, can be answered in one tap, and never gets
   louder. An answered one is quieter still, because it is news rather than a
   thing to do. */
.offers { margin: 0 0 16px; }
.offer {
  padding: 14px 16px;
  margin-bottom: 10px;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: 12px;
  background: var(--bg-soft);
}
.offer.is-answer {
  position: relative;
  border-left-color: var(--rule);
  padding-right: 38px;
}
.offer-head {
  margin: 0 0 6px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text);
}
.offer.is-answer .offer-head { font-weight: 500; color: var(--muted); }
.offer-what {
  margin: 0 0 4px;
  font-size: 15px;
  color: var(--text);
}
.offer-note,
.offer-fine { margin: 0 0 4px; line-height: 1.5; }
.offer-fine { margin-bottom: 10px; }
/* Their words, kept as theirs. */
.offer-said {
  margin: 6px 0 0;
  font-size: 13px;
  font-style: italic;
  color: var(--muted);
}
.offer-reason {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--edge);
  border-radius: 9px;
  background: var(--bg);
  color: var(--text);
  font-size: 13.5px;
}
.offer-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.offer-seen {
  position: absolute;
  top: 8px;
  right: 10px;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 6px;
}
.watch-suggest { display: block; margin-top: 10px; }

/* What they said back. Worth more than the tick, so it gets to look like a
   thing a person wrote rather than a status field. */
.partner-reply-quote {
  margin-top: 10px;
  padding-left: 11px;
  border-left: 2px solid var(--accent);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
}

/* ------------------------- the partner's page ----------------------- */

.partner-title {
  font-size: 20px;
  line-height: 1.3;
  margin-bottom: 12px;
}

.partner-facts {
  margin-top: 16px;
  padding: 14px 16px;
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: var(--bg-soft);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--muted);
}
.partner-facts p { color: var(--text); font-size: 13px; }
.partner-facts p + ul { margin-top: 6px; }
.partner-facts ul { margin: 0 0 14px; padding-left: 18px; }
.partner-facts ul:last-child { margin-bottom: 0; }
.partner-facts li { margin-bottom: 4px; }

.partner-reply { display: block; margin-top: 18px; }
.partner-reply input {
  width: 100%;
  margin-top: 6px;
  padding: 12px 14px;
  border: 1px solid var(--edge);
  border-radius: 11px;
  background: var(--card);
  color: var(--text);
  outline: none;
}
.partner-reply input:focus { border-color: var(--accent); }

/* ------------------------- looking out for them --------------------- */
/*
 * Collapsed to one line by default. This is your day screen first and theirs
 * second, so somebody else's report should never push your own items down the
 * page before you have asked to see it.
 */

.watching { margin-bottom: 26px; }
.watching-list { display: grid; gap: 8px; }

.watch-card {
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: var(--card);
  overflow: hidden;
}
.watch-card.is-open { border-color: var(--rule); border-radius: var(--radius); }

.watch-line {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 13px 15px;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.watch-line:hover { background: var(--card-hi); }
.watch-who { flex: 1; min-width: 0; font-size: 15px; }
.watch-who strong { font-weight: 600; }

.watch-score {
  flex: none;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--line-soft);
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
}
.watch-score.full { background: rgba(var(--good-rgb), .16); color: var(--good); }
.watch-score.part { background: rgba(224, 138, 74, .16); color: var(--accent-soft); }
/* A day still going gets no verdict colour at all.
   Green for "all done" and orange for "some done" are judgements about a
   finished day. Putting either on a day with six hours left in it turns a
   tally into a scoreline, which is exactly the failure-alert reading this
   whole feature is built to avoid. Neutral, and the word "so far" does the
   rest. */
.watch-score.live {
  background: var(--line-soft);
  color: var(--text);
  font-weight: 500;
}

/* Today, above the report. Two different claims, so two visible blocks: one is
   still moving, the other is settled and is the one you can answer. */
.watch-live {
  margin-top: 10px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line-soft);
}
.watch-since {
  margin: 14px 0 0;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--dim);
}

/* Why there is no "I saw it" on an unfinished day. Cut back to the half that
   says something: "still going" only repeated what the card already shows. */
.watch-live-note {
  margin: 12px 0 0;
  padding-left: 11px;
  border-left: 2px solid var(--rule);
  line-height: 1.5;
}

.watch-when { flex: none; font-size: 12px; }

/* One dot, meaning "they have not heard from you about this yet". */
.watch-unread {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}
.watch-caret { flex: none; width: 14px; text-align: center; color: var(--dim); font-size: 15px; }

.watch-card.is-open .watch-summary,
.watch-card.is-open .watch-lines,
.watch-card.is-open .watch-strip,
.watch-card.is-open .watch-act,
.watch-card.is-open .watch-done,
.watch-card.is-open .watch-back { margin-left: 15px; margin-right: 15px; }
.watch-card.is-open .watch-done { padding-bottom: 15px; }
.watch-card.is-open .watch-act { padding-bottom: 15px; }

.watch-summary { font-size: 14.5px; line-height: 1.45; color: var(--text); }

.watch-lines { list-style: none; margin: 10px 0 0; padding: 0; }
.watch-lines li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14.5px;
}
.watch-lines li:last-child { border-bottom: 0; }
/* Under the item, not beside it — a reason can be a sentence, and squeezing it
   onto the label line would truncate the one part of this that is in their own
   words. Dimmer than the label: it is context for the miss, not a headline. */
.watch-reason {
  display: block;
  margin-top: 4px;
  padding-left: 12px;
  border-left: 1px solid var(--rule);
  font-family: var(--serif);
  font-size: 14.5px;
  line-height: 1.45;
  color: var(--muted);
  font-style: italic;
}
.watch-mark { flex: none; font-size: 13px; font-weight: 600; color: var(--dim); }
.watch-lines li.hit .watch-mark { color: var(--good); }

/* A week of shape, not a week of detail — enough to notice a bad run without
   becoming a record of which day they missed what. */
.watch-strip { display: flex; gap: 5px; margin-top: 12px; }
.watch-pip {
  width: 100%;
  height: 5px;
  border-radius: 3px;
  background: var(--track);
}
.watch-pip.part { background: var(--r2); }
.watch-pip.full { background: var(--good); }

.watch-act { display: flex; gap: 8px; margin-top: 14px; }
.watch-act .btn { margin-top: 0; flex: none; }
.watch-reply,
.watch-note {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border: 1px solid var(--edge);
  border-radius: 10px;
  background: var(--bg-soft);
  color: var(--text);
  font-size: 14px;
  outline: none;
}
.watch-reply:focus,
.watch-note:focus { border-color: var(--accent); }
.watch-done { margin-top: 12px; }

/* The two halves of the sheet, so neither reads as a sub-point of the other. */
.sheet-inner h4 {
  margin: 18px 0 8px;
  font-size: 12px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.sheet-list { list-style: none; margin: 0; padding: 0; }
.sheet-list li {
  padding: 10px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14.5px;
}
.sheet-list li:last-child { border-bottom: 0; }
.sheet-list .small { display: block; margin-top: 2px; }

@media (max-width: 420px) {
  .watch-act { flex-wrap: wrap; }
  .watch-act .btn { width: 100%; }
  .watch-when { display: none; }
}

/* Reciprocity in one tap. Quiet, because it is an offer and not a prompt. */
.watch-back {
  display: block;
  margin-top: 14px;
  font-size: 13px;
  text-align: left;
}

/* A line back is the only thing that travels from the watcher to the watched,
   so when there is one it takes the box in Settings over anything else the
   arrangement could be saying. */
.setting-status.said {
  border-color: rgba(var(--accent-rgb), .45);
  background: rgba(var(--accent-rgb), .07);
}
.setting-status.said strong { color: var(--text); }

/* ---------------------- a day that shrinks as you work --------------- */
/*
 * Measured at 2,596px on a 390-wide phone — more than three screens, with
 * tier 3 alone taking 919px against tier 1's 504px. The layout inverted the
 * app's own priorities. The rule now is that the page is proportional to what
 * is still outstanding, not to what exists: only things needing no further tap
 * get smaller, so nothing costs a click it did not cost before.
 */

/* A finished thing: one line, still with its ⋯ for undo. */
/* A settled entry keeps its line and loses everything else. No box here
   either — a hairline under it is enough to keep a run of finished things from
   reading as one paragraph. */
.item.settled {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 8px 0;
  margin-top: 0;
  border-bottom: 1px solid var(--line-soft);
}
/* The list and the refill watch, which are not part of the day's ladder. */
.watch-lines li.pending .settled-label,
.watch-lines li.pending span { color: var(--text); }
.watch-firstreport { margin-top: 12px; }

/* The card before the first report: a name, and what they are keeping on top
   of. Tighter than an opened report, because there is no report in it. */
.watch-card.is-pending .watch-line { padding-bottom: 2px; }
.watch-card.is-pending .watch-lines { margin-top: 2px; }
.watch-card.is-pending .watch-lines li { padding: 6px 0; }
.watch-card.is-pending .watch-firstreport { padding-bottom: 14px; margin-top: 8px; }

/* Removing, from the roster list itself. Deliberately quieter than the pause
   switch beside it: pausing is the common act and removing is the rare one,
   so the rare one does not get to look like the obvious tap. */
.roster-drop {
  flex: none;
  width: 30px;
  height: 30px;
  margin-left: 4px;
  border: 1px solid transparent;
  border-radius: 9px;
  background: none;
  color: var(--dim);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}
.roster-drop:hover {
  border-color: rgba(var(--bad-rgb), .45);
  background: rgba(var(--bad-rgb), .12);
  color: var(--text-bad);
}

/* Folding a tier away. Open by default — the tiers are the app — but somebody
   who never looks at tier 3 should be able to put it away and have it stay. */
.tier-head[data-tier] {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  min-height: 44px;
  padding: 0 0 2px;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
}
.tier-title { flex: none; }
.tier-count {
  flex: none;
  font-family: var(--mono);
  font-size: calc(11px * var(--k));
  letter-spacing: .1em;
  color: inherit;
  opacity: .8;
}
.tier-count.done { color: var(--good); }

/* --------------------------- your people ----------------------------- */
/*
 * Two rows under the greeting, where one icon used to stand for both of them.
 *
 * They sit on the day screen, which everything else about other people is kept
 * off. A row earns it by being chrome rather than content: one line tall
 * whether nobody is on it or six people are, and it never grows with how badly
 * anyone's day went.
 */
.people-nav { display: grid; gap: 6px; margin-bottom: 10px; }

.nav-row {
  display: flex;
  align-items: baseline;
  gap: 9px;
  width: 100%;
  padding: 10px 0;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  border-radius: 0;
  background: none;
  color: var(--text);
  font-family: var(--sans);
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}
.nav-row:hover .nav-label { color: var(--accent); }
.nav-glyph { flex: none; width: 16px; text-align: center; color: var(--muted); }
.nav-label { font-weight: 600; min-width: 0; }
.nav-chev { margin-left: auto; flex: none; color: var(--dim); font-size: 15px; }

/*
 * A dot, on the way in. Deliberately not a count: what is behind the row is a
 * handful of things at most, and a number would suggest that four unread days
 * are more pressing than one.
 *
 * It follows the label rather than sitting at the end, so it reads as part of
 * the word "People" rather than as something done to the chevron.
 */
/* Tinted like every other surface in the app that came from another person, so
   the row and the sheet it opens read as one thing. */
/* From somebody else. With no fills left on the screen, the accent on the
   glyph and the label is what marks it as not yours. */
.nav-row.from-them .nav-glyph,
.nav-row.from-them .nav-label { color: var(--accent); }

/* ------------------------- looking out for --------------------------- */

/* The same measure and the same gutters as .app. Two widths would have every
   watch card change size on the way between the two screens. */
.people-screen {
  max-width: 640px;
  margin: 0 auto;
  padding:
    calc(14px + var(--safe-top))
    calc(18px + var(--safe-right))
    calc(var(--bar-h) + 40px + var(--safe-bottom))
    calc(18px + var(--safe-left));
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.people-title { font-size: calc(26px * var(--k)); }
.people-sub { margin: -4px 0 4px; font-size: calc(13px * var(--k)); color: var(--muted); }
.people-empty { line-height: 1.55; }

/* The other direction, at the foot of the people screen. Ruled off rather than
   boxed: it is a different subject, not a different kind of thing. */
.people-other {
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}
.people-other-head {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 650;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}

/* ------------------------------- rows ------------------------------- */
/*
 * A resting row shows what happened or what is coming, and nothing that can be
 * pressed by accident. Opening it is what reveals the answers.
 *
 * The one exception is a counter: adding a glass of water is not confirming a
 * thing, and making somebody open a row to do it would be worse than the
 * inconsistency. And there is deliberately no tick here — Done never appears
 * without "Couldn't do it" beside it, because a lone tick makes the easy answer
 * one tap and the honest one two.
 */
.row {
  display: flex;
  align-items: center;
  gap: calc(14px * var(--k));
  width: 100%;
  /* The rhythm moves with the type: this is what lets Small fit two more rows
     on a short phone instead of just printing the same rows smaller. */
  padding: calc(13px * var(--k)) 2px;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: calc(16px * var(--k));
  text-align: left;
  cursor: pointer;
}
/* The mark that says this is a thing to answer. It does not answer it —
   tapping the row opens it, and Done never appears without "Couldn't do it"
   beside it, which a lone tick would quietly undo. */
.row-box {
  flex: none;
  width: calc(22px * var(--k));
  height: calc(22px * var(--k));
  border: 1.5px solid var(--edge);
  border-radius: 50%;
}
/* The level, in the shape of the ring rather than in a heading: firm for what
   will not be let go, plain for what can be negotiated, dashed for what is only
   said once. Shape, so it survives being looked at in grey. */
.row.t1 .row-box { border: 2px solid var(--accent); }
.row.t2 .row-box { border: 1.5px solid var(--muted); }
.row.t3 .row-box { border: 1.5px dashed var(--dim); }
.row.settled .row-box {
  border-style: solid;
  border-color: var(--good);
  background: var(--good);
}
.row:last-child { border-bottom: 0; }
.row:hover { background: var(--card-hi); border-radius: 8px; }
.row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.row .counter { flex: none; gap: 4px; }
/*
 * The one control on a resting row, and the one pressed most often: eight
 * glasses of water is eight taps on a 24px square sitting inside a row that is
 * itself a button, so a miss does not do nothing — it opens the row.
 *
 * It grows to 38 and reaches 44 vertically only. Reaching sideways as well
 * would make the two hit areas overlap each other, and a + that quietly
 * swallows the right-hand edge of the - is worse than either being small.
 */
.row .counter button {
  position: relative;
  width: 38px;
  height: 38px;
  font-size: 17px;
}
.row .counter button::after {
  content: '';
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: 0;
  right: 0;
}
.row .counter .val { font-size: 12px; color: var(--muted); }
/* The right-hand side of a row: when it is due, and under that how late it is. */
.row-when {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.3;
  font-family: var(--sans);
}
.row-when .row-t {
  font-size: calc(13px * var(--k));
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.row-t:empty { display: none; }
.row-sub {
  display: block;
  font-family: var(--sans);
  font-size: calc(12.5px * var(--k));
  font-weight: 400;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* One line of the item's own voice, and only on a row that is late enough for
   the app to have something to say. The rest of it is one tap away. */
.row-voice {
  display: block;
  font-family: var(--serif);
  font-size: calc(13.5px * var(--k));
  font-weight: 400;
  line-height: 1.35;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
}
.row-n {
  flex: 1;
  min-width: 0;
  font-family: var(--serif);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.row.settled.skipped .row-n { white-space: normal; }
/* Weight, not height. The heading carries the rest of the difference between a
   tier that will not let go and one that mentions something once. */
.row.t1 .row-n { font-weight: 600; }
.row-s {
  flex: none;
  font-family: var(--sans);
  font-size: calc(13px * var(--k));
  color: var(--muted);
}
.row-s.due,
.row-s.late { color: var(--accent-soft); font-weight: 650; font-size: calc(12px * var(--k)); }
.row-s.done { color: var(--good); }
.row.settled .row-n { color: var(--muted); text-decoration: line-through; }
.row.settled.skipped .row-n { text-decoration: none; }
/* The typed reason stays on the resting row. It is the whole point of making
   the honest answer cost something, and hiding it would quietly undo that. */
.row-why {
  display: block;
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  color: var(--dim);
  margin-top: 1px;
}
.row-chip {
  flex: none;
  font-family: var(--sans);
  font-size: 9px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .4);
  border-radius: 99px;
  padding: 1px 6px;
}

/* --------------------------- the open row --------------------------- */

.open-row {
  background: var(--card-hi);
  border-bottom: 1px solid var(--line-soft);
  padding: 11px 12px 13px;
}
.open-row:last-child { border-bottom: 0; }
.open-head { display: flex; align-items: baseline; gap: 10px; }
.open-head .row-n { font-weight: 600; font-size: calc(13.5px * var(--k)); }
.open-caret { margin-left: auto; flex: none; color: var(--dim); font-size: 15px; font-family: var(--sans); }
/* Indented to the row's own text column, so the block reads as that row rather
   than as a new object that has appeared underneath it. */
.open-body { padding-left: 52px; }
.open-body .item-line { font-family: var(--serif); font-size: calc(15px * var(--k)); line-height: 1.42; margin-top: 6px; }
.open-body .badges { margin-top: 6px; }
.open-body .item-actions { margin-top: 10px; }
.open-body .item-more {
  margin-left: 6px;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--dim);
  border: 0;
  background: none;
  cursor: pointer;
}
.open-body .item-actions,
.open-body .item-more { display: inline-flex; vertical-align: middle; }

/* The menu is a strip under the open row, not a floating layer. Two taps to
   reach Remove is the right price for it. */
.open-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  padding: 0 12px 12px 64px;
  background: var(--card-hi);
  border-bottom: 1px solid var(--line-soft);
}

/* ------------------------- people who know -------------------------- */
/*
 * Up to three arrangements in one sheet. A rule between them rather than a box
 * around each: the day screen learned that a card both decorates and bounds,
 * and only the second job was worth keeping.
 */
.person-rule {
  height: 1px;
  background: var(--line);
  margin: 26px 0 20px;
}

/* Three marks, filled as they are used. A count would be a number to read;
   three marks is a thing to glance at, and it says there is a limit before
   anybody goes looking for one. */
.slots { display: flex; gap: 5px; margin-bottom: 18px; }
.slot { width: 34px; height: 3px; background: var(--track); }
.slot.on { background: var(--muted); }

.hide-list {
  display: flex;
  flex-direction: column;
  margin: 10px 0 4px;
}
.hide-row {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14.5px;
  cursor: pointer;
}
.hide-row:last-child { border-bottom: 0; }
.hide-row input { width: 17px; height: 17px; accent-color: var(--good); flex: none; }
/* Unticked is kept back, so the name of a thing they cannot see reads as
   withdrawn rather than merely unselected. */
.hide-row input:not(:checked) + span { color: var(--dim); text-decoration: line-through; }

/* --------------------------- colour schemes ------------------------- */
/*
 * Two settings, not one list.
 *
 * The old list held three hues and one brightness — Ember, Slate, Plum and
 * Paper — which is why "light and dark both" had nowhere to go in it: choosing
 * a bright room cost you the choice of hue. A hue is now a hue, and light or
 * dark is a separate attribute, so every combination exists.
 *
 * Ember light is :root and needs no block. A stored scheme that has been
 * renamed or deleted therefore falls back to the app's default ground rather
 * than to half a stylesheet.
 *
 * The dark halves live in their own section below.
 */

:root[data-theme="slate"] {
  --bg: #f0f1ed;
  --bg-soft: #e3e6df;
  --card: #f8f9f5;
  --card-hi: #eceee7;
  --line: #ccd1c6;
  --line-soft: #dde0d7;
  --text: #22261f;
  --muted: #5d6458;
  --dim: #697063;

  --accent: #3f6b57;
  --accent-soft: #2f5443;
  --accent-rgb: 63, 107, 87;
  --accent-hi: #2f5443;
  --on-accent: #f8f9f5;
  --btn-hi: #e6e9e0;

  --good: #2f6b45;
  --good-rgb: 47, 107, 69;
  --text-good: #255739;
  --warm-rgb: 138, 138, 44;

  --r1: #8a8a2c;
  --r2: #94702c;
  --r3: #96502a;
  --r4: #8a3520;
  --r5: #72271a;
}

:root[data-theme="plum"] {
  --bg: #f5edec;
  --bg-soft: #ebdedd;
  --card: #fbf6f5;
  --card-hi: #f2e8e7;
  --line: #d9c7c6;
  --line-soft: #e6d8d7;
  --text: #2a2321;
  --muted: #6b5c5a;
  --dim: #7a6967;

  --accent: #9c4050;
  --accent-soft: #7e2f40;
  --accent-rgb: 156, 64, 80;
  --accent-hi: #882c4a;
  --on-accent: #fbf6f5;
  --btn-hi: #f0e4e3;

  --good: #2f6b52;
  --good-rgb: 47, 107, 82;
  --text-good: #255742;
  --warm-rgb: 160, 117, 64;
  --bad-rgb: 136, 44, 74;
  --text-bad: #7e2f40;
  --text-hot: #6e1f3c;
  --text-error: #882c4a;

  --r1: #a07540;
  --r2: #a35a45;
  --r3: #9c4050;
  --r4: #882c4a;
  --r5: #6e1f3c;
}

/* ------------------------------ the dark half ----------------------- */
/*
 * A brightness, on top of a hue. Written as a second attribute rather than
 * three more schemes, so that every hue has both and neither setting can eat
 * the other — which is exactly what the old one-list version did.
 *
 * Every dark reuses the ladder ramp the app shipped with. It is the one part
 * of the old palette worth keeping verbatim: already proven legible on a dark
 * ground, and the thing a person learns to read at a glance.
 */

/*
 * Four more hues, from the redesign handoff's colour studies.
 *
 * Each one arrived as a single scheme — three of them dark, one light — and
 * this app has always been a hue crossed with a brightness, so the other half
 * of each was derived rather than invented: the ground and the text swap, the
 * accent moves far enough to stay legible on the ground it lands on, and every
 * pair below clears 4.5:1. An accent picked for a dark room is usually much too
 * bright for a white one — lime on white is the extreme case, and it is why the
 * light Graphite is a deep olive rather than the same green turned down.
 *
 * The ladder stays warm in all of them, for the reason the top of this file
 * gives: recolouring urgency to match a chosen accent trades a meaning for a
 * mood.
 */

:root[data-theme="ink"] {
  --bg: #eef2f8;
  --bg-soft: #e2e8f2;
  --card: #f8fafd;
  --card-hi: #eaeff7;
  --line: #c9d3e2;
  --line-soft: #dde4ee;
  --text: #101722;
  --muted: #4f5b6d;
  --dim: #5c687a;

  --accent: #2a63ba;
  --accent-soft: #1f4c92;
  --accent-rgb: 42, 99, 186;
  --accent-hi: #1f4c92;
  --on-accent: #f8fafd;
  --btn-hi: #e3eaf5;

  --good: #1f6b4a;
  --good-rgb: 31, 107, 74;
  --text-good: #195939;
  --warm-rgb: 176, 124, 44;

  --r1: #a8792c;
  --r2: #b0632c;
  --r3: #a8462a;
  --r4: #94301f;
  --r5: #7a2318;
}

:root[data-theme="moss"] {
  --bg: #eef2ea;
  --bg-soft: #e1e8dc;
  --card: #f7faf4;
  --card-hi: #eaf0e4;
  --line: #cfdac8;
  --line-soft: #dde5d7;
  --text: #16211a;
  --muted: #4f5d4c;
  --dim: #5b6a57;

  --accent: #7a5c14;
  --accent-soft: #614810;
  --accent-rgb: 122, 92, 20;
  --accent-hi: #614810;
  --on-accent: #f7faf4;
  --btn-hi: #e5ecdd;

  --good: #2b6647;
  --good-rgb: 43, 102, 71;
  --text-good: #225539;
  --warm-rgb: 168, 128, 42;

  --r1: #9a7a1e;
  --r2: #a86a26;
  --r3: #a8462a;
  --r4: #8f2f20;
  --r5: #77251a;
}

:root[data-theme="terracotta"] {
  --bg: #f5efe4;
  --bg-soft: #ebe3d4;
  --card: #fffdf9;
  --card-hi: #f2ece0;
  --line: #e0d8c8;
  --line-soft: #ebe4d8;
  --text: #1c1b18;
  --muted: #696457;
  --dim: #6f6a5d;

  --accent: #a84f2e;
  --accent-soft: #8a3d22;
  --accent-rgb: 168, 79, 46;
  --accent-hi: #8a3d22;
  --on-accent: #fffdf9;
  --btn-hi: #eee6d8;

  --good: #276149;
  --good-rgb: 39, 97, 73;
  --text-good: #1f513c;
  --warm-rgb: 176, 134, 46;

  --r1: #a8802a;
  --r2: #b0602a;
  --r3: #a8462a;
  --r4: #93301f;
  --r5: #792318;
}

:root[data-theme="graphite"] {
  --bg: #f2f2ef;
  --bg-soft: #e6e6e1;
  --card: #ffffff;
  --card-hi: #ecece7;
  --line: #dcdcd6;
  --line-soft: #e7e7e1;
  --text: #17171a;
  --muted: #56564f;
  --dim: #62625a;

  --accent: #4f6a0d;
  --accent-soft: #3f550a;
  --accent-rgb: 79, 106, 13;
  --accent-hi: #3f550a;
  --on-accent: #ffffff;
  --btn-hi: #e8e8e2;

  --good: #2c6440;
  --good-rgb: 44, 100, 64;
  --text-good: #245334;
  --warm-rgb: 166, 128, 44;

  --r1: #9c7a24;
  --r2: #a86526;
  --r3: #a34528;
  --r4: #8e2f1e;
  --r5: #762317;
}

:root[data-bright="dark"] {
  --bg: #16130f;
  --bg-soft: #1d1915;
  --card: #221d17;
  --card-hi: #2a241d;
  --line: #2e2820;
  --line-soft: #241f19;
  --text: #efe7d9;
  --muted: #a1968a;
  --dim: #8e857a;

  --accent: #e0714a;
  --accent-soft: #f0a882;
  --accent-rgb: 224, 113, 74;
  --accent-hi: #e88157;
  --on-accent: #2a1109;
  --btn-hi: #2e2522;

  --good: #7fc99a;
  --good-rgb: 127, 201, 154;
  --text-good: #a8dcbc;
  --bad-rgb: 198, 57, 47;
  --warm-rgb: 217, 164, 65;
  --text-bad: #f0b9a4;
  --text-hot: #f5c4b6;
  --text-error: #f09a86;

  --r1: #d9a441;
  --r2: #e08a4a;
  --r3: #e0714a;
  --r4: #d8543f;
  --r5: #c6392f;

  --shadow: 0 10px 30px rgba(0, 0, 0, .35);
}

:root[data-theme="slate"][data-bright="dark"] {
  --bg: #101413;
  --bg-soft: #161b19;
  --card: #1a201e;
  --card-hi: #212825;
  --line: #2a322e;
  --line-soft: #222926;
  --text: #e4e8e2;
  --muted: #94a099;
  --dim: #808a85;

  --accent: #6fb08f;
  --accent-soft: #a3d2b8;
  --accent-rgb: 111, 176, 143;
  --accent-hi: #83bd9e;
  --on-accent: #08150f;
  --btn-hi: #202824;
}

:root[data-theme="plum"][data-bright="dark"] {
  --bg: #15101a;
  --bg-soft: #1b1522;
  --card: #211a29;
  --card-hi: #292031;
  --line: #352b3f;
  --line-soft: #2d2536;
  --text: #ece2ea;
  --muted: #a294ad;
  --dim: #8d8295;

  --accent: #c86a8c;
  --accent-soft: #e29ab4;
  --accent-rgb: 200, 106, 140;
  --accent-hi: #d47b9c;
  --on-accent: #1b0f26;
  --btn-hi: #2a2233;

  --r1: #d9a441;
  --r2: #d4844e;
  --r3: #cc6068;
  --r4: #c04a72;
  --r5: #a83566;
}

/* ------------------------- picking one of them ---------------------- */

/* ----------------------------- the look ----------------------------- */

/*
 * One line for the scheme: what it looks like, and a list to change it from.
 *
 * It was a grid of seven cards, each with a swatch, a name and a sentence —
 * which on a short phone was most of Settings before anything else got a word
 * in. The swatch is built from the hue's own colours in app.js now, so a hue
 * cannot be added without one; the four most recent had shipped as empty
 * outlines because the colours lived in this file and nobody added them.
 */
.theme-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}
.theme-swatch {
  display: flex;
  flex: none;
  width: 66px;
  height: 30px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--line-soft);
}
.theme-swatch i { flex: 1; }

#themePick {
  flex: 1;
  min-width: 0;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--edge);
  border-radius: 11px;
  background: var(--bg-soft);
  color: var(--text);
  font-family: var(--sans);
  font-weight: 600;
}
#themePick:focus { outline: none; border-color: var(--accent); }
.theme-note { margin-top: 8px; }

/* Brightness sits under the hue as one row of three, because it is one
   question with a short answer rather than four things to look at. The text
   size below it is the same shape, so it shares these rules. */
.brights {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.bright {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 90px;
  padding: 9px 10px;
  border: 0;
  border-bottom: 2px solid var(--line-soft);
  border-radius: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: calc(13.5px * var(--k));
  font-weight: 600;
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.bright:hover { color: var(--text); }
.bright.picked { color: var(--accent); border-bottom-color: var(--accent); }

/*
 * The three text sizes are set at the size they choose.
 *
 * A setting whose effect is behind the sheet you are standing in reads as one
 * that does nothing — which is how it was reported. The words demonstrate
 * themselves, and the sheet's own type answers to the choice as well, so the
 * change is visible without closing anything. Ids, so this beats the
 * narrow-screen sizing at the end of the file.
 */
#sizes [data-size-pick="small"] { font-size: calc(11.5px * var(--k)); }
#sizes [data-size-pick="default"] { font-size: calc(13.5px * var(--k)); }
#sizes [data-size-pick="large"] { font-size: calc(15.5px * var(--k)); }

/* A second row of choices under the first has to say which question it is
   answering. The hues need no label — the dropdown names itself. */
.setting-label {
  margin: 16px 0 -2px;
  font-size: calc(12.5px * var(--k));
  color: var(--muted);
}

/* ------------------ somebody else's idea, on your list --------------- */
/*
 * Two things get said here, and neither is decoration: this was not your idea,
 * and it was theirs. Built out of --accent rather than a fixed colour so it
 * still reads as "somebody else" in whichever scheme is on — including a light
 * one, where a hardcoded dark tint would simply be a smudge.
 */
.item.from-them {
  border-color: color-mix(in srgb, var(--accent) 38%, var(--line));
  background: color-mix(in srgb, var(--accent) 7%, var(--card));
}
.from-chip {
  flex: none;
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 999px;
  padding: 1px 7px;
  white-space: nowrap;
}

/* What they said they meant by it, in their name. Not italic: this is a fact
   about the suggestion, where .offer-said is a quotation of their own words. */
.offer-suggested {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--accent-soft);
}

/* ---------------------- saying what you meant ------------------------ */

.suggest-label {
  margin: 14px 0 6px;
  font-size: 11px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--dim);
}
.suggest-seg { display: flex; gap: 6px; }
.suggest-seg button {
  flex: 1;
  border: 1px solid var(--edge);
  border-radius: 9px;
  background: var(--card);
  color: var(--muted);
  padding: 8px 6px;
  font-size: 12px;
  line-height: 1.3;
  cursor: pointer;
}
.suggest-seg button.picked {
  border-color: var(--accent);
  color: var(--text);
  background: color-mix(in srgb, var(--accent) 14%, var(--card));
}
.suggest-when { display: flex; gap: 10px; margin-top: 8px; }
.suggest-when label { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.suggest-when input {
  padding: 8px 10px;
  border: 1px solid var(--edge);
  border-radius: 9px;
  background: var(--bg);
  color: var(--text);
}

/* ...and the dark half of each. Three of the four arrived this way round, so
   these are the handoff's own values; Paper's dark is the derived one. */

:root[data-theme="ink"][data-bright="dark"] {
  --bg: #0e1420;
  --bg-soft: #131b2a;
  --card: #161e2e;
  --card-hi: #1d2739;
  --line: #222c40;
  --line-soft: #1b2434;
  --text: #eaf0fa;
  --muted: #8e9bb5;
  --dim: #7d89a1;

  --accent: #6fb1ff;
  --accent-soft: #8fc1ff;
  --accent-rgb: 111, 177, 255;
  --accent-hi: #86bdff;
  --on-accent: #0e1420;
  --btn-hi: #232d41;

  --good: #7fc99a;
  --good-rgb: 127, 201, 154;
  --text-good: #a8dcbc;
  --bad-rgb: 198, 57, 47;
  --warm-rgb: 217, 164, 65;
  --text-bad: #f0b9a4;
  --text-hot: #ffb570;
  --text-error: #f09a86;

  --r1: #d9a441;
  --r2: #e08a4a;
  --r3: #ffb570;
  --r4: #e0714a;
  --r5: #d8543f;

  --shadow: 0 10px 30px rgba(0, 0, 0, .45);
}

:root[data-theme="moss"][data-bright="dark"] {
  --bg: #14201a;
  --bg-soft: #192720;
  --card: #1c2b23;
  --card-hi: #23342a;
  --line: #27382e;
  --line-soft: #1f2e26;
  --text: #eef2ea;
  --muted: #8fa896;
  --dim: #7e9685;

  --accent: #c9a24a;
  --accent-soft: #d9bb6a;
  --accent-rgb: 201, 162, 74;
  --accent-hi: #d4ae5c;
  --on-accent: #14201a;
  --btn-hi: #263830;

  --good: #7fc99a;
  --good-rgb: 127, 201, 154;
  --text-good: #a8dcbc;
  --bad-rgb: 198, 57, 47;
  --warm-rgb: 217, 164, 65;
  --text-bad: #f0b9a4;
  --text-hot: #e8b86d;
  --text-error: #f09a86;

  --r1: #d9c069;
  --r2: #e8b86d;
  --r3: #e09a5a;
  --r4: #d8684a;
  --r5: #c6483a;

  --shadow: 0 10px 30px rgba(0, 0, 0, .4);
}

:root[data-theme="terracotta"][data-bright="dark"] {
  --bg: #1b1815;
  --bg-soft: #221e1a;
  --card: #241f1b;
  --card-hi: #2c2621;
  --line: #332c26;
  --line-soft: #28221d;
  --text: #f3ece1;
  --muted: #a2988a;
  --dim: #928778;

  --accent: #d9714a;
  --accent-soft: #eda183;
  --accent-rgb: 217, 113, 74;
  --accent-hi: #e2825d;
  --on-accent: #1b1815;
  --btn-hi: #2f2823;

  --good: #7fc99a;
  --good-rgb: 127, 201, 154;
  --text-good: #a8dcbc;
  --bad-rgb: 198, 57, 47;
  --warm-rgb: 217, 164, 65;
  --text-bad: #f0b9a4;
  --text-hot: #f5c4b6;
  --text-error: #f09a86;

  --r1: #d9a441;
  --r2: #e08a4a;
  --r3: #d9714a;
  --r4: #d8543f;
  --r5: #c6392f;

  --shadow: 0 10px 30px rgba(0, 0, 0, .45);
}

:root[data-theme="graphite"][data-bright="dark"] {
  --bg: #171717;
  --bg-soft: #1d1d1d;
  --card: #222222;
  --card-hi: #2a2a2a;
  --line: #2e2e2e;
  --line-soft: #262626;
  --text: #f2f2f0;
  --muted: #9a9a94;
  --dim: #8a8a84;

  --accent: #c6e651;
  --accent-soft: #d3ec7c;
  --accent-rgb: 198, 230, 81;
  --accent-hi: #cfe968;
  --on-accent: #171717;
  --btn-hi: #2f2f2f;

  --good: #7fc99a;
  --good-rgb: 127, 201, 154;
  --text-good: #a8dcbc;
  --bad-rgb: 198, 57, 47;
  --warm-rgb: 217, 164, 65;
  --text-bad: #f0b9a4;
  --text-hot: #ffb570;
  --text-error: #f09a86;

  --r1: #d9a441;
  --r2: #e08a4a;
  --r3: #ffb570;
  --r4: #e0714a;
  --r5: #d8543f;

  --shadow: 0 10px 30px rgba(0, 0, 0, .5);
}

/* ------------------------- typing on a phone ------------------------- */

/*
 * Every field you type into is at least 16px, wherever it is.
 *
 * Safari on iOS zooms the page in when a focused field is smaller than that,
 * and it does not zoom back out: tapping "say something" on the Looking out
 * screen left the app magnified, which is what "the screen zooms on my face"
 * is. It is not a preference and there is no way to opt out of it — a field
 * under 16px is a field that zooms.
 *
 * Applied once, to everything, rather than per component: this had quietly
 * grown a dozen instances at 13.5, 14, 14.5 and 15px, each of them reasonable
 * on its own and each of them the same bug. max() so the text-size setting can
 * still make fields bigger, never smaller than the floor.
 *
 * Last in the file so it wins over the component rules it is correcting.
 */
/* The :root prefix is not decoration — it lifts this to the same specificity
   as the component rules it is correcting (`.imp-paste textarea` and friends),
   so that being last in the file is enough to win without !important. */
:root input:not([type='checkbox']):not([type='radio']):not([type='range']),
:root textarea,
:root select {
  font-size: max(16px, calc(15px * var(--k)));
}

/*
 * Narrow phones, last in the file on purpose.
 *
 * Everything here overrides a rule defined above it, and a media query does
 * not raise specificity — so sitting earlier in the stylesheet meant several
 * of these quietly lost to the very rules they were written to override. The
 * three-across choice rows were wrapping onto three lines each because of it.
 */
@media (max-width: 420px) {
  /*
   * Narrower side margins on a narrow phone — and nothing else, because this
   * rule used to restate the whole padding and so quietly undid two things it
   * was never about: the room the bar needs underneath the day, and
   * the safe-area insets. It set 56px of bottom padding under a 106px bar, so
   * "How this week went" and "Sign out" sat under it, visible and untappable,
   * on exactly the phones that have a notch to handle as well.
   *
   * Only the two sides are overridden now. Everything vertical stays with the
   * rule that knows about the bar.
   */
  .app,
  .lists-screen,
  .people-screen {
    padding-left: calc(14px + var(--safe-left));
    padding-right: calc(14px + var(--safe-right));
  }
  .appbar {
    padding-left: calc(14px + var(--safe-left));
    padding-right: calc(14px + var(--safe-right));
  }
  .topbar h1 { font-size: calc(28px * var(--k)); }
  /* One line for the notice on the smallest phone too: the sentence and its two
     controls have about 290px between them there. */
  .prompt { gap: 10px; }
  .prompt strong { font-size: 13.5px; }
  .counter .val { min-width: 56px; }

  /* 27px of serif on a 320pt screen wraps a two-word reminder onto three lines,
     and then one row is the screen. One step down for the whole day, multiplied
     on top of whatever text size was chosen; the 44px targets do not move. */
  :root { --narrow: .93; }

  /* Three choices across a 320pt sheet. The 90px floor was written when there
     were two rows of them and it wrapped each row onto three lines here, which
     is most of what made Settings feel like a wall. */
  .bright {
    min-width: 0;
    padding: 8px 6px;
    font-size: calc(11.5px * var(--k));
  }
  .themes { gap: 8px; }
}

/* ------------------------------- the day -------------------------------- */

.day-count { flex: none; text-align: right; }
.day-n {
  font-family: var(--serif);
  font-size: calc(26px * var(--k));
  font-weight: 650;
  line-height: 1.2;
}
.day-of { color: var(--dim); font-weight: 400; }
.day-count .eyebrow { margin: 0; }

/* One segment for each thing on the day. Colour is the second way of saying it:
   the caption above says the same in words. */
.day-bar { display: flex; gap: 4px; margin-top: 8px; }
.day-bar[hidden] { display: none; }
.seg { flex: 1; height: 5px; border-radius: 3px; background: var(--track); }
.seg.done { background: var(--good); }
.seg.owed { background: var(--accent); }

/* One notice at a time. Each decides for itself whether it is showing; all this
   does is let only the first of them through, in the order they are written in.
   They share one shape here so whichever wins takes the same room. */
.notices > * { margin: 6px 0 0; }
.notices > :not([hidden]) ~ :not([hidden]) { display: none; }

.later,
.done-list {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.later { margin-top: 10px; }
.later[hidden], .done-list[hidden] { display: none; }
.later .row,
.done-list .row {
  padding-left: 14px;
  padding-right: 14px;
  /* 11 rather than 13: a row is still 46 tall, above the 44 a finger needs, and a
     phone gets a row more of the day for it. */
  padding-top: calc(11px * var(--k));
  padding-bottom: calc(11px * var(--k));
}
/* Rows still carry the class the old card-shaped items had, and with it the 22px
   that separated one card from the next. Inside a list they are lines, so flush. */
.later .item + .item,
.done-list .item + .item { margin-top: 0; }
.done-list { margin-top: 8px; }

.habits { margin-top: 16px; }
.sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.sec-head .eyebrow { margin: 0; }
.habit-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: 8px; }
.habit {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 6px;
  min-height: 60px;
  padding: 8px 10px;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  /* A hold opens the item, so the browser must not treat it as a text selection
     or a link preview, and a tap must not wait to see whether it is a double. */
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.habit.is-open { border-color: var(--accent); }
.habit-top { display: flex; justify-content: space-between; gap: 6px; font-size: calc(12px * var(--k)); color: var(--muted); }
.habit-name {
  min-width: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.habit-n { flex: none; color: var(--text); font-weight: 650; font-variant-numeric: tabular-nums; }
.habit-bar { display: block; height: 4px; border-radius: 2px; background: var(--track); overflow: hidden; }
.habit-bar i { display: block; height: 100%; background: var(--good); }
.habit-open { margin-top: 8px; }
.habit-open:empty { display: none; }

/* What is finished: one line, until it is asked for. */
.done-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 52px;
  margin-top: 12px;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: calc(15px * var(--k));
  font-weight: 550;
  text-align: left;
  cursor: pointer;
}
.done-row[hidden] { display: none; }
.done-row .ico { color: var(--good); }
.done-label { flex: 1; min-width: 0; }
.done-n { font-size: calc(14px * var(--k)); font-weight: 400; color: var(--muted); }
.done-row[aria-expanded="true"] .me-chev { transform: rotate(90deg); }
.open-tally { margin-top: 10px; }
.open-tally .counter { justify-content: flex-start; }
