/*
 * Shiro: the button that is always there, and the panel it opens.
 *
 * Her own palette throughout (`--surface`, `--text`, `--line`, `--primary`), so it turns dark with
 * the rest of the app. The first version invented its own fallbacks and came out a white card
 * floating in her dark world.
 *
 * Written for the phone first, because that is where she actually uses it — standing at the pantry
 * with one hand. Four things that only matter on a phone:
 *
 * - **It sits above the tab bar**, not on top of it, and above the home bar on a phone with no
 *   button (`safe-area-inset-bottom`). A floating thing that covers a tab is a floating thing she
 *   has to fight.
 * - **The tap target is 56px.** Smaller reads fine and misses often.
 * - **The panel is capped at 72vh and its own text box stays visible**, so the on-screen keyboard
 *   cannot push the thing she is typing off the screen.
 * - **It scrolls on its own** (`overscroll-behavior: contain`), so flicking the conversation does
 *   not drag the page behind it.
 */

.shiro-bubble {
  position: fixed;
  right: 14px;
  bottom: calc(var(--tabbar-h, 64px) + 14px + env(safe-area-inset-bottom, 0px));
  width: 56px;
  height: 56px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  /*
   * A light plate, in both worlds, and NOT `--surface`.
   *
   * The mark is a white dog drawn in dark ink. On her dark surface the ink disappeared into the
   * button and all that was left was a faint pale smudge — it read as switched off. A logo badge
   * carries its own background for exactly this reason.
   */
  background: #fdf8f1;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 60;
  transition: transform 0.12s ease;
}
.shiro-bubble:active { transform: scale(0.92); }
.shiro-bubble img { width: 42px; height: 42px; display: block; pointer-events: none; -webkit-user-drag: none; }
/* She can drag it (features/shiro/bubble.js): the page must not scroll under her finger while she does. */
.shiro-bubble { touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.shiro-bubble.is-dragging { transform: scale(1.08); transition: none; cursor: grabbing; box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5); }

.shiro-panel {
  position: fixed;
  right: 10px;
  left: 10px;
  bottom: calc(var(--tabbar-h, 64px) + 10px + env(safe-area-inset-bottom, 0px));
  max-width: 460px;
  margin-inline: auto;
  max-height: 72vh;
  display: none;
  flex-direction: column;
  background: var(--surface);
  color: var(--text);
  border-radius: 18px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
  z-index: 70;
  overflow: hidden;
}
.shiro-panel.is-open { display: flex; }

.shiro-top {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
}
.shiro-top img {
  width: 26px;
  height: 26px;
  background: #fdf8f1;       /* the same plate, for the same reason */
  border-radius: 50%;
  padding: 1px;
}
.shiro-top strong { flex: 1; }
.shiro-x { background: none; border: 0; padding: 6px; cursor: pointer; color: inherit; opacity: 0.6; }

.shiro-talk {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.shiro-her,
.shiro-said {
  max-width: 85%;
  padding: 8px 11px;
  border-radius: 14px;
  white-space: pre-wrap;
  line-height: 1.35;
}
.shiro-her {
  align-self: flex-end;
  background: var(--primary);
  color: var(--on-primary);
}
.shiro-said {
  align-self: flex-start;
  background: var(--surface-2);
}
.shiro-said.is-soft { opacity: 0.65; font-style: italic; }

/*
 * The short replies Shiro offers at the end of a turn. Tapping one sends it.
 *
 * They wrap rather than scroll: two of them, each at most thirty characters, and a row that
 * scrolls sideways on a phone hides the second one exactly when it matters.
 */
.shiro-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding-top: 2px;
}
.shiro-chip {
  border: 1px solid var(--primary);
  background: transparent;
  color: var(--primary);
  border-radius: 999px;
  padding: 7px 13px;
  font: inherit;
  font-size: 0.92em;
  cursor: pointer;
  /* A comfortable thumb target without making them look like the send button. */
  min-height: 36px;
}
.shiro-chip:active { background: var(--surface-2); }

/* The photos waiting for her next message, with a way to take them back. */
.shiro-pending {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 4px 8px 0 12px;
  font-size: var(--t-small);
  color: var(--muted);
}

.shiro-ask {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px;
  border-top: 1px solid var(--line);
}
.shiro-camera {
  font-size: 20px;
  line-height: 1;
  padding: 8px;
  cursor: pointer;
  border-radius: 10px;
}
.shiro-say {
  flex: 1;
  min-width: 0;
  border: 0;
  background: var(--surface-2);
  color: inherit;
  border-radius: 12px;
  padding: 11px 12px;
  /* 16px or iOS zooms the whole page in when she taps it, and never quite zooms back out. */
  font-size: 16px;
}
.shiro-go {
  border: 0;
  background: var(--primary);
  color: var(--on-primary);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  cursor: pointer;
}

/*
 * Talking to Shiro (house D118).
 *
 * The mic sits between the box and Send, the same size as Send but quiet (her surface, not her
 * primary), so the one strong button is still Send. While she talks it turns primary and grows a
 * ring that follows her voice (`--level`, 0..1, set as she speaks); with reduced motion the ring
 * stays still - the words "Listening…" above the box are the signal, the ring only an extra.
 */
.shiro-mic {
  flex: none;
  border: 0;
  background: var(--surface-2);
  color: inherit;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  cursor: pointer;
  --level: 0;
  transition: box-shadow 0.08s linear, background 0.15s ease;
}
.shiro-mic svg { width: 20px; height: 20px; }
.shiro-mic.is-on {
  background: var(--primary);
  color: var(--on-primary);
  box-shadow: 0 0 0 calc(3px + var(--level) * 9px) color-mix(in srgb, var(--primary) 22%, transparent);
}
.shiro-mic.is-writing { opacity: 0.7; }
.shiro-say[readonly] { color: var(--muted); }

/* What is happening while she talks, in words, just above the box. */
.shiro-hearing {
  padding: 6px 12px 0;
  font-size: var(--t-small);
  color: var(--muted);
}
/* No way to listen in this browser: said once, quietly, under the box. */
.shiro-voice-note {
  margin: 0;
  padding: 0 12px 8px;
  font-size: var(--t-small);
  color: var(--muted);
}

/* A small mic on what she said out loud. */
.shiro-spoke { display: inline-flex; vertical-align: -1px; margin-right: 4px; opacity: 0.75; }

/* Shiro saying its answer: what is happening, and Stop. */
.shiro-speaking {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--t-small);
  color: var(--muted);
}
.shiro-hush { display: inline-flex; align-items: center; gap: 5px; min-height: 32px; padding: 4px 11px; }

@media (prefers-reduced-motion: reduce) {
  .shiro-mic { transition: none; }
  .shiro-mic.is-on { box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 22%, transparent); }
}

/* Wide enough for a laptop: sit in the corner rather than stretching across the whole window. */
@media (min-width: 720px) {
  .shiro-panel { left: auto; width: 420px; bottom: 90px; right: 18px; }
  .shiro-bubble { right: 18px; bottom: 22px; }
}

/*
 * Something is happening, and it has to look like it.
 *
 * This was a static "…" at 65% opacity, italic. Correct, and perfectly easy to miss on a phone —
 * especially in the few seconds before the words arrive, which is exactly when she is looking for
 * a sign that the thing she just asked for is being done. Lekhaj, 2026-09-21: *"it said i am
 * checking but it did not send back message until i asked it again. no loading indicator"*.
 *
 * Three dots that move. Not because the old one was wrong, but because a thing that does not move
 * does not read as "working" next to a bubble of text that also does not move.
 */
.shiro-typing {
  display: flex;
  gap: 4px;
  align-items: center;
  min-height: 19px;
}
.shiro-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.3;
  animation: shiro-working 1.2s infinite ease-in-out;
}
.shiro-typing span:nth-child(2) { animation-delay: 0.16s; }
.shiro-typing span:nth-child(3) { animation-delay: 0.32s; }
@keyframes shiro-working {
  0%, 75%, 100% { opacity: 0.25; transform: translateY(0); }
  35% { opacity: 0.9; transform: translateY(-3px); }
}
/* Her app's own rule everywhere else: motion is an extra, never the only signal. */
@media (prefers-reduced-motion: reduce) {
  .shiro-typing span { animation: none; opacity: 0.6; }
}

/*
 * The whole conversation, on its own page (#/talks).
 *
 * Deliberately the panel's bubbles at the panel's sizes: it is the same conversation, and reading
 * it back should not feel like a different app. Wider, because a page is not a sheet.
 */
.talks {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 0 8px;
}
.talk-day {
  align-self: center;
  margin: 14px 0 4px;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.55;
}
.talk-row {
  display: flex;
  flex-direction: column;
  max-width: 88%;
}
.talk-row.is-hers { align-self: flex-end; align-items: flex-end; }
.talk-row.is-shiro { align-self: flex-start; align-items: flex-start; }
.talk-bubble {
  padding: 8px 11px;
  border-radius: 14px;
  white-space: pre-wrap;
  line-height: 1.35;
  background: var(--surface-2);
}
.is-hers .talk-bubble {
  background: var(--primary);
  color: var(--on-primary);
}
.talk-when {
  margin: 2px 4px 0;
  font-size: 0.72rem;
  opacity: 0.5;
}

/* Which conversation the panel is in, beside its name. Absent = General. */
.shiro-topic {
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 0.78rem;
  font-weight: 500;
  max-width: 45%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.talk-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: 14px 0 4px;
}

/*
 * Something Shiro would like to remember (house C167), under the answer that noticed it. Dashed,
 * because it is a question and not something already done; the buttons are the chips' own, so
 * the panel has one kind of thing to press.
 */
.shiro-offer {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: transparent;
  border: 1px dashed var(--primary);
  white-space: normal;
}
.shiro-offer-buttons { display: flex; flex-wrap: wrap; gap: 6px; }

/* What Shiro knows (#/memory). Rows wrap on the Fold's cover screen rather than squeezing the words. */
.mem-switch { margin-bottom: var(--s3); }
.mem-head { margin: var(--s4) 4px var(--s2); }
.mem-row { flex-wrap: wrap; }
.mem-row .grow { display: flex; flex-direction: column; gap: 2px; min-width: 60%; }
.mem-buttons { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.mem-undo { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s3); }

/*
 * How deep Shiro goes (house D120, D123, D124): Quick, Think, Research.
 *
 * **The chip sits just above the message box, at its left edge.** Beside it in the same row there is no room on
 * the Fold's cover screen: the camera, the box, the mic and Send already share 350px, and a chip there would leave
 * her about thirteen characters to type in. Above the box it is also above the mic while she talks, with what is
 * happening ("Listening…") in words beside it. Small and quiet on Quick - the ordinary case should not shout - and
 * tinted once she has chosen to go deeper, so the depth a chat is on is seen at a glance.
 */
.shiro-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px 0;
  min-height: 34px;
  /* It belongs to the box below it, not to the talk above: the line that used to sit on the box sits on this. */
  border-top: 1px solid var(--line);
}
.shiro-bar + .shiro-ask { border-top: 0; padding-top: 6px; }
.shiro-bar .shiro-hearing { padding: 0; min-width: 0; }
.shiro-depth {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* A comfortable thumb target for something tapped now and then, without looking like a button to press first. */
  min-height: 30px;
  padding: 3px 9px 3px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
}
.shiro-depth:active { transform: scale(0.96); }
.shiro-depth.is-think,
.shiro-depth.is-research {
  --tone: var(--job-new);
  border-color: color-mix(in srgb, var(--tone) 45%, transparent);
  background: color-mix(in srgb, var(--tone) 13%, var(--surface));
  color: color-mix(in srgb, var(--tone) 80%, var(--text));
}
.shiro-depth.is-research { --tone: var(--job-sky); }

/* The sheet: the three, one line each; the one this chat is on is marked. */
.depth-sheet { display: flex; flex-direction: column; gap: var(--s3); }
.depth-sheet h2 { margin: 0; }
.depth-list { box-shadow: none; border: 1px solid var(--line); }
.depth-row { align-items: flex-start; }
.depth-row .small { line-height: 1.35; }
.depth-row.is-on { background: color-mix(in srgb, var(--job-new) 7%, var(--surface)); }
.depth-row > .i, .depth-pill { align-self: center; }
.depth-pill { background: color-mix(in srgb, var(--job-new) 18%, var(--surface)); color: color-mix(in srgb, var(--job-new) 78%, var(--text)); }

/*
 * "Think it through" / "Research it": home's offer to answer the same question one deeper. Filled with the depth's
 * own colour and carrying its icon, so it is not one more outlined chip among the short replies - it does something
 * different. Tinted from her surface rather than a solid colour with white on it, which washed out in the dark worlds.
 */
.shiro-deeper {
  --tone: var(--job-new);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 7px 14px 7px 11px;
  border: 1px solid color-mix(in srgb, var(--tone) 55%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--tone) 22%, var(--surface));
  color: color-mix(in srgb, var(--tone) 72%, var(--text));
  font: inherit;
  font-size: 0.92em;
  font-weight: 800;
  cursor: pointer;
}
.shiro-deeper.is-research { --tone: var(--job-sky); }
.shiro-deeper:active { transform: scale(0.96); }

/* A Think turn on its way: its own words where the answer will be, the dots beside them. */
.shiro-thinking { display: flex; flex-direction: column; gap: 2px; white-space: normal; }
.shiro-thinking-top { display: flex; align-items: center; gap: 6px; color: color-mix(in srgb, var(--job-new) 78%, var(--text)); }
.shiro-thinking .shiro-typing { margin-left: 2px; }

/* One quiet line under an answer: Think came from the other model. */
.shiro-note {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 5px;
  margin: -2px 4px 0;
  font-size: 0.78rem;
  color: var(--muted);
}

/* "Researching heat pumps…" under the answer that started it, with a bar that moves while home is at it. */
.shiro-research {
  align-self: flex-start;
  /* Never squeezed by the talk above it: `overflow: hidden` (for the bar) would otherwise let the column shrink it flat. */
  flex: none;
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  max-width: 85%;
  padding: 6px 11px 9px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--job-sky) 9%, var(--surface));
  color: color-mix(in srgb, var(--job-sky) 70%, var(--text));
  font-size: var(--t-small);
  overflow: hidden;
}
.shiro-research .shiro-working-bar { position: absolute; left: 0; right: 0; bottom: 0; border-radius: 0; }
.shiro-working-bar {
  display: block;
  height: 3px;
  border-radius: 99px;
  background: color-mix(in srgb, var(--job-sky) 18%, transparent);
  overflow: hidden;
}
.shiro-working-bar::after {
  content: '';
  display: block;
  width: 38%;
  height: 100%;
  border-radius: inherit;
  background: var(--job-sky);
  animation: shiro-bar 1.6s infinite ease-in-out;
}
@keyframes shiro-bar {
  from { transform: translateX(-100%); }
  to { transform: translateX(265%); }
}

/*
 * A research document, as a card in the chat (panel and Talks): what it is, one line of what it found, how long
 * a read - and Read it. It reads as a thing to open, not as one more bubble of talk.
 */
.doc-card {
  align-self: flex-start;
  flex: none;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 10px;
  max-width: 92%;
  padding: 11px 12px;
  border: 1px solid color-mix(in srgb, var(--job-sky) 32%, var(--line));
  border-radius: 14px;
  background: var(--surface);
  white-space: normal;
}
.doc-card-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.doc-card-words strong { line-height: 1.25; }
.doc-card-summary { font-size: var(--t-small); line-height: 1.35; }
.doc-card-read { grid-column: 1 / -1; justify-self: start; }
.talk-row .doc-card { max-width: 100%; margin-top: 4px; }
.talk-row .shiro-note { margin-top: 2px; }

/*
 * The reading view (#/note/<id>): a note from home as a page. The whole screen and no tab bar; a measure that is
 * comfortable on a phone and does not run the width of a laptop; her own colours, so it turns dark with the app.
 */
.read-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.read { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s2) 2px var(--s4); }
.read h1 { overflow-wrap: anywhere; }
.read-by { margin-bottom: var(--s2); }
.read-card { display: flex; flex-direction: column; gap: var(--s2); }
.md { font-size: 17px; line-height: 1.62; overflow-wrap: anywhere; }
.md > * + * { margin-top: 0.85em; }
.md h2, .md h3, .md h4, .md h5, .md h6 { margin-top: 1.5em; line-height: 1.25; letter-spacing: -0.01em; }
/* A document opens on a heading ("Short answer"): no heading's gap between the note's title and its first words. */
.md > :first-child { margin-top: 0; }
.md h2 { font-size: 1.3em; }
.md h3 { font-size: 1.12em; }
.md h4, .md h5, .md h6 { font-size: 1em; }
.md p { margin-bottom: 0; }
.md ul, .md ol { margin-bottom: 0; padding-left: 1.35em; display: flex; flex-direction: column; gap: 0.4em; }
.md li { padding-left: 2px; }
.md li.md-tick { list-style: none; margin-left: -1.35em; display: flex; gap: 8px; }
.md li.md-tick.is-done { color: var(--muted); }
.md-box { flex: none; }
.md a {
  color: color-mix(in srgb, var(--job-sky) 78%, var(--text));
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
.md code { font: 0.9em ui-monospace, Consolas, monospace; padding: 1px 5px; border-radius: 6px; background: var(--surface-2); }
.md pre { margin-bottom: 0; padding: var(--s3); border-radius: var(--r-sm); background: var(--surface-2); overflow-x: auto; }
.md pre code { padding: 0; background: none; }
.md blockquote { margin: 0.85em 0 0; padding: 2px 0 2px var(--s3); border-left: 3px solid var(--line); color: var(--muted); }
.md blockquote > :first-child { margin-top: 0; }
.md hr { border: 0; border-top: 1px solid var(--line); margin-bottom: 0; }
.md-file { color: var(--muted); font-style: italic; }
/* On a laptop the page is 920px wide, which is far too long a line to read: the note keeps a book's measure. */
@media (min-width: 720px) {
  .read-head, .read { max-width: 680px; width: 100%; margin-left: auto; margin-right: auto; }
}
/* Editing it: the words as she would type them, with room to see a few paragraphs at once. */
.read-editor { width: 100%; min-height: 38dvh; line-height: 1.5; }

/* Something home says is still running, in the bell: a bar that moves under its words. */
.notice.is-working .shiro-working-bar { margin-top: -2px; }

@media (prefers-reduced-motion: reduce) {
  .shiro-working-bar::after { animation: none; width: 100%; opacity: 0.45; }
  .shiro-depth:active, .shiro-deeper:active { transform: none; }
}
