:root {
  --bg: #fbfaf8;
  --fg: #1c1b19;
  --muted: #6b6862;
  --line: #e3ded6;
  --accent: #8a5a2b;
  --danger: #a11;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 1rem;
  font: 17px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--fg);
  background: var(--bg);
  max-width: 40rem;
  margin-inline: auto;
}

h1 { font-size: 1.5rem; margin: 0 0 0.5rem; }
h2 { font-size: 1.1rem; margin: 1.5rem 0 0.5rem; color: var(--muted); }

nav.crumbs { font-size: 1rem; color: var(--muted); margin-bottom: 1rem; }
nav.crumbs a {
  display: inline-block;
  padding: 0.625rem 0.375rem;
  min-height: 44px;
  color: var(--muted);
}
nav.crumbs span { padding: 0 0.25rem; }

/* The one nav every screen shares, above its <h1>. Same tap-target pattern as
   nav.crumbs above; the difference is the current page, which renders as
   plain text rather than a link to itself. */
nav.sitenav {
  font-size: 1rem;
  color: var(--muted);
  margin-bottom: 1rem;
  padding-bottom: 0.25rem;
  border-bottom: 1px solid var(--line);
}
nav.sitenav a,
nav.sitenav span[aria-current] {
  display: inline-block;
  padding: 0.625rem 0.375rem;
  min-height: 44px;
  color: var(--muted);
}
nav.sitenav span[aria-current] {
  color: var(--fg);
  font-weight: 600;
}
nav.sitenav span.sep { padding: 0 0.25rem; }

ul.locations { list-style: none; margin: 0; padding: 0; }
ul.locations li { border-bottom: 1px solid var(--line); }
ul.locations a {
  display: block;
  padding: 0.85rem 0.25rem;
  min-height: 44px;
  text-decoration: none;
  color: var(--fg);
}

/* Three sentences at three altitudes. What is kept here is the one you scan for,
   so it stays at body colour; what the place is, and any generated summary, sit
   back in muted grey. */
.theme, .about, .hint { color: var(--muted); font-size: 1rem; margin: 0.25rem 0 0.5rem; }
p.holds { margin: 0.25rem 0 0.5rem; }
p.holds + .theme, p.about + p.holds { margin-top: 0; }

/* Inside the child list, what a child holds sits under its name rather than
   beside it: twenty-three shelves of "rice, pasta, flour" would otherwise wrap
   mid-list and lose the column of names you are scanning down. */
ul.locations .holds {
  display: block;
  color: var(--muted);
  font-size: 0.95rem;
  margin-top: 0.15rem;
}
/* A box row carries a control as well as a link, so the row becomes a strip: the
   link takes the space it can and the × sits at the end, still its own 44px
   target. Without this the form would drop onto a line of its own. */
ul.locations.movables li { display: flex; align-items: center; gap: 0.5rem; }

/* Naming photographs: the picture beside the field you name it in, big enough
   on a phone to tell one item from another. Formerly shared with the add
   screen's naming-at-capture flow (deleted once capture stopped asking for
   names); still load-bearing here, since /unnamed's list uses the same class. */
ul.locations.naming li { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0; }
ul.locations.naming li img {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 6px;
  flex: none;
}
ul.locations.naming li input { margin: 0; }

/* Standing in for a photograph that was never taken, so the row still has
   something to be recognised by — its number. */
ul.locations.naming .nophoto {
  width: 72px;
  flex: none;
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
}
ul.locations.movables li a { flex: 1; }
ul.locations.movables li form { margin: 0; }
/* A menu that reads as a button. The options are sentences, but closed it is one
   red × at the end of the row: appearance:none drops the native arrow, and
   text-align-last centres the selected option, which plain text-align does not
   do inside a select. Still a real <select>, so a phone opens its native picker
   on tap and no JavaScript is needed to draw a menu. */
ul.locations.movables li select {
  appearance: none;
  -webkit-appearance: none;
  width: 44px;
  min-height: 44px;
  margin: 0;
  padding: 0;
  text-align: center;
  text-align-last: center;
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--danger);
  font-size: 1.3rem;
  line-height: 1;
}
ul.locations.movables li button { min-height: 44px; margin: 0 0 0 0.25rem; }

/* Inside the row's own link, so tapping the picture goes where tapping the name
   goes. Fixed size, and absent entirely when there is no photograph. Scoped to
   .movables, which is the only list that renders it — Rows (fixed places) was
   deliberately left out of this task, and a broader selector would have it
   silently inherit float and sizing if Rows ever grew one of its own. */
ul.locations.movables img.rowthumb {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 4px;
  float: left;
  margin-right: 0.6rem;
}

/* The description is a block beside a float, which would otherwise wrap around
   the picture and stay indented after it ends. Its own formatting context makes
   it a column beside the image instead — the name above it already sits there,
   so the two line up. */
ul.locations.movables li a .holds { overflow: hidden; }

/* The only way into the forms, so it takes a real tap target rather than the
   0-height text link `linkish` gives a secondary control sitting mid-form. */
p.edit { margin: 0.5rem 0 1.5rem; }
p.edit button.linkish { min-height: 44px; padding: 0.625rem 0; }

/* One target, at the end of what is already here, sized for a thumb. */
p.add { margin: 0.75rem 0 1.5rem; }
a.plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 1.5rem;
  line-height: 1;
  text-decoration: none;
  color: var(--fg);
}

.photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.5rem; }
.photos img { width: 100%; height: auto; border-radius: 6px; display: block; }

.photos figure.photo { margin: 0; }
/* The link wrapping a thumbnail is inline by default, which leaves it narrower
   than the picture it holds and mis-sizes the tap target. */
.photos figure.photo a { display: block; }
.photos figure.photo form { margin: 0; }
.photos figure.photo button { margin-top: 0.25rem; font-size: 1rem; }

.empty { color: var(--muted); font-style: italic; }
.error { color: var(--danger); font-weight: 600; }
/* A batch upload can fail on more than one photo, so the failures are a list
   and each names the file it is about. No bullets: at one item, which is the
   common case, a bullet reads as the start of a list that never arrives. */
ul.error { list-style: none; margin: 0.5rem 0 0; padding: 0; }
.message { color: var(--accent); font-weight: 600; }

label { display: block; margin: 1rem 0 0.25rem; font-weight: 600; }
input, select, textarea, button {
  font: inherit;
  width: 100%;
  padding: 0.7rem;
  min-height: 44px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
}
button {
  background: var(--accent);
  color: #fff;
  border: none;
  font-weight: 600;
  margin-top: 1rem;
}

/* A button that does something other than finish the screen — `Add them all
   without naming`, `Back to the paste`, a box to move here. It was written as a
   class the stylesheet never defined, so all of them drew as the filled block
   above and every screen ended up with several things that looked like the one
   thing to tap. A link is what the markup meant, so a link is what it gets.
   Still a real button: it acts on the page rather than going anywhere. */
button.linkish {
  background: none;
  color: var(--accent);
  width: auto;
  min-height: 0;
  padding: 0;
  text-align: left;
  text-decoration: underline;
  font-weight: 400;
  margin-top: 0;
}

/* A label styled as the button for a hidden file input, so the wording can say
   "Take a photo" rather than the browser's own "Choose file". Same 44px target
   and 16px+ text as a real button. */
.filebutton {
  display: block;
  width: 100%;
  padding: 0.7rem;
  min-height: 44px;
  box-sizing: border-box;
  border-radius: 6px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  text-align: center;
  margin-top: 1rem;
  cursor: pointer;
}

/* The strip of what has been photographed so far. Small, because it is a
   record that the shot was taken rather than something to look at — the
   photograph itself gets looked at on /unnamed, next to its name. */
ul.strip { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
ul.strip li { position: relative; width: 72px; }
ul.strip li img {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 6px;
  display: block;
}
/* Still on its way up: dimmed, so the strip says what is finished without a
   spinner per thumbnail. */
ul.strip li.sending img { opacity: 0.5; }
ul.strip li.failed img { outline: 2px solid var(--danger); }
ul.strip li .error { font-size: 0.8rem; }

/* The viewfinder fills the width and keeps its own aspect; `cover` rather than
   `contain` so there are no letterbox bars to mistake for the frame edge. */
video.viewfinder {
  width: 100%;
  max-height: 60vh;
  object-fit: cover;
  border-radius: 6px;
  background: #000;
  display: block;
}
/* A round shutter, thumb-sized, under the frame it takes. */
button.shutter {
  display: block;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  font-size: 1.5rem;
  margin: 1rem auto;
}

/* Reachable by the label and by assistive tech, but not drawn. Not
   display:none, which would take it out of the accessibility tree. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
textarea { min-height: 12rem; font-family: ui-monospace, monospace; }

/* A sentence, not a pasted outline: prose font, and short enough that the Save
   button stays on screen with the keyboard up. */
textarea.brief {
  min-height: 4.5rem;
  font-family: inherit;
}

.itemcontrols { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.itemcontrols input[type="search"] { flex: 1 1 12rem; font-size: 1rem; padding: 0.5rem; }

/* The global input/select/button rule below makes every control a full-width
   44px bar, which is right for a form filled in one field at a time but wrong
   for a row of controls sitting side by side. The select sizes to its own
   text, and the checkbox and its label go back to looking like a checkbox
   rather than a stretched bordered box fighting `label { display: block; }`. */
.itemcontrols select {
  width: auto;
  min-height: auto;
  padding: 0.4rem 1.6rem 0.4rem 0.5rem;
}
.itemcontrols label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-weight: 400;
}
.itemcontrols input[type="checkbox"] {
  width: 1.2rem;
  min-height: 0;
  padding: 0;
}

.count { color: var(--muted); font-size: 0.9rem; }
table.items { width: 100%; border-collapse: collapse; }
table.items td, table.items th { text-align: left; padding: 0.5rem 0.5rem 0.5rem 0; vertical-align: top; }

/* A thumbnail column that stays out of the way of the names: fixed width, and
   nothing at all when a row has no photograph. */
table.items td.thumb, table.items th.thumb { width: 48px; padding-right: 0.5rem; }
table.items td.thumb img { width: 48px; height: 48px; object-fit: cover; border-radius: 4px; display: block; }

/* A four-column table is unreadable on a phone, which is where this is used:
   each row becomes a thumbnail beside two lines, name over place, and the
   About column is dropped rather than wrapped into a third. */
@media (max-width: 34rem) {
  table.items thead { display: none; }
  table.items, table.items tbody, table.items tr, table.items td { display: block; }
  table.items tr { padding: 0.6rem 0; border-bottom: 1px solid var(--line); }
  table.items td { padding: 0; }
  table.items td.about { display: none; }
  table.items td.thumb { float: left; margin-right: 0.6rem; }
  table.items td.where { font-size: 0.85rem; }
}

/* The Find screen. Phone-first: one big box, one big answer. The global
   input/select/button rule below already makes every control full-width —
   this only makes the input itself the largest thing on the screen, and
   leaves the Ask button as the secondary path since Enter already submits. */
.findbox {
  margin-bottom: 1rem;
}
.findbox input {
  font-size: 1.5rem;
  padding: 1rem;
  min-height: 3.5rem;
}
/* No rule elsewhere gives an input a visible focus ring, but a hero control
   needs one. Outline only, so focus never shifts the layout. */
.findbox input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.findbox button {
  font-size: 1.125rem;
  min-height: 3rem;
}
/* Two trees, one set of rules: the answer to a question and the house itself
   fold the same way, so the fold is a gesture you learn once. What differs is
   what hangs off them, and that is further down under each name. */
.answers,
.answers ul,
.places,
.places ul {
  list-style: none;
  padding: 0;
}
/* A branch is one line — the twist and the room's name — with its own list
   hanging under it. The rule down the left is what makes a fold visible as a
   fold: the line stops where the branch does. */
.answers li.branch,
.places li.branch {
  display: block;
}
.answers li.branch > ul,
.places li.branch > ul {
  margin: 0 0 0 1.35rem;
  padding-left: 0.9rem;
  border-left: 1px solid var(--line);
}
.answers li.branch > a {
  display: inline;
  font-size: 1rem;
  font-weight: 600;
}
/* Small to look at, 44px to hit: this is pressed with a thumb, and it sits
   beside a link that goes somewhere else entirely. */
.answers button.twist,
.places button.twist {
  width: 44px;
  height: 44px;
  min-height: 44px;
  margin: 0 0.1rem 0 0;
  padding: 0;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--muted);
  background: none;
  border: none;
}
.answers li.leaf {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--line);
}
.answers li.leaf > div {
  flex: 1;
  min-width: 0;
}
.answers .thumb {
  flex: none;
  width: 4rem;
  height: 4rem;
  object-fit: cover;
  border-radius: 4px;
}
.answers li.leaf a {
  font-size: 1.15rem;
  display: block;
}
/* The catalogue's own words, told apart from the model's account of them: the
   reason is a guess in italics, the matched text is a fact. */
.answers .matched {
  display: block;
  color: var(--muted);
}
.answers .reason {
  display: block;
  font-style: italic;
  opacity: 0.75;
}
/* Every row in the house tree is a place, so the name is the row: no leaf and
   branch to tell apart, and nothing under the name. */
.places a {
  display: inline-block;
  padding: 0.7rem 0;
  font-size: 1.0625rem;
  text-decoration: none;
  color: var(--fg);
}
/* A place with nothing inside it has no twist, so its name would sit 44px to
   the left of its siblings' unless it is pushed across to meet them. */
.places li:not(.branch) > a {
  margin-left: calc(44px + 0.1rem);
}
.filtered ul {
  list-style: none;
  padding: 0;
  opacity: 0.7;
}
.guess {
  font-size: 0.9rem;
  opacity: 0.7;
}
/* A session's trail is dense, monospaced, and read on a phone as often as not,
   so it scrolls sideways inside itself rather than widening the page. */
.diagnostics {
  list-style: none;
  padding: 0;
}
.diagnostics > li {
  padding: 0.6rem 0;
  border-bottom: 1px solid #ddd;
}
.diagnostics > li.died {
  border-left: 3px solid #b00;
  padding-left: 0.6rem;
}
.trail {
  font-size: 0.8rem;
  line-height: 1.5;
  overflow-x: auto;
}
.trail pre {
  margin: 0.15rem 0 0.4rem;
  white-space: pre-wrap;
  word-break: break-all;
  opacity: 0.75;
}
