/* The app. Quiet, like the UX plan page: thin ink rules, small mono labels, a colour bar per
   class, soft rounded controls, Neue Haas Grotesk throughout. Icons are inline SVG (ui.js's
   icon()), never text symbols, which NHG doesn't have.

   Layout: under 1000px, a phone: the list scrolls the page, tabs along the bottom, an item in a
   sheet over the list. From 1000px, a laptop: sidebar, list and item side by side, each column
   scrolling on its own. */

@font-face { font-family: "NHG Display"; src: url("/assets/fonts/NHaasGroteskDSPro-55Rg.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "NHG Display"; src: url("/assets/fonts/NHaasGroteskDSPro-65Md.woff2") format("woff2"); font-weight: 500; font-display: swap; }
@font-face { font-family: "NHG Display"; src: url("/assets/fonts/NHaasGroteskDSPro-75Bd.woff2") format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "NHG Display"; src: url("/assets/fonts/NHaasGroteskDSPro-95Blk.woff2") format("woff2"); font-weight: 900; font-display: swap; }
@font-face { font-family: "NHG Text"; src: url("/assets/fonts/NHaasGroteskTXPro-55Rg.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "NHG Text"; src: url("/assets/fonts/NHaasGroteskTXPro-56It.woff2") format("woff2"); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "NHG Text"; src: url("/assets/fonts/NHaasGroteskTXPro-65Md.woff2") format("woff2"); font-weight: 500; font-display: swap; }
@font-face { font-family: "NHG Text"; src: url("/assets/fonts/NHaasGroteskTXPro-75Bd.woff2") format("woff2"); font-weight: 700; font-display: swap; }

:root {
  --paper: #ffffff;
  --ink: #0d0d0f;
  --muted: #5b5e66;
  --line: #dcdde2;
  --line-soft: #eceef1; /* between the rows of one thing: an item's steps */
  --soft: #f2f3f5;
  --ok: #1d7a3e;
  --warn: #a86400;
  --bad: #c42419;
  --accent: #da291c;
  --scrim: rgb(0 0 0 / 0.38);
  /* class colours, by /classes' `color` index */
  --k0: #2457c5; --k1: #c86f00; --k2: #2f8a52; --k3: #c0357c; --k4: #7546c2;
  --k5: #0f7f86; --k6: #8b6630; --k7: #69707d; --k8: #6f8019; --k9: #a8432a;
  --k-none: #9a9ca3;

  /* Not the installed "Neue Haas Grotesk" names: a locally installed copy can map arrows and
     check marks to its empty box, which stops the browser falling back for them. */
  --display: "NHG Display", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --text: "NHG Text", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --gutter: 16px;
  --tabs: 60px;
  --radius: 10px;
  --btn-radius: 8px;
  --rule: 1.5px;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0f1012; --ink: #f1f1f3; --muted: #a3a6ae; --line: #2e3036; --line-soft: #222328; --soft: #1a1b1f;
    --ok: #4cc276; --warn: #f0a43a; --bad: #ff6a5e; --accent: #e8382b; --scrim: rgb(0 0 0 / 0.6);
    --k0: #6b96f2; --k1: #f29a2e; --k2: #4fb877; --k3: #e866a6; --k4: #a07ce8;
    --k5: #39b4bc; --k6: #c49b5f; --k7: #9aa1ad; --k8: #aec24a; --k9: #e0785c;
    --k-none: #6c6f77;
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 16px/1.45 var(--text);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "ss01" 0;
}
h1, h2, h3, p { margin: 0; }
h1, h2, h3 { text-wrap: balance; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-underline-offset: 3px; text-decoration-thickness: 1px; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; } /* not red: that means late */
kbd { font: 500 12px/1.6 var(--mono); border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; padding: 0 5px; }
code { font: 13px/1.5 var(--mono); }
small { font-size: 13px; }
.booting, .loading { padding: 32px var(--gutter); color: var(--muted); }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 42px; padding: 8px 14px;
  border: var(--rule) solid var(--ink); border-radius: var(--btn-radius);
  background: transparent; color: var(--ink);
  font: 500 15px/1.2 var(--text); text-decoration: none; text-align: center;
  cursor: pointer;
}
.btn:disabled { opacity: 0.45; cursor: default; }
.btn-primary, .btn-strong { background: var(--ink); color: var(--paper); }
.btn-quiet { border-color: transparent; color: var(--muted); }
.btn-wide { width: 100%; }
.btns { display: flex; flex-wrap: wrap; gap: 8px; }
/* Equal columns while they fit; a longer label ("Turned in") widens its own column rather than
   wrapping onto two lines. */
.btns-even { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(max-content, 1fr); }
.btns-even .btn { padding-inline: 6px; white-space: nowrap; }
.btns-even .btn-strong { background: transparent; color: var(--ink); border-width: 2px; font-weight: 700; }
.btn[aria-expanded="true"] { background: var(--soft); }
.link-btn {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: 500 14px var(--text); text-decoration: underline; text-underline-offset: 3px;
}
.close, .tool {
  flex: none; display: grid; place-items: center; width: 40px; height: 40px;
  border: 0; background: none; cursor: pointer; color: var(--muted);
}
.close { margin: -8px -10px 0 0; }
.close:hover, .tool:hover { color: var(--ink); }
.close .icon { width: 22px; height: 22px; }
.tool .icon { width: 20px; height: 20px; }
.tool.is-busy { color: var(--ink); cursor: default; }
.tool.is-busy .icon { animation: spin 1.2s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Icons (ui.js's icon()): 1em, so they size with the text beside them. A 2/24 stroke is about
   NHG Text's stem at 16px. */
.icon {
  width: 1em; height: 1em; flex: none; vertical-align: -0.14em;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: square; stroke-linejoin: miter;
}
.icon .fill { stroke: none; }
.field {
  display: block; width: 100%;
  padding: 10px 12px;
  border: var(--rule) solid var(--line); border-radius: 9px;
  background: var(--paper); color: var(--ink);
  font: 16px/1.4 var(--text); /* 16px: iOS zooms into smaller inputs */
}
.field:focus { border-color: var(--ink); outline: none; }
textarea.field { resize: vertical; }

.chip {
  display: inline-block;
  font: 600 10.5px/1.5 var(--mono); letter-spacing: 0.04em; text-transform: uppercase;
  border: 1px solid var(--line); border-radius: 3px; padding: 0 5px;
  color: var(--muted); white-space: nowrap;
}
.chip-ink { border-color: var(--ink); color: var(--ink); }
.chip-bad { border-color: var(--bad); color: var(--bad); }
.chip-fill { background: var(--soft); }
.src { font: 600 10px/1.5 var(--mono); border: 1px solid var(--line); border-radius: 3px; padding: 0 4px; color: var(--muted); }

/* ---------- frame: phone ---------- */

.shell { min-height: 100dvh; }
.side { display: none; }
.topbar {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: calc(10px + env(safe-area-inset-top)) var(--gutter) 0;
}
.brand { font: 900 19px/1 var(--display); letter-spacing: -0.02em; text-decoration: none; }
.list { display: block; padding: 0 var(--gutter) calc(var(--tabs) + 40px + env(safe-area-inset-bottom)); outline: none; }
.tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: grid; grid-template-columns: repeat(4, 1fr);
  padding: 6px 4px env(safe-area-inset-bottom);
  background: var(--paper); border-top: 1px solid var(--line);
}
.tabs a {
  display: grid; justify-items: center; gap: 4px; padding: 4px 0 6px;
  font: 500 11.5px/1.2 var(--text); color: var(--muted); text-decoration: none;
}
.tabs .icon { width: 24px; height: 24px; stroke-width: 1.75; }
.tabs a[aria-current="page"] { color: var(--ink); font-weight: 700; }
.tabs a[aria-current="page"] .icon .fill { fill: currentColor; }

.fresh {
  display: inline-flex; align-items: center; gap: 7px; min-height: 36px;
  border: 0; background: none; padding: 0; cursor: pointer;
  font: 500 12px/1.3 var(--mono); color: var(--muted); text-align: left;
}
.fresh-dot, .src-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); flex: none; }
.is-warn > .fresh-dot, .is-warn > .src-dot { background: var(--warn); }
.is-bad > .fresh-dot, .is-bad > .src-dot { background: var(--bad); }
.is-busy > .fresh-dot, .is-busy > .src-dot { background: var(--ink); animation: pulse 1.2s ease-in-out infinite; }
.is-off > .src-dot { background: var(--line); }
.fresh.is-bad { color: var(--bad); font-weight: 600; }
@keyframes pulse { 50% { opacity: 0.25; } }

/* The item, as a sheet from the bottom. */
.scrim {
  position: fixed; inset: 0; z-index: 30; background: var(--scrim);
  opacity: 0; pointer-events: none; transition: opacity 0.2s;
}
.detail {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 31;
  max-height: calc(100dvh - 40px - env(safe-area-inset-top)); overflow-y: auto; overscroll-behavior: contain;
  background: var(--paper);
  border-top: var(--rule) solid var(--ink); border-radius: 18px 18px 0 0;
  padding-bottom: env(safe-area-inset-bottom);
  transform: translateY(105%); visibility: hidden;
  transition: transform 0.25s ease, visibility 0s 0.25s;
}
.shell.has-item .scrim { opacity: 1; pointer-events: auto; }
.shell.has-item .detail { transform: none; visibility: visible; transition: transform 0.25s ease; }
body:has(.shell.has-item) { overflow: hidden; }
.detail-empty { display: none; }

@media (min-width: 640px) {
  :root { --gutter: 28px; }
  .list > *, .topbar { max-width: 760px; margin-inline: auto; }
  .detail { max-width: 640px; margin-inline: auto; border-inline: var(--rule) solid var(--ink); }
}

/* ---------- frame: laptop ---------- */

@media (min-width: 1000px) {
  :root { --gutter: 40px; --side-w: 236px; --detail-w: max(380px, 30vw); }
  .shell { display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr) var(--detail-w); height: 100dvh; }
  .topbar, .tabs, .scrim { display: none; }
  body:has(.shell.has-item) { overflow: auto; }
  .side, .list, .detail { height: 100dvh; overflow-y: auto; }
  .side {
    display: flex; flex-direction: column; gap: 4px;
    padding: 24px 16px 16px 20px; border-right: 1px solid var(--line);
  }
  .side .brand { font-size: 22px; padding: 2px 8px 18px; }
  .side-nav { display: grid; gap: 2px; }
  .side-nav a { display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: 7px; text-decoration: none; font: 500 15px/1.3 var(--text); color: var(--muted); }
  .side-nav .icon { width: 18px; height: 18px; stroke-width: 1.75; }
  .side-nav a[aria-current="page"] .icon .fill { fill: currentColor; }
  .side-nav a:hover { color: var(--ink); }
  .side-nav a[aria-current="page"] { color: var(--ink); background: var(--soft); font-weight: 700; }
  .side-label { font: 600 11px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); padding: 22px 8px 6px; }
  .side-classes { display: grid; gap: 1px; margin-bottom: auto; }
  .side-classes a { display: flex; align-items: center; gap: 10px; padding: 5px 8px; border-radius: 7px; text-decoration: none; font-size: 14px; }
  .side-classes a:hover, .side-classes a[aria-current="page"] { background: var(--soft); }
  .side-classes a[aria-current="page"] { font-weight: 700; }
  .side-bar { width: 4px; height: 16px; border-radius: 2px; background: var(--c); flex: none; }
  .side .fresh { margin: 16px 8px 0; }
  .list { padding: 8px var(--gutter) 80px; }
  .list > * { max-width: 760px; margin-inline: 0; }
  .detail {
    position: static; max-height: none; transform: none; visibility: visible; transition: none;
    border: 0; border-left: 1px solid var(--line); border-radius: 0; max-width: none; margin: 0;
  }
  .detail-empty { display: grid; place-content: center; gap: 14px; height: 100%; padding: 32px; color: var(--muted); text-align: center; }
  .detail-empty .keys { font-size: 13px; line-height: 2.2; max-width: 30ch; }
}

/* ---------- Today ---------- */

.today-head { display: grid; gap: 4px; padding: 18px 0 6px; }
.today-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 28px; }
.today-select { min-height: 28px; padding: 2px 10px; font-size: 13px; }
.today-select[aria-pressed="true"] { border-color: var(--ink); }
.today-kicker { font: 600 12px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.today-date { font: 700 clamp(30px, 6vw, 42px)/1.05 var(--display); letter-spacing: -0.02em; }
.next {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 14px;
  margin-top: 14px; padding: 12px 14px;
  border: var(--rule) solid var(--ink); border-radius: 12px; text-decoration: none;
}
.next > :not(.next-count) { grid-column: 1; }
.next-label { font: 600 11px/1.4 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.next-title { font: 500 17px/1.3 var(--text); overflow-wrap: anywhere; }
.next-sub { color: var(--muted); font-size: 14px; }
.next-count { grid-column: 2; grid-row: 1 / span 3; font: 700 30px/1 var(--display); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.next-none { border-color: var(--line); }
a.next:hover { background: var(--soft); }

/* The class you're in, or between classes the next one, above the next deadline: only during
   the school day. */
.now-slot:empty { display: none; }
.now { margin-top: 14px; border: var(--rule) solid var(--ink); border-radius: 12px; }
.now-main { display: grid; grid-template-columns: 4px minmax(0, 1fr) auto; column-gap: 12px; align-items: center; padding: 12px 14px; }
.now-main .row-bar { align-self: stretch; }
.now-text { display: grid; min-width: 0; }
.now-count { display: grid; justify-items: end; font: 700 30px/1 var(--display); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.now-count small { font: 500 12px/1.5 var(--text); letter-spacing: 0; color: var(--muted); }
.now-next { display: flex; align-items: baseline; gap: 10px; padding: 9px 14px; border-top: 1px solid var(--line); font-size: 14px; }
.now-next b { color: var(--c); font-weight: 700; }
.now-day { border-top: 1px solid var(--line); }
.now-day > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
  padding: 9px 14px; font-size: 14px; color: var(--muted);
}
.now-day > summary::-webkit-details-marker { display: none; }
.now-day > summary:hover { color: var(--ink); }
.now-day[open] > summary .icon { transform: rotate(90deg); }
.periods { margin: 0; padding: 0 14px 10px; list-style: none; }
.periods li {
  display: grid; grid-template-columns: 2.6em 5.4em 4px minmax(0, 1fr) auto; column-gap: 10px; align-items: center;
  padding: 3px 0; font-size: 14px; font-variant-numeric: tabular-nums;
}
.periods .row-bar { align-self: stretch; }
.period-name { font: 500 12px var(--mono); color: var(--muted); }
.period-class { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.period-room { color: var(--muted); }
.periods .is-past { color: var(--muted); }
.periods .is-past .row-bar { opacity: 0.35; }
.periods .is-now { font-weight: 700; }
.periods .is-now .period-name, .periods .is-now .period-room { color: var(--ink); }

.day { display: block; margin-top: 26px; }
.day-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding-bottom: 6px; border-bottom: var(--rule) solid var(--ink);
  font: 600 12px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
}
.day-today .day-head { color: var(--ink); }
.day-head.is-alert { color: var(--bad); border-color: var(--bad); }
.day-right { font: 500 13px var(--text); letter-spacing: 0; text-transform: none; color: var(--ink); }
.day-link { display: inline-flex; align-items: center; gap: 4px; text-decoration: none; }
.day-link:hover { text-decoration: underline; }
details.day > summary { list-style: none; cursor: pointer; }
details.day > summary::-webkit-details-marker { display: none; }
details[open].day .day-right { visibility: hidden; }
.empty { padding: 12px 0; color: var(--muted); border-bottom: 1px solid var(--line); }
.more > summary {
  list-style: none; cursor: pointer; padding: 10px 0 10px 16px; border-bottom: 1px solid var(--line);
  font-size: 14px; font-weight: 500; color: var(--muted);
}
.more > summary::-webkit-details-marker { display: none; }
.more > summary::before { content: "+ "; }
.more[open] > summary::before { content: "− "; }
.more > summary:hover { color: var(--ink); }

.row-wrap { position: relative; overflow: hidden; border-bottom: 1px solid var(--line); }
.row {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 4px minmax(0, 1fr) auto; gap: 12px; align-items: start;
  padding: 11px 0; background: var(--paper);
  cursor: pointer; touch-action: pan-y; user-select: none; -webkit-user-select: none;
  -webkit-touch-callout: none; transition: transform 0.18s ease;
}
.row-wrap.is-swiping .row { transition: none; }
.row:focus-visible { outline-offset: -2px; }
.row-bar { align-self: stretch; border-radius: 2px; background: var(--c); }
.row-main { display: grid; gap: 3px; min-width: 0; }
.row-title { font: 500 16px/1.3 var(--text); overflow-wrap: anywhere; }
.row-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 13px; color: var(--muted); }
.row-class { color: var(--c); font-weight: 700; }
.row-when { font-size: 14px; font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; padding-top: 1px; }
.row.is-late .row-when { color: var(--bad); }
.row.is-done .row-title { text-decoration: line-through; text-decoration-thickness: 1px; color: var(--muted); font-weight: 400; }
.row.is-done .row-bar { opacity: 0.35; }
.row-done { display: inline-flex; align-items: center; gap: 4px; color: var(--ok); font-weight: 500; }
.row-btns { display: none; }
.row.is-open { background: var(--soft); }

/* Under a swiped row: what letting go will do. */
.under {
  position: absolute; inset: 0; display: none; align-items: center; gap: 6px; padding: 0 16px;
  font: 700 14px var(--text); color: var(--paper);
}
.under .icon { width: 18px; height: 18px; stroke-width: 2.25; }
.under-right { background: var(--ok); }
.under-left { background: var(--ink); justify-content: flex-end; }
.row-wrap[data-dir="right"] .under-right, .row-wrap[data-dir="left"] .under-left { display: flex; opacity: 0.55; }
.row-wrap.is-armed .under { opacity: 1; }

/* With a mouse, a row shows its buttons on hover. */
@media (hover: hover) and (pointer: fine) {
  .row { grid-template-columns: 4px minmax(0, 1fr) auto 64px; padding-right: 4px; }
  .row:hover { background: var(--soft); }
  .row-btns { display: flex; gap: 2px; justify-content: flex-end; visibility: hidden; }
  .row:hover .row-btns, .row:focus-within .row-btns, .row:focus .row-btns { visibility: visible; }
  .row-btn {
    display: grid; place-items: center; width: 30px; height: 28px;
    border: 1px solid var(--line); border-radius: 6px; background: var(--paper); cursor: pointer;
  }
  .row-btn .icon { width: 16px; height: 16px; }
  .row-btn:hover { border-color: var(--ink); }
}

/* A row with a box to tick it (Missing): the box, then the colour bar. */
.row.has-check { grid-template-columns: 20px 4px minmax(0, 1fr) auto; }
@media (hover: hover) and (pointer: fine) {
  .row.has-check { grid-template-columns: 20px 4px minmax(0, 1fr) auto 64px; }
}
.row-check, .group-check {
  width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--ink); cursor: pointer;
}
.row.is-picked, .steps-head.is-picked, .step-row.is-picked { background: var(--soft); }
/* Skipped isn't done: muted, not struck through or green. */
.row.is-skipped .row-title { text-decoration: none; }
.row.is-skipped .row-done { color: var(--muted); }

/* An item with its steps (Today's stepsBlock()), as one block: the item's own row, or where it
   isn't due a smaller header naming it, led by an arrow; under it the steps, compact rows with a
   dashed bar in the item's bar's column; then a fold with every step. */
.steps-block { padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.steps-block > .row-wrap { border-bottom: 0; }
.steps-block > .row-wrap > .row { padding-bottom: 0; }
.steps-block > .row-wrap > .row > .row-main { padding-bottom: 9px; }
.steps-block .row-bar { border-radius: 2px 2px 0 0; }
.steps-head {
  display: grid; grid-template-columns: 4px minmax(0, 1fr); gap: 12px; align-items: start;
  padding-top: 10px; cursor: pointer; user-select: none; -webkit-user-select: none;
}
.steps-head > .row-main { gap: 2px; padding-bottom: 8px; }
.steps-head, .step-row { -webkit-touch-callout: none; }
/* While selecting, Today's rows and headers have a box before their bar (20px and a 12px gap), so
   the steps under them are indented as far, keeping their dashed bars under the item's. */
.steps-head.has-check { grid-template-columns: 20px 4px minmax(0, 1fr); }
.today.is-selecting .step { padding-left: 32px; }
.step-src { margin-left: 7px; vertical-align: 1px; white-space: nowrap; }
.steps-head:focus-visible, .step-row:focus-visible { outline-offset: -2px; }
.steps-title { font: 500 14px/1.3 var(--text); color: color-mix(in srgb, var(--ink) 80%, var(--paper)); overflow-wrap: anywhere; }
/* Down and to the right: only part of this item is here. */
.steps-title > .icon-substep { width: 13px; height: 13px; margin-right: 6px; vertical-align: -0.08em; color: var(--c); stroke-width: 2.4; }
.steps-head .row-meta { font-size: 12.5px; }
.steps-head .is-late { color: var(--bad); }
.steps-head.is-open, .step-row.is-open { background: var(--soft); }
.steps-count { display: inline-flex; align-items: center; gap: 6px; }
.steps-meter { display: inline-flex; gap: 2px; }
.steps-meter i { display: block; width: 9px; height: 4px; border-radius: 1px; background: var(--line); }
.steps-meter i.is-done { background: var(--c); }
/* The steps this block lists. */
.steps-meter i.is-here { background: transparent; box-shadow: inset 0 0 0 1.5px var(--c); }
.step { display: grid; grid-template-columns: 4px minmax(0, 1fr); column-gap: 12px; }
.step-dash { background: repeating-linear-gradient(to bottom, var(--c) 0 5px, transparent 5px 8px); }
.step-swipe { position: relative; min-width: 0; overflow: hidden; }
.step-swipe[data-dir="right"] .under-right, .step-swipe[data-dir="left"] .under-left { display: flex; opacity: 0.55; }
.step-swipe.is-armed .under { opacity: 1; }
.step-row {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; column-gap: 9px; align-items: start;
  padding: 7px 0; border-top: 1px solid var(--line-soft); background: var(--paper);
  cursor: pointer; touch-action: pan-y; user-select: none; -webkit-user-select: none;
  transition: transform 0.18s ease; -webkit-tap-highlight-color: transparent;
}
.step-swipe.is-swiping .step-row { transition: none; }
/* A bigger target than the box, overlapping the row's padding. */
.step-hit { display: grid; place-items: center; width: 36px; height: 34px; margin: -8px -10px; cursor: pointer; }
.step-tick { width: 16px; height: 16px; margin: 0; accent-color: var(--ink); cursor: pointer; }
.step-title { font: 15px/1.3 var(--text); overflow-wrap: anywhere; min-width: 0; }
.step-when { font-size: 13px; line-height: 1.3; white-space: nowrap; font-variant-numeric: tabular-nums; padding-top: 1px; }
.step-when.is-none { color: var(--muted); }
.step-row.is-late .step-when { color: var(--bad); }
.step-row.is-done .step-title { text-decoration: line-through; text-decoration-thickness: 1px; color: var(--muted); }
.step-row.is-done .step-when { color: var(--muted); }
.step-row.is-here .step-title, .step-row.is-here .step-when { font-weight: 500; }
.steps-fold { min-width: 0; border-top: 1px solid var(--line-soft); }
.steps-fold > summary {
  list-style: none; display: grid; grid-template-columns: 16px minmax(0, 1fr); column-gap: 9px; align-items: center;
  min-height: 34px; font-size: 13px; color: var(--muted); cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.steps-fold > summary::-webkit-details-marker { display: none; }
.steps-fold > summary:hover { color: var(--ink); }
.steps-fold > summary > .icon { grid-column: 1; justify-self: center; width: 14px; height: 14px; transition: transform 0.15s ease; }
.steps-fold[open] > summary > .icon { transform: rotate(90deg); }
.steps-fold > summary > span { grid-column: 2; min-width: 0; }
.steps-opened, .steps-fold[open] .steps-closed { display: none; }
.steps-fold[open] .steps-opened { display: inline; }
.steps-all .step-row { padding-block: 6px; }
@media (prefers-reduced-motion: reduce) { .steps-fold > summary > .icon { transition: none; } }
/* With a mouse: hover like a row, and times in line with the rows' (left of their buttons). */
@media (hover: hover) and (pointer: fine) {
  .steps-head:hover, .step-row:hover { background: var(--soft); }
  .step-row { padding-right: 80px; }
}

/* ---------- pages ---------- */

/* One column that never grows past the screen: a wide row (the Inbox's filters) scrolls instead. */
.page { padding-top: 20px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.page-title { font: 700 clamp(30px, 6vw, 42px)/1.05 var(--display); letter-spacing: -0.02em; }
.page-note { color: var(--muted); max-width: 60ch; }
.page .day { margin-top: 14px; }
.page-head { display: grid; gap: 4px; }
.more-links { display: grid; gap: 8px; }
.page-more { padding-top: 14px; font-size: 15px; }
.page-more a { display: inline-flex; align-items: center; gap: 4px; }

/* ---------- Missing ---------- */

.missing-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.missing-class .day-head { align-items: center; }
.group-pick { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.group-pick .title-bar { height: 1em; margin-right: 0; }

/* What's ticked, and what to do to it: in ink, fixed at the bottom of the screen (above the tabs
   on a phone, over the list column on a laptop) while there's a selection. Not sticky: a sticky
   bar rides up into the page when the list is short or scrolled to its end, under the toast.
   The page leaves room for it, so the last rows scroll clear (missing.js keeps --bulk-h). */
.bulk {
  position: fixed; z-index: 5; left: var(--gutter); right: var(--gutter);
  bottom: calc(var(--tabs) + 12px + env(safe-area-inset-bottom));
  max-width: 760px; margin-inline: auto;
  display: grid; gap: 10px; padding: 10px 12px;
  background: var(--ink); color: var(--paper); border-radius: 12px;
}
.missing-page:has(> .bulk:not([hidden])), .today:has(> .bulk:not([hidden])) { padding-bottom: calc(var(--bulk-h, 64px) + 12px); }
.bulk[hidden], .bulk-panel[hidden], .bulk .btn[hidden] { display: none; }
.bulk :focus-visible { outline-color: var(--paper); }
.bulk { -webkit-tap-highlight-color: transparent; }
/* The count and the close button share a line, over the buttons; side by side from 600px. */
.bulk-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px; }
.bulk-count { font-weight: 600; font-variant-numeric: tabular-nums; }
.bulk-btns { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
@media (min-width: 600px) {
  .bulk-row { grid-template-columns: auto minmax(0, 1fr) auto; }
  .bulk-btns { grid-column: 2; grid-row: 1; justify-content: flex-end; }
  .bulk-clear { grid-column: 3; grid-row: 1; }
}
/* A phone's width fits four of them in a row as words alone. */
@media (max-width: 429px) {
  .bulk-btns .btn-small > .icon { display: none; }
}
.bulk .btn-small { color: var(--paper); border-color: color-mix(in srgb, var(--paper) 40%, transparent); }
.bulk .btn-small:hover { border-color: var(--paper); }
.bulk .btn-small .icon { color: inherit; }
.bulk .btn[aria-expanded="true"] { background: color-mix(in srgb, var(--paper) 18%, transparent); }
.bulk-clear {
  display: grid; place-items: center; width: 34px; height: 34px; padding: 0;
  border: 0; border-radius: var(--btn-radius); background: none; color: inherit; cursor: pointer;
}
.bulk-clear .icon { width: 18px; height: 18px; }
.bulk-move { display: grid; gap: 8px; }
.bulk-days { display: flex; flex-wrap: wrap; gap: 6px; }
.bulk .field { background: var(--paper); color: var(--ink); }
.bulk .btn-small:disabled { opacity: 0.45; cursor: default; }
.bulk .btn-small:disabled:hover { border-color: color-mix(in srgb, var(--paper) 40%, transparent); }
/* What the selection is part of (Today): choices, each an item's title over its class and date. */
.bulk-parent { display: grid; gap: 8px; }
.bulk-label { font: 600 11px/1.4 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.7; }
.bulk-choices { display: grid; gap: 6px; max-height: min(36vh, 300px); overflow-y: auto; overscroll-behavior: contain; }
.bulk-choices:empty { display: none; }
.bulk-choice {
  display: grid; grid-template-columns: 4px minmax(0, 1fr); column-gap: 10px; text-align: left;
  padding: 7px 10px; border: 1px solid color-mix(in srgb, var(--paper) 40%, transparent); border-radius: var(--btn-radius);
  background: none; color: inherit; font: inherit; cursor: pointer;
}
.bulk-choice::before { content: ""; grid-row: 1 / span 2; border-radius: 2px; background: var(--c); }
.bulk-choice:hover { border-color: var(--paper); }
.bulk-choice b { font-weight: 500; overflow-wrap: anywhere; }
.bulk-choice small { font-size: 13px; opacity: 0.7; }
.bulk-none { font-size: 14px; opacity: 0.7; }
@media (min-width: 1000px) {
  .bulk {
    left: calc(var(--side-w) + var(--gutter)); right: auto; bottom: 16px; margin: 0;
    width: min(760px, 100vw - var(--side-w) - var(--detail-w) - 2 * var(--gutter));
  }
}
/* A toast while the bar is up goes above it (missing.js keeps --bulk-h). */
body:has(.bulk:not([hidden])) .toast-host { bottom: calc(var(--tabs) + 28px + var(--bulk-h, 64px) + env(safe-area-inset-bottom)); }
@media (min-width: 1000px) {
  body:has(.bulk:not([hidden])) .toast-host { bottom: calc(32px + var(--bulk-h, 64px)); }
}

/* ---------- Inbox ---------- */

.inbox-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.inbox-tools .seg { min-width: 0; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.inbox-tools .seg > a { white-space: nowrap; }
.seg-count { font: 500 12px var(--mono); }
.ibx { border-bottom: 1px solid var(--line); }
.ibx-link {
  display: grid; grid-template-columns: 4px minmax(0, 1fr) auto; gap: 12px; align-items: start;
  padding: 11px 0; text-decoration: none;
}
.ibx-link:hover, .ibx-link.is-open { background: var(--soft); }
.ibx-link:focus-visible { outline-offset: -2px; }
.ibx-link .row-bar { align-self: stretch; }
.ibx-main { display: grid; gap: 3px; min-width: 0; }
.ibx-head { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; font-size: 13px; color: var(--muted); }
/* New: a dot in ink (red means late). */
.ibx-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink); flex: none; }
.ibx-title { font: 500 16px/1.3 var(--text); overflow-wrap: anywhere; }
.ibx-text {
  font-size: 15px; line-height: 1.45; white-space: pre-line; overflow-wrap: anywhere; color: var(--muted);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.ibx-text.is-lead { color: var(--ink); -webkit-line-clamp: 3; } /* a post: its text is what it says */
.ibx-sub { font-size: 14px; color: var(--muted); }
.ibx-sub b { color: var(--ink); font-weight: 500; }
.ibx-right { display: grid; justify-items: end; gap: 1px; padding-top: 1px; font-size: 15px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ibx-right small { font-size: 13px; }
.ibx-streams > summary { padding-left: 16px; }
.ibx-streams .ibx:last-child { border-bottom: 0; }

/* What a post suggests: a card under it, in ink like the item's panels. */
.sug {
  display: grid; gap: 6px; margin: 0 0 12px 16px; padding: 12px 14px;
  border: var(--rule) solid var(--ink); border-radius: 12px;
}
.sug-label { font: 600 11px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.sug-title { font: 500 16px/1.3 var(--text); overflow-wrap: anywhere; }
.sug-meta { font-size: 14px; color: var(--muted); }
.sug-meta b { color: var(--ink); font-weight: 500; }
.sug-btns { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.sug-form { display: grid; gap: 10px; }
.sug-form label { display: grid; gap: 4px; font-size: 13px; color: var(--muted); }
.sug-form .sug-check { display: flex; align-items: center; gap: 8px; font-size: 15px; color: var(--ink); cursor: pointer; }
.sug-check input { width: 18px; height: 18px; margin: 0; accent-color: var(--ink); }
.sug-added { display: flex; gap: 6px; align-items: baseline; margin: -2px 0 10px 16px; font-size: 14px; color: var(--muted); }
.sug-added .icon { color: var(--ok); }
.sug-added a { color: var(--ink); }
.sug-slot { display: grid; gap: 10px; }
.sug-slot .sug, .sug-slot .sug-added { margin: 0; }
.sug-hand { font-size: 14px; color: var(--muted); }

/* The Inbox's count, on its tab: in ink, never red. */
.badge {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--ink); color: var(--paper); font: 600 11px/18px var(--mono); text-align: center;
}
.badge[hidden] { display: none; }
.tabs a { position: relative; }
.tabs .badge { position: absolute; top: 0; left: calc(50% + 6px); }
.side-nav .badge { margin-left: auto; }

/* ---------- Search ---------- */

.search-field { display: grid; gap: 8px; }
.search-box { font-size: 17px; }
/* The browser's clear button, drawn as the app's close icon (Chrome's is blue). */
.search-box::-webkit-search-cancel-button {
  -webkit-appearance: none; appearance: none; width: 18px; height: 18px; cursor: pointer;
  background: var(--muted);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / contain no-repeat;
}
.search-box::-webkit-search-cancel-button:hover { background: var(--ink); }
.pill { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 14px; }
.pill[hidden] { display: none; }
.pill-label { font: 600 11px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.pill-item {
  display: inline-flex; align-items: center; min-width: 0; padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px;
  font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pill-item .title-bar { flex: none; margin-right: 8px; }
.pill-x { display: grid; place-items: center; width: 28px; height: 28px; border: 0; border-radius: 6px; background: none; cursor: pointer; color: var(--muted); }
.pill-x:hover { color: var(--ink); background: var(--soft); }
.say:empty { display: none; }
.say .icon { color: var(--muted); }
.say-unknown { color: var(--muted); }
.search-hint .icon { width: 15px; height: 15px; }
.hits > .day:first-child { margin-top: 6px; }
.hit-text { font-size: 14px; color: var(--muted); overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.hit-class .plain-title { display: flex; align-items: center; }
.post .row-class { color: var(--c); font-weight: 700; }
mark { background: color-mix(in srgb, var(--ink) 12%, transparent); color: inherit; border-radius: 2px; padding: 0 1px; }

/* ---------- Classes ---------- */

.back {
  justify-self: start; display: inline-flex; align-items: center; gap: 2px; margin: 0 0 -4px -6px; padding: 6px 6px 2px 0;
  font-size: 15px; color: var(--muted); text-decoration: none;
}
.back:hover { color: var(--ink); }
.back .icon { width: 18px; height: 18px; }
.title-bar { display: inline-block; width: 6px; height: 0.78em; margin-right: 12px; border-radius: 2px; background: var(--c); vertical-align: 0.02em; }
.btn-small { min-height: 34px; padding: 5px 10px; font-size: 14px; border-width: 1px; border-color: var(--line); }
.btn-small:hover { border-color: var(--ink); }
.btn-small .icon { width: 14px; height: 14px; color: var(--muted); }
.platforms { display: flex; flex-wrap: wrap; gap: 6px; }

/* A grade or the GPA: the value, how it moved, and its line. Proportional figures: tabular
   ones look loose at this size. */
.tile { display: grid; gap: 2px; padding: 12px 14px 10px; border: var(--rule) solid var(--ink); border-radius: 12px; }
.tile-top { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.tile-label { font: 600 11px/1.4 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.tile-value { display: flex; align-items: baseline; gap: 4px; font: 700 34px/1.1 var(--display); letter-spacing: -0.02em; }
.tile-value small { font: 500 15px var(--text); letter-spacing: 0; color: var(--muted); }
.tile-letter { margin-right: 8px; font-weight: 700; }
.tile-delta { min-height: 1.45em; font-size: 14px; color: var(--muted); }
.tile-delta b { color: var(--ink); font-weight: 500; }
.delta { font-weight: 500; white-space: nowrap; }
/* The arrow stands on the baseline at cap height with about the text's stem; its box is cut to
   the arrow's width (`slice`), so it lines up with the text's left edge. */
.delta .icon { width: 0.55em; overflow: visible; margin-right: 0.28em; stroke-width: 2.5; }
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.delta.is-up { color: var(--ok); }
.delta.is-down { color: var(--bad); }
.spark { position: relative; height: 40px; margin: 6px 0 2px; cursor: crosshair; touch-action: pan-y; }
.spark:focus-visible { outline-offset: 4px; border-radius: 4px; }
.spark svg { display: block; width: 100%; height: 100%; overflow: visible; }
.spark-line {
  fill: none; stroke: color-mix(in srgb, var(--muted) 70%, var(--paper)); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke;
}
.spark-dot, .spark-mark {
  position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
  background: var(--c, var(--ink)); box-shadow: 0 0 0 2px var(--paper); pointer-events: none;
}
.spark-mark { background: var(--ink); }
.spark-cross { position: absolute; top: -2px; bottom: -2px; width: 1px; background: var(--line); pointer-events: none; }
.spark [hidden] { display: none; }

/* A segmented control: terms, and the GPA's scale. */
.seg { justify-self: start; display: inline-flex; border: 1px solid var(--line); border-radius: var(--btn-radius); overflow: hidden; }
.seg > a, .seg > button {
  min-height: 34px; padding: 6px 12px; border: 0; background: none; cursor: pointer;
  font: 500 14px/1.6 var(--text); color: var(--muted); text-decoration: none;
}
.seg > * + * { border-left: 1px solid var(--line); }
.seg > :hover { color: var(--ink); }
.seg > [aria-current="true"], .seg > [aria-pressed="true"] { background: var(--ink); color: var(--paper); font-weight: 700; }
.seg-small > button, .seg-small > a { min-height: 28px; padding: 2px 10px; font: 500 13px/1.7 var(--text); letter-spacing: 0; text-transform: none; }
.day-head:has(.seg) { align-items: center; padding-bottom: 8px; }

.class-row {
  display: grid; grid-template-columns: 4px minmax(0, 1fr) auto; gap: 12px; align-items: center;
  padding: 11px 0; border-bottom: 1px solid var(--line); text-decoration: none;
}
.class-row:hover { background: var(--soft); }
.class-row:focus-visible { outline-offset: -2px; }
.class-row .row-bar { align-self: stretch; }
.class-main { display: grid; gap: 2px; min-width: 0; }
.class-name { font: 500 16px/1.3 var(--text); overflow-wrap: anywhere; }
.class-next { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.class-next .is-late { color: var(--bad); font-weight: 500; }
.class-grade { display: grid; justify-items: end; gap: 1px; font-size: 13px; white-space: nowrap; }
.class-grade.is-none { color: var(--muted); }
.class-score { font: 500 16px/1.3 var(--text); font-variant-numeric: tabular-nums; }
.class-score b { font-weight: 700; margin-right: 6px; }
.class-row-other > .icon { width: 16px; height: 16px; color: var(--muted); }
.class-row-other .row-bar { background: var(--line); }

.page-tabs { display: flex; gap: 20px; margin-top: 4px; border-bottom: var(--rule) solid var(--line); overflow-x: auto; scrollbar-width: none; }
.page-tabs a { padding: 8px 0 7px; margin-bottom: calc(-1 * var(--rule)); font-size: 15px; color: var(--muted); text-decoration: none; white-space: nowrap; border-bottom: 2.5px solid transparent; }
.page-tabs a:hover { color: var(--ink); }
.page-tabs a[aria-current="page"] { color: var(--ink); font-weight: 700; border-bottom-color: var(--ink); }
.page-tabs small { font: 500 12px var(--mono); color: var(--muted); }
.tab-body > .day:first-child, .tab-body > .posts:first-child { margin-top: 0; }
.tab-body > .empty:first-child { border-bottom: 0; }

.when-two { display: grid; justify-items: end; }
.when-two small { color: var(--muted); }
.row.is-late .when-two small { color: inherit; }

.posts { display: grid; }
.post { display: grid; gap: 4px; padding: 12px 0; border-bottom: 1px solid var(--line); text-decoration: none; }
.post:hover { background: var(--soft); }
.post:focus-visible { outline-offset: -2px; }
.post.is-open, .plain-row.is-open { background: var(--soft); }
.post-head { display: flex; align-items: baseline; gap: 8px; font-size: 13px; color: var(--muted); }
.post-head b { color: var(--ink); font-weight: 500; }
.post-text {
  font-size: 15px; line-height: 1.45; white-space: pre-line; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden;
}
.post-meta { font-size: 13px; color: var(--muted); }
.plain-row { display: grid; gap: 2px; padding: 10px 0; border-bottom: 1px solid var(--line); text-decoration: none; }
.plain-row:hover { background: var(--soft); }
.plain-title { font: 500 16px/1.3 var(--text); overflow-wrap: anywhere; }
.plain-meta { font-size: 13px; color: var(--muted); }

.cats { display: grid; }
.cat { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.cat-name { font-weight: 500; }
.cat-name small, .cat-score small { color: var(--muted); font-weight: 400; }
.cat-score { font-variant-numeric: tabular-nums; text-align: right; }
/* The track is a light step of the fill's own colour. */
.meter { grid-column: 1 / -1; height: 6px; border-radius: 3px; overflow: hidden; background: color-mix(in srgb, var(--c) 16%, var(--paper)); }
.meter i { display: block; height: 100%; border-radius: 3px; background: var(--c); }
.entries { display: grid; }
.entry { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.entry-main { display: grid; gap: 2px; min-width: 0; }
.entry-name { font-weight: 500; overflow-wrap: anywhere; }
.entry-name a { text-decoration: none; }
.entry-name a:hover { text-decoration: underline; }
.entry-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 13px; color: var(--muted); }
.entry-comment { font-size: 14px; padding-left: 10px; border-left: 2px solid var(--line); margin-top: 2px; }
.entry-score { display: grid; justify-items: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
.entry-score small { color: var(--muted); }
.values { margin: 0; padding: 0; list-style: none; }
.values li { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 15px; font-variant-numeric: tabular-nums; }

.signin { max-width: 380px; margin: 0 auto; padding: 18vh var(--gutter) 40px; display: grid; gap: 14px; }
.signin h1 { font: 700 34px/1.05 var(--display); letter-spacing: -0.02em; }
.signin p:not(.brand) { color: var(--muted); }

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

.item { display: grid; gap: 14px; padding: 14px var(--gutter) 32px; }
@media (min-width: 1000px) { .item { padding: 22px 28px 48px; } }
/* The head stays put while a long item scrolls, so × is always in reach. */
.item-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  position: sticky; top: 0; z-index: 2; background: var(--paper);
  margin: -14px calc(-1 * var(--gutter)) 0; padding: 14px var(--gutter) 6px;
}
@media (min-width: 1000px) { .item-head { margin: -22px -28px 0; padding: 22px 28px 6px; } }
.item-kicker { font: 500 12px/1.5 var(--mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); padding-top: 6px; }
.item-class { color: var(--c); font-weight: 700; }
a.item-class { text-decoration: none; }
a.item-class:hover { text-decoration: underline; }
.item-tools { display: flex; flex: none; margin: -8px -10px 0 0; }
.item-tools .close { margin: 0; }
.item-title { font: 700 26px/1.12 var(--display); letter-spacing: -0.015em; overflow-wrap: anywhere; }
.item-sync { margin-top: -6px; font-size: 14px; color: var(--muted); }
.item-sync:empty { display: none; }
.item > .btn-primary { min-height: 48px; font-size: 16px; }
.facts { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 10px 12px; margin: 0; padding-top: 12px; border-top: 1px solid var(--line); }
.facts dt { color: var(--muted); font-size: 14px; padding-top: 1px; }
.facts dd { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; }
.facts dd small { flex-basis: 100%; color: var(--muted); }
.facts dd .prose { flex-basis: 100%; }
.item-sec {
  font: 600 11px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
  padding-top: 12px; border-top: 1px solid var(--line); margin-bottom: -6px;
}
.prose { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 15px; line-height: 1.5; }
.links { display: grid; gap: 6px; }
.links li { display: flex; justify-content: space-between; gap: 10px; font-size: 15px; overflow-wrap: anywhere; }
.links small { color: var(--muted); white-space: nowrap; }
.comments { display: grid; gap: 12px; }
.comments li { display: grid; gap: 2px; font-size: 15px; }
.comments .is-private { padding-left: 10px; border-left: 2px solid var(--accent); }
.comment-head { font-size: 13px; color: var(--muted); }
.comment-head b { color: var(--ink); font-weight: 500; }
.changes-fold { display: grid; gap: 10px; }
.changes-fold > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px; margin-bottom: 0; }
.changes-fold > summary::-webkit-details-marker { display: none; }
.changes-fold > summary:hover { color: var(--ink); }
.changes-fold > summary .icon { width: 13px; height: 13px; }
.changes-fold[open] > summary .icon { transform: rotate(90deg); }
.changes-fold > .link-btn { justify-self: start; }
.changes-status { font-size: 14px; color: var(--muted); }
.changes-status:empty { display: none; }
.changes { display: grid; gap: 8px; }
.changes li { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 15px; }
.changes li > span { display: grid; }
.changes small { color: var(--muted); }
.command { display: grid; gap: 8px; padding-top: 14px; border-top: 1px solid var(--line); }

.panel { display: grid; gap: 10px; padding: 14px; border: var(--rule) solid var(--ink); border-radius: 12px; }
.panel-slot:empty { display: none; }
.panel-label { font: 600 11px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.date-chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 8px; }
.date-chip {
  display: grid; justify-items: start; gap: 1px; padding: 8px 10px; cursor: pointer; text-align: left;
  border: var(--rule) solid var(--line); border-radius: var(--btn-radius); background: var(--paper);
}
.date-chip:hover { border-color: var(--ink); }
.date-chip b { font-weight: 500; }
.date-chip small { color: var(--muted); }
.move-preview { display: grid; gap: 2px; font-size: 15px; min-height: 1.4em; }
.move-preview small { color: var(--muted); }
.is-error { color: var(--bad); }
.pick summary { cursor: pointer; font-size: 14px; color: var(--muted); list-style: none; display: inline-flex; align-items: center; gap: 6px; }
.pick summary::-webkit-details-marker { display: none; }
.pick[open] summary .icon { transform: rotate(90deg); }
.pick .field { margin-top: 8px; }

/* Subtasks (subtasks.js): a box to tick, the title (edited in place), when under it, and at the
   end the grip that drags it, with open and remove beside it on hover with a mouse. On a touch
   screen it swipes like Today's rows, over the same `.under` layers. */
.subtasks { display: grid; gap: 10px; }
.subs { display: grid; margin: 0; padding: 0; list-style: none; }
.sub { position: relative; border-bottom: 1px solid var(--line); background: var(--paper); }
.sub:first-child { border-top: 1px solid var(--line); }
.sub[hidden] { display: none; }
.sub.is-dragging { z-index: 3; box-shadow: 0 6px 22px rgb(0 0 0 / 0.16); border-color: transparent; }
.sub-swipe { position: relative; overflow: hidden; }
.sub-swipe[data-dir="right"] .under-right, .sub-swipe[data-dir="left"] .under-left { display: flex; opacity: 0.55; }
.sub-swipe.is-armed .under { opacity: 1; }
.sub-row {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: start; column-gap: 8px;
  padding: 4px 0; background: var(--paper);
  touch-action: pan-y; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  transition: transform 0.18s ease;
}
.sub-swipe.is-swiping .sub-row { transition: none; }
/* The box to tick, in a target bigger than it. */
.sub-hit { display: grid; place-items: center; width: 44px; height: 44px; margin: -7px -11px 0; cursor: pointer; }
.sub-tick { width: 18px; height: 18px; margin: 0; accent-color: var(--ink); cursor: pointer; }
.sub-main { display: grid; justify-items: start; min-width: 0; }
.sub-title, .sub-edit {
  justify-self: stretch; padding: 4px 6px; margin-left: -6px;
  border: 1px solid transparent; border-radius: 6px; color: var(--ink);
  font: 16px/1.35 var(--text); /* 16px: iOS zooms into smaller inputs */
}
.sub-title { cursor: text; overflow-wrap: anywhere; }
.sub.is-linked .sub-title { cursor: pointer; } /* the platform's: it opens, it isn't renamed */
.sub-edit { width: calc(100% + 6px); background: var(--paper); border-color: var(--ink); outline: none; user-select: text; -webkit-user-select: text; }
.sub.is-done .sub-title { color: var(--muted); text-decoration: line-through; }
.sub.is-skipped .sub-title { color: var(--muted); }
.sub-when {
  padding: 0 6px 6px; margin-left: -6px; border: 0; background: none; cursor: pointer;
  font: 13px/1.4 var(--text); color: var(--muted); text-align: left;
}
.sub-when[aria-expanded="true"] { color: var(--ink); }
.sub-when.is-late { color: var(--bad); }
.sub-btns { display: flex; align-items: center; }
.sub-btns .tool { width: 34px; height: 34px; }
.sub-btns .tool .icon { width: 16px; height: 16px; }
.sub-grip {
  display: grid; place-items: center; width: 40px; height: 40px; margin-right: -8px;
  color: var(--muted); cursor: grab; touch-action: none;
}
.sub-grip .icon { width: 18px; height: 18px; }
.sub.is-dragging .sub-grip { cursor: grabbing; color: var(--ink); }
.sub-hover { display: none; }
@media (hover: hover) and (pointer: fine) {
  .sub-title:hover { background: var(--soft); }
  .sub-when:hover { color: var(--ink); }
  .sub-hover { display: grid; }
  .sub-btns { opacity: 0; }
  .sub-row:hover .sub-btns, .sub-row:focus-within .sub-btns, .sub.is-dragging .sub-btns { opacity: 1; }
}
/* On a touch screen: a bigger box, and room to tap when. */
@media (pointer: coarse) {
  .sub-row { grid-template-columns: 26px minmax(0, 1fr) auto; padding: 6px 0 2px; }
  .sub-hit { margin: -8px -9px 0; }
  .sub-tick { width: 22px; height: 22px; }
  .sub-title { padding-block: 5px; }
  .sub-when { padding-bottom: 10px; font-size: 14px; }
}
.sub-panel { margin: 2px 0 10px; }
.sub-new { display: grid; gap: 8px; }
.sub-add-row { position: relative; display: block; border-radius: 9px; background: var(--paper); }
.sub-add-row .icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--muted); }
.sub-add { position: relative; z-index: 1; padding-left: 36px; background: transparent; }
/* Behind the box, the same text in the same place, invisible but for brackets read as a time.
   Only a background: weight or size would move the text off the box's. */
.sub-add-marks {
  position: absolute; inset: 0; overflow: hidden; pointer-events: none;
  padding: 10px 12px 10px 36px; border: var(--rule) solid transparent;
  font: 16px/1.4 var(--text); white-space: pre; color: transparent;
}
.sub-add-marks mark {
  --m: var(--ink);
  color: transparent; border-radius: 3px;
  background: color-mix(in srgb, var(--m) 9%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--m) 9%, transparent);
  text-decoration: underline 2px var(--m); text-underline-offset: 3px; text-decoration-skip-ink: none;
}
.sub-add-marks mark.is-bad { --m: var(--bad); }
.sub-pick { display: grid; gap: 8px; }
.sub-pick[hidden] { display: none; }
.sub-pick.is-empty .time-chip { color: var(--muted); }
/* Above the box on a touch screen, where the keyboard doesn't cover them. */
@media (pointer: coarse) { .sub-pick { order: -1; } }
.time-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.time-chip {
  display: inline-flex; align-items: baseline; gap: 6px; min-height: 38px; padding: 8px 12px;
  border: var(--rule) solid var(--line); border-radius: var(--btn-radius); background: var(--paper);
  font: 500 15px/1.2 var(--text); color: var(--ink); cursor: pointer; text-align: left;
  touch-action: manipulation;
}
@media (hover: hover) { .time-chip:hover { border-color: var(--ink); } }
.time-chip:active { background: var(--soft); }
.time-chip small { font-size: 13px; font-weight: 400; color: var(--muted); }
.time-chip[hidden] { display: none; }
/* The time Enter uses: the one typed in brackets, else No date. */
.time-chip.is-lit, .sub-pick.is-empty .time-chip.is-lit { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.time-chip.is-lit small { color: inherit; opacity: 0.75; }
.sub-pick.is-empty .time-chip.is-lit { opacity: 0.45; }
@media (pointer: coarse) { .key-hint { display: none; } }
/* How a time typed in brackets reads: a time there isn't, or how something was taken. */
.sub-read { font-size: 13px; line-height: 1.4; color: var(--muted); }
.sub-read[hidden] { display: none; }
.sub-read.is-bad { color: var(--bad); }
.sub-read.is-nudged { animation: nudge 0.3s ease; }
@keyframes nudge { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }
@media (prefers-reduced-motion: reduce) { .sub-read.is-nudged { animation: none; font-weight: 500; } }
/* Taps show as the control's own pressed state, not the browser's grey or blue flash. */
.sub-row, .sub-panel, .sub-new { -webkit-tap-highlight-color: transparent; }
.sub-title:active { background: var(--soft); }
.sub-when:active { color: var(--ink); }
.sub-days { display: grid; gap: 12px; margin-top: 10px; }
.sub-day { display: grid; gap: 6px; }
.sub-day-name { font: 600 11px/1.3 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.sub-day-times { display: flex; flex-wrap: wrap; gap: 6px; }
.sub-day-times small { color: var(--muted); margin-left: 4px; }
.sub-own-row { display: flex; gap: 8px; }
.sub-own-row .field { margin-top: 0; flex: 1; min-width: 0; }

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

.toast-host {
  position: fixed; z-index: 50; left: 50%; bottom: calc(var(--tabs) + 16px + env(safe-area-inset-bottom));
  width: min(440px, calc(100vw - 2 * var(--gutter)));
  transform: translate(-50%, 16px); opacity: 0; pointer-events: none;
  transition: opacity 0.18s, transform 0.18s;
}
.toast-host.is-shown { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }
@media (min-width: 1000px) { .toast-host { bottom: 24px; } }
.toast {
  display: flex; justify-content: space-between; align-items: center; gap: 14px;
  padding: 12px 14px; border-radius: 12px;
  background: var(--ink); color: var(--paper); font-size: 15px;
  box-shadow: 0 6px 24px rgb(0 0 0 / 0.18);
}
.toast.is-error { background: var(--bad); color: #fff; }
.toast-text { display: grid; gap: 2px; }
.toast-text small { opacity: 0.75; }
.toast-act { border: 0; background: none; padding: 6px 2px; cursor: pointer; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; color: inherit; }

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

dialog.sheet {
  width: 100%; max-width: 100%; max-height: 90dvh; margin: auto 0 0;
  padding: 16px var(--gutter) calc(20px + env(safe-area-inset-bottom));
  border: 0; border-top: var(--rule) solid var(--ink); border-radius: 18px 18px 0 0;
  background: var(--paper); color: var(--ink);
}
dialog.sheet[open] { display: grid; gap: 14px; }
dialog.sheet::backdrop { background: var(--scrim); }
@media (min-width: 640px) {
  dialog.sheet { width: 480px; margin: auto; border: var(--rule) solid var(--ink); border-radius: 14px; padding: 22px 26px; }
}
.sheet-head { display: flex; justify-content: space-between; align-items: center; }
.sheet-head h2 { font: 700 26px/1.1 var(--display); letter-spacing: -0.015em; }
.fresh-line { display: flex; align-items: center; gap: 8px; color: var(--muted); }
.fresh-line::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--ok); }
.fresh-line.is-bad { color: var(--bad); }
.fresh-line.is-warn::before { background: var(--warn); }
.fresh-line.is-bad::before { background: var(--bad); }
.fresh-line.is-busy::before { background: var(--ink); animation: pulse 1.2s infinite; }
.src-list { border-top: var(--rule) solid var(--ink); }
.src-row { display: grid; grid-template-columns: 8px minmax(0, 1fr) auto; gap: 12px; align-items: start; padding: 12px 0; border-bottom: 1px solid var(--line); }
.src-row .src-dot { margin-top: 7px; }
.src-row .btn { min-height: 36px; padding: 6px 12px; font-size: 14px; }
.src-main { display: grid; gap: 2px; min-width: 0; }
.src-name { font-weight: 500; }
.src-state { font-size: 14px; }
.src-row.is-bad .src-state { color: var(--bad); }
.src-next { font: 12px var(--mono); color: var(--muted); }
.src-fix { display: grid; gap: 6px; margin-top: 8px; font-size: 14px; justify-items: start; }
.src-fix code { display: block; width: 100%; padding: 8px 10px; background: var(--soft); border-radius: 6px; overflow-wrap: anywhere; }
.src-note { font-size: 14px; color: var(--muted); }
.sources .more-links { font-size: 15px; }

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