:root {
  color-scheme: light dark;
  /* A cool off-white page with white cards on it. Kept as components too, so a
     scrim can fade the same colour out. Taken from the cards app unchanged:
     these are two halves of one thing and should not look like two apps. */
  --bg-rgb: 247 247 250;
  --bg: rgb(var(--bg-rgb));
  --card: #ffffff;
  --text: #1c1c1e;
  --muted: #8a8a93;
  --faint: #b6b6c0;
  /* Indigo. The one saturated colour in the app, spent on the Done button, the
     due badges, and nothing else. */
  --accent: #4c3fd6;
  --accent-pressed: #4134b8;
  --on-accent: #ffffff;
  /* Semantic, and separate from the accent: being late is not an error and is
     not styled like one, but it is not nothing either. */
  --miss: #b8412f;
  --hairline: rgba(0, 0, 0, 0.1);
  --border: rgba(0, 0, 0, 0.14);
  --chip-bg: #ffffff;
  --chip-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
  --card-shadow: 0 1px 2px rgba(20, 20, 40, 0.06), 0 10px 30px -18px rgba(20, 20, 40, 0.4);

  --bar-h: 52px;
  --radius: 14px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg-rgb: 0 0 0;
    --bg: rgb(var(--bg-rgb));
    --card: #1c1c1e;
    --text: #f2f2f7;
    --muted: #93939c;
    --faint: #55555e;
    --accent: #7c6ffb;
    --accent-pressed: #6b5ef0;
    --on-accent: #ffffff;
    --miss: #ff7c66;
    --hairline: rgba(255, 255, 255, 0.12);
    --border: rgba(255, 255, 255, 0.16);
    --chip-bg: #2c2c2e;
    --chip-shadow: none;
    --card-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 12px 32px -18px rgba(0, 0, 0, 0.8);
  }
}

* {
  box-sizing: border-box;
}

/* An author `display` beats the UA stylesheet's `[hidden] { display: none }`
   whatever the specificity, so any element given a display here stops
   responding to the hidden attribute. The section heads on the home page and
   the "Earlier" head are all toggled that way. */
[hidden] {
  display: none !important;
}

/* Nothing at document level ever scrolls: every view is position: fixed and
   carries its own scroller. */
html,
body {
  height: 100%;
  overflow: hidden;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-tap-highlight-color: transparent;
}

.view {
  position: fixed;
  inset: 0;
  /* dvh, not vh. Safari's toolbar overlays the bottom of the viewport and
     changes height as you scroll; a done bar positioned against 100vh sits
     underneath it. */
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* --------------------------------------------------------------------------
   Home
   -------------------------------------------------------------------------- */

.view--home {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: max(env(safe-area-inset-top, 0px), 12px) 16px
           max(env(safe-area-inset-bottom, 0px), 12px);
}

.home-head {
  padding: 18px 4px 6px;
}

.home-title {
  margin: 0;
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.home-build {
  margin: 4px 0 0;
  font-size: 12px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* One sentence about today, above a list that says the same thing in more
   detail. A list is read; a sentence is glanced at. */
.home-sub {
  margin: 0 4px 16px;
  font-size: 14px;
  color: var(--muted);
}

.list-head {
  margin: 14px 4px 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
}

.list-head:first-of-type {
  margin-top: 0;
}

.topics {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Two hit targets, not one with a mode inside it: the row body opens the
   writing page and the caret opens the topic's settings. Siblings rather than
   nested buttons, which is invalid markup and untappable in practice. */
.topic-item {
  display: flex;
  gap: 6px;
}

.topic-open {
  flex: none;
  width: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  color: var(--muted);
  cursor: pointer;
  touch-action: manipulation;
}

.topic-open:active {
  background: color-mix(in srgb, var(--card) 92%, var(--text));
}

.topic-open svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.topic-row {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  /* Removes the double-tap-to-zoom delay. Invisible until someone moves
     quickly, and then it is the whole experience. */
  touch-action: manipulation;
}

.topic-row:active {
  background: color-mix(in srgb, var(--card) 92%, var(--text));
}

/* Never disabled, unlike the cards app's deck rows. A deck with nothing due
   has nothing to review; a topic that is not due yet can still be written in,
   and refusing to open it would be refusing the one thing this app does. */
.topic-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.topic-name {
  font-size: 17px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topic-sub {
  font-size: 13px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topic-badge {
  flex: none;
  height: 26px;
  padding: 0 10px;
  border-radius: 13px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
}

/* Waiting topics keep the shape and lose the colour. The number still says
   how far off it is, so the list can be read top to bottom without the eye
   being pulled to the things that are not asking for anything. */
.topic-badge--waiting {
  background: transparent;
  color: var(--faint);
  font-weight: 500;
}

.new-topic {
  width: 100%;
  margin-top: 14px;
  padding: 13px 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--muted);
  font: inherit;
  font-size: 15px;
  cursor: pointer;
  touch-action: manipulation;
}

.new-topic svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.home-note {
  margin: 14px 4px 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--miss);
}

.home-foot {
  margin-top: auto;
  padding: 22px 4px 8px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.home-account {
  margin: 0;
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--muted);
}

.sync-btn {
  flex: none;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--chip-bg);
  box-shadow: var(--chip-shadow);
  color: inherit;
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  touch-action: manipulation;
}

.sync-btn:disabled {
  opacity: 0.5;
}

/* --------------------------------------------------------------------------
   The three inner views
   --------------------------------------------------------------------------
   Parked off the window rather than merely translated, so a closed view is not
   sitting in the gutter in full view on a wide display. */

.view--topic,
.view--entry,
.view--settings {
  background: var(--bg);
  transform: translateX(100vw);
  visibility: hidden;
  transition: transform 220ms ease, visibility 0s linear 220ms;
}

.view--topic.is-open,
.view--entry.is-open,
.view--settings.is-open {
  transform: translateX(0);
  visibility: visible;
  transition: transform 220ms ease, visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
  .view--topic,
  .view--entry,
  .view--settings {
    transition: none;
  }
}

.rv-bar {
  flex: none;
  display: grid;
  grid-template-columns: 40px 1fr 40px;
  align-items: center;
  gap: 10px;
  height: calc(var(--bar-h) + env(safe-area-inset-top, 0px));
  padding: env(safe-area-inset-top, 0px) 12px 0;
}

.chip {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 17px;
  background: var(--chip-bg);
  box-shadow: var(--chip-shadow);
  color: var(--text);
  cursor: pointer;
  touch-action: manipulation;
}

.chip:disabled {
  opacity: 0.35;
  cursor: default;
}

.chip svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chip--danger {
  color: var(--miss);
}

/* Armed by the first tap, fired by the second. A destructive action behind a
   single tap on a phone is a destructive action taken by accident. */
.chip--danger.is-armed {
  background: var(--miss);
  color: #ffffff;
}

.rv-title {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}

.rv-deck {
  font-size: 15px;
  font-weight: 600;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rv-counts {
  font-size: 12px;
  color: var(--muted);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Writing
   -------------------------------------------------------------------------- */

.write-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px 16px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Nothing in this column shrinks. The body is the scroller, so a flex item
   left at its default `flex-shrink: 1` is squeezed to fit the viewport instead
   of running past it -- which is exactly what happened to the writing area:
   app.js grew its style.height to 1612px and the box on screen stayed 371.
   Measured, not guessed. */
.write-body > * {
  flex: none;
}

.entry-when {
  margin: 0 2px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
}

/* A page, not a box. It has no scrollbar of its own -- app.js grows it to fit
   what is in it and the body scrolls -- so a long entry is one continuous
   sheet with the earlier ones underneath it, rather than a small window onto
   text that has to be scrolled inside a field that is itself being scrolled.

   min-height is the whole point of the screen: arriving at a topic should put
   a page in front of you, not a two-line comment field. */
.write-area {
  width: 100%;
  min-height: 44vh;
  padding: 16px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  color: var(--text);
  font: inherit;
  font-size: 16px;   /* 16px or iOS zooms the page on focus */
  line-height: 1.62;
  resize: none;
  overflow: hidden;
  white-space: pre-wrap;
}

.write-area:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  border-color: transparent;
}

.write-area::placeholder {
  color: var(--faint);
}

/* The entry view is one field and nothing else, so it gets the whole height
   rather than the draft's 44%. */
.view--entry .write-area {
  min-height: 60vh;
}

.entrylist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.entry-row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
}

.entry-row:active {
  background: color-mix(in srgb, var(--card) 92%, var(--text));
}

.entry-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.entry-row-when,
.entry-peek {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entry-row-when {
  font-size: 15px;
  font-weight: 500;
}

.entry-peek {
  font-size: 13px;
  color: var(--muted);
}

.entry-len {
  flex: none;
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Done
   --------------------------------------------------------------------------
   One button, in the place the cards app puts two, and for the same reason:
   it is the thing you came here to press and a thumb should not have to travel
   to a header for it. It says when the topic comes back before it is pressed,
   as a sentence -- "Back in a week", never "7d". */

.done-bar {
  flex: none;
  padding: 12px 16px max(env(safe-area-inset-bottom, 0px), 16px);
  background: var(--bg);
  /* The list scrolls underneath this, so without a line the last visible row
     is a card sliced in half by nothing. The rule says the bar is chrome. */
  border-top: 1px solid var(--hairline);
}

.done {
  width: 100%;
  min-height: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 10px 8px;
  border: 1px solid transparent;
  border-radius: 12px;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color 140ms ease;
}

.done:active {
  background: var(--accent-pressed);
}

/* The confirmation beat. There are no haptics on the web -- the Vibration API
   does not exist in Safari -- so the tap a native app would give back has to
   be carried visually. The real confirmation is that the entry has moved into
   the list below and the header now says when it returns; this only makes sure
   that change is noticed. */
.done.is-filed {
  background: var(--accent-pressed);
}

.done-top {
  display: flex;
  align-items: center;
  gap: 8px;
}

.done-icon {
  width: 18px;
  height: 18px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.done-label {
  font-size: 16px;
  font-weight: 600;
}

.done-when {
  font-size: 11.5px;
  opacity: 0.82;
  min-height: 14px;
}

/* --------------------------------------------------------------------------
   Topic settings
   -------------------------------------------------------------------------- */

.edit-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 8px 16px max(env(safe-area-inset-bottom, 0px), 20px);
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.field-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
}

.field-input {
  width: 100%;
  padding: 11px 13px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  color: var(--text);
  font: inherit;
  font-size: 16px;   /* 16px or iOS zooms the page on focus */
  line-height: 1.45;
}

.field-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  border-color: transparent;
}

.field-note {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}

/* The cadences a journal actually has, named the way people say them. Wrapping
   chips rather than a select: every option is visible at once, which is what
   makes it obvious that four-weekly is available at all. */
.presets {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.preset {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  touch-action: manipulation;
}

.preset:active {
  background: color-mix(in srgb, var(--card) 92%, var(--text));
}

.preset.is-on {
  background: var(--accent);
  border-color: transparent;
  color: var(--on-accent);
  font-weight: 600;
}

/* Anything the chips do not cover. It always shows the current interval, so
   the two controls are one setting seen twice rather than two settings that
   can disagree. */
.custom {
  display: flex;
  align-items: center;
  gap: 8px;
}

.custom-label {
  font-size: 15px;
  color: var(--muted);
}

.custom-n {
  width: 84px;
  padding: 10px 12px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  color: var(--text);
  font: inherit;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

.custom-unit {
  padding: 10px 12px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  color: var(--text);
  font: inherit;
  font-size: 16px;
}

.custom-n:focus,
.custom-unit:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  border-color: transparent;
}

/* The laptop. The app keeps its shape and takes the middle of the screen: a
   journal entry is one column of text, and at 1440px that column was 1400px of
   empty. */
@media (min-width: 720px) {
  .view {
    left: 50%;
    right: auto;
    width: 620px;
    transform: translateX(-50%);
    border-left: 1px solid var(--hairline);
    border-right: 1px solid var(--hairline);
  }

  .view--topic,
  .view--entry,
  .view--settings {
    transform: translateX(calc(-50% + 100vw));
  }

  .view--topic.is-open,
  .view--entry.is-open,
  .view--settings.is-open {
    transform: translateX(-50%);
  }
}
