/* =============================================================================
   JJHA Family Ops — design system
   =============================================================================
   Deliberately not a SaaS admin dashboard. This is read by a household staff
   of six across four properties, often on a phone, often mid-task. It should
   feel like a well-kept house: calm, legible, unhurried, nothing shouting.

   Warm neutrals rather than the usual cool greys, generous whitespace, one
   restrained accent, and a serif for headings to keep it from reading as
   software.
   ========================================================================== */

:root {
  --ink:            #1c1a17;
  --ink-soft:       #56504a;
  --ink-faint:      #8a827a;
  --paper:          #faf8f5;
  --paper-raised:   #ffffff;
  --line:           #e6e0d8;
  --line-soft:      #f0ebe4;
  --accent:         #2c5f8a;
  --accent-soft:    #eaf1f7;
  --warn:           #9a5b25;
  --warn-soft:      #fbf1e7;
  --good:           #3d6b4a;
  --good-soft:      #edf3ee;

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
           Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  --radius: 10px;
  --shadow: 0 1px 2px rgba(28, 26, 23, 0.04),
            0 4px 16px rgba(28, 26, 23, 0.04);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--ink);
  line-height: 1.55;
  font-size: 15px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

a { color: inherit; text-decoration: none; }

/* ---------- masthead ---------- */

.masthead {
  border-bottom: 1px solid var(--line);
  background: var(--paper-raised);
  position: sticky;
  top: 0;
  z-index: 20;
}

.masthead-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 24px;
  height: 62px;
  display: flex;
  align-items: center;
  gap: 28px;
}

.wordmark {
  font-family: var(--serif);
  font-size: 1.16rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.wordmark span { color: var(--ink-faint); font-style: italic; }

.nav { display: flex; gap: 4px; flex: 1; align-items: center; }
.nav::-webkit-scrollbar { display: none; }

.nav a {
  padding: 7px 12px;
  border-radius: 7px;
  font-size: 0.875rem;
  color: var(--ink-soft);
  white-space: nowrap;
  transition: background 0.12s, color 0.12s;
}
.nav a:hover { background: var(--line-soft); color: var(--ink); }
.nav a.active { background: var(--accent-soft); color: var(--accent); font-weight: 500; }

/* ---------- grouped nav ----------
   No JavaScript: the menu opens on hover and on keyboard focus anywhere
   inside the group, which covers pointer and tab. `overflow-x: auto` on .nav
   would clip an absolutely positioned menu, so the scroll behaviour moves to
   a wrapper and .nav itself is allowed to overflow visibly.

   The group label is a real link to the section's main page. A menu is a
   shortcut, never the only route: hover fails on touch, and a pointer that
   leaves by two pixels should not strand anyone. */

.navgroup { position: relative; display: inline-block; }
.navgroup > a { display: inline-flex; align-items: center; gap: 4px; }
.navgroup .caret { font-size: 0.65em; opacity: 0.55; }

.navmenu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 208px;
  padding: 6px;
  background: var(--bg-raised, #fff);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.12);
  display: none;
  z-index: 40;
}

.navgroup:hover .navmenu,
.navgroup:focus-within .navmenu { display: block; }

.navsep { height: 1px; background: var(--line-soft); margin: 5px 8px; }

.navmenu a {
  display: block;
  padding: 7px 10px;
  border-radius: 6px;
  font-size: 0.85rem;
  white-space: nowrap;
}

/* A hover bridge. Without it the 6px gap between the label and the menu is a
   dead room that closes the menu on the way down. */
.navgroup::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 8px;
}

.who { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
.who img { width: 27px; height: 27px; border-radius: 50%; }
.who-name { font-size: 0.83rem; color: var(--ink-soft); }
.who a { font-size: 0.8rem; color: var(--ink-faint); }
.who a:hover { color: var(--ink); }

/* ---------- layout ---------- */

.wrap { max-width: 1180px; margin: 0 auto; padding: 36px 24px 72px; width: 100%; flex: 1; }

.page-head { margin-bottom: 28px; }
.page-head h1 {
  font-family: var(--serif);
  font-size: 1.95rem;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.page-head .sub { color: var(--ink-faint); font-size: 0.92rem; margin-top: 5px; }

.crumb { font-size: 0.82rem; color: var(--ink-faint); margin-bottom: 9px; }
.crumb a:hover { color: var(--accent); }
.crumb span { margin: 0 6px; opacity: 0.5; }

.section { margin-top: 40px; }
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line);
}
.section-head h2 {
  font-family: var(--serif);
  font-size: 1.14rem;
  font-weight: 400;
}
.section-head .meta { font-size: 0.8rem; color: var(--ink-faint); }

/* ---------- cards ---------- */

.grid { display: grid; gap: 14px; }
.grid.two   { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.grid.three { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.grid.four  { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }

/* The digest number row. auto-fit rather than auto-fill, and a smaller floor,
   so six counts sit on one line instead of five plus an orphan — and so a role
   that only earns three of them gets three wide cards rather than three narrow
   ones with a gap. */
.grid.stats { grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); }

/* ---------- digest ----------
   The counts were six cards a screen tall, which spent the whole fold saying
   "there are four properties". One line instead, and the three queues sit
   beside each other underneath so the actionable part is visible without
   scrolling. */

.statstrip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 22px;
  padding: 12px 16px;
  margin-bottom: 22px;
  background: var(--bg-raised, #fff);
  border: 1px solid var(--line);
  border-radius: 10px;
  font-size: 0.86rem;
  color: var(--ink-soft);
}
.statstrip a { color: var(--ink-soft); white-space: nowrap; }
.statstrip a:hover { color: var(--ink); }
.statstrip b { font-size: 1.05rem; color: var(--ink); font-weight: 600; margin-right: 3px; }

.grid.digest { align-items: start; margin-bottom: 8px; }
.grid.digest .section { margin: 0; }

ul.rows { list-style: none; margin: 0; padding: 0; }
ul.rows li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.87rem;
}
ul.rows li:last-child { border-bottom: 0; }
ul.rows .dim { font-size: 0.82rem; }


.card {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow);
  transition: border-color 0.14s, transform 0.14s;
}
a.card:hover { border-color: var(--accent); transform: translateY(-1px); }

.card h3 { font-family: var(--serif); font-size: 1.06rem; font-weight: 400; margin-bottom: 4px; }
.card p { font-size: 0.86rem; color: var(--ink-soft); }

.card.muted { opacity: 0.55; }
.card.muted:hover { transform: none; border-color: var(--line); }

/* ---------- stats ---------- */

.stat { text-align: left; }
.stat .n {
  font-family: var(--serif);
  font-size: 2.05rem;
  line-height: 1.05;
  letter-spacing: -0.02em;
}
.stat .k {
  font-size: 0.73rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
  margin-top: 5px;
}

/* ---------- tables ---------- */

.table-wrap {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}

table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
thead th {
  text-align: left;
  font-weight: 500;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
  padding: 11px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
tbody td { padding: 12px 16px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--paper); }
td .dim { color: var(--ink-faint); font-size: 0.82rem; }
td .mono { font-family: var(--mono); font-size: 0.79rem; color: var(--ink-soft); }

/* ---------- pills ---------- */

.pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 20px;
  font-size: 0.73rem;
  font-weight: 500;
  background: var(--line-soft);
  color: var(--ink-soft);
  white-space: nowrap;
}
.pill.accent { background: var(--accent-soft); color: var(--accent); }
.pill.good   { background: var(--good-soft); color: var(--good); }
.pill.warn   { background: var(--warn-soft); color: var(--warn); }

/* ---------- photographs ---------- */

.plates { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }

.plate {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.plate img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  background: var(--line-soft);
}
a.plate { display: block; transition: border-color 0.14s, transform 0.14s; }
a.plate:hover { border-color: var(--accent); transform: translateY(-1px); }

.plate .cap { padding: 12px 14px; }
.plate .cap h4 { font-size: 0.9rem; font-weight: 500; margin-bottom: 3px; }
.plate .cap p { font-size: 0.8rem; color: var(--ink-faint); }

/* ---------- thumbnails in lists ---------- */
/* A row with a photograph is scanned differently from a row without one: the
   eye finds the object before it reads the name. Small, fixed, and never
   reflowing when an image is missing. */

/* The frame is a span and the photograph sits inside it, so an image that
   fails to load can simply hide and leave the frame — no reflow, and no
   broken-image glyph pretending the page is broken. */
.thumb {
  width: 46px;
  height: 46px;
  border-radius: 7px;
  display: block;
  overflow: hidden;
  background: var(--line-soft);
  border: 1px solid var(--line);
}
.thumb.empty-thumb { border-style: dashed; }
.thumb-img { width: 100%; height: 100%; object-fit: cover; display: block; }

td.thumb-cell { width: 62px; padding-right: 0; }

.rowlink { display: block; color: inherit; }
.rowlink:hover { color: var(--accent); }
tbody tr.clickable:hover { background: var(--accent-soft); }

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

.detail-head .pill { margin-right: 6px; }
.detail-head h1 { margin-top: 10px; }

.detail {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(290px, 1fr);
  gap: 30px;
  align-items: start;
}

.figure {
  background: #17150f;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  margin-bottom: 16px;
}
.figure img {
  width: 100%;
  max-height: 68vh;
  object-fit: contain;
  display: block;
}
/* A photograph we cannot produce — the volume is missing it, or a legacy
   capture has not been backfilled out of Slack yet. Say so plainly. */
.figure.broken img { display: none; }
.figure.broken::before {
  content: "Photograph unavailable — it may not have been copied from Slack yet.";
  display: block;
  padding: 46px 24px;
  text-align: center;
  color: rgba(250, 248, 245, 0.66);
  font-size: 0.86rem;
}
.figure.broken figcaption { display: none; }

.figure figcaption {
  padding: 8px 13px;
  font-size: 0.76rem;
  color: rgba(250, 248, 245, 0.6);
  text-align: right;
}
.figure:hover figcaption { color: rgba(250, 248, 245, 0.95); }

.lede {
  font-family: var(--serif);
  font-size: 1.05rem;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-bottom: 22px;
}

.facts {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.fact {
  display: grid;
  grid-template-columns: 40% 60%;
  gap: 12px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.88rem;
}
.fact:last-child { border-bottom: none; }
.fact dt {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
  padding-top: 2px;
}
.fact dd.mono { font-family: var(--mono); font-size: 0.82rem; }
.link { color: var(--accent); }
.link:hover { text-decoration: underline; }

.provenance {
  margin-top: 22px;
  padding: 15px 17px;
  background: var(--line-soft);
  border-radius: var(--radius);
}
.provenance h3 {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
  font-weight: 500;
  margin-bottom: 6px;
}
.provenance p { font-size: 0.84rem; color: var(--ink-soft); }
.provenance code {
  font-family: var(--mono);
  font-size: 0.79rem;
  background: var(--paper-raised);
  padding: 1px 5px;
  border-radius: 4px;
}

@media (max-width: 860px) {
  .detail { grid-template-columns: 1fr; gap: 22px; }
  .figure img { max-height: 52vh; }
}

/* ---------- empty ---------- */

.empty {
  text-align: center;
  padding: 52px 24px;
  color: var(--ink-faint);
  background: var(--paper-raised);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}
.empty .big { font-family: var(--serif); font-size: 1.1rem; color: var(--ink-soft); margin-bottom: 5px; }
.empty p { font-size: 0.87rem; }
.empty code {
  font-family: var(--mono);
  font-size: 0.83rem;
  background: var(--line-soft);
  padding: 1px 5px;
  border-radius: 4px;
  color: var(--ink-soft);
}

/* ---------- sign in ---------- */

.signin {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.signin-card {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 2px 6px rgba(28,26,23,.05), 0 16px 48px rgba(28,26,23,.07);
  padding: 46px 40px;
  max-width: 400px;
  width: 100%;
  text-align: center;
}
.signin-card .mark {
  font-family: var(--serif);
  font-size: 1.55rem;
  margin-bottom: 6px;
}
.signin-card .mark span { color: var(--ink-faint); font-style: italic; }
.signin-card .tag { color: var(--ink-faint); font-size: 0.88rem; margin-bottom: 30px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  padding: 11px 18px;
  background: var(--ink);
  color: var(--paper-raised);
  border-radius: 8px;
  font-size: 0.92rem;
  font-weight: 500;
  transition: opacity 0.14s;
}
.btn:hover { opacity: 0.87; }

.note {
  margin-top: 22px;
  font-size: 0.78rem;
  color: var(--ink-faint);
  line-height: 1.5;
}
.error {
  background: var(--warn-soft);
  color: var(--warn);
  border-radius: 7px;
  padding: 11px 14px;
  font-size: 0.85rem;
  margin-bottom: 20px;
  text-align: left;
}

/* ---------- vendors, forms and tags ---------- */
/* The first writable surface. Forms are laid out as rows of fields that wrap,
   rather than a column, because a vendor record is mostly short values and a
   single column of thirty inputs reads as a chore. */

.page-head.with-action {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
}

.filters {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 20px;
  box-shadow: var(--shadow);
}
.filters .f { display: flex; flex-direction: column; gap: 5px; min-width: 150px; }
.filters .f.grow { flex: 1; min-width: 240px; }

.clearlink { font-size: 0.83rem; color: var(--ink-faint); padding-bottom: 9px; }
.clearlink:hover { color: var(--accent); }

.btn.ghost {
  background: transparent;
  color: var(--ink-soft);
  border: 1px solid var(--line);
}
.btn.ghost:hover { border-color: var(--accent); color: var(--accent); opacity: 1; }

.stack { display: flex; flex-direction: column; gap: 22px; }

.fieldset {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow);
}
.fieldset h2 {
  font-family: var(--serif);
  font-size: 1.02rem;
  font-weight: 400;
  margin-bottom: 14px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line-soft);
}

.rowform.boxed {
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin-top: 14px;
  box-shadow: var(--shadow);
}

.check {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.86rem;
  color: var(--ink-soft);
  padding-bottom: 9px;
  white-space: nowrap;
}
.check input { width: auto; }

textarea {
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 9px 11px;
  width: 100%;
  resize: vertical;
}
textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.formactions { display: flex; align-items: center; gap: 16px; }

/* A destructive action inside a table row should read as a link, not as a
   button competing with the row's own link. */
.linkbtn {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.8rem;
  color: var(--ink-faint);
  cursor: pointer;
}
.linkbtn:hover { color: var(--warn); text-decoration: underline; }

ul.plain { list-style: none; }
ul.plain li { font-size: 0.87rem; padding: 4px 0; border-bottom: 1px solid var(--line-soft); }
ul.plain li:last-child { border-bottom: none; }
ul.plain .dim { margin-left: 6px; }

.tagrow { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }

.tagchip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 20px;
  padding: 3px 5px 3px 11px;
  font-size: 0.79rem;
  font-weight: 500;
}
.tagchip a { color: inherit; }
.tagchip a:hover { text-decoration: underline; }
.tagchip form { display: inline-flex; }

.tagx {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--accent);
  opacity: 0.5;
  font-size: 0.95rem;
  line-height: 1;
  padding: 0 5px;
}
.tagx:hover { opacity: 1; }

.tagadd { display: flex; gap: 8px; margin-top: 12px; }
.tagadd input { font-size: 0.85rem; padding: 6px 10px; }
.tagadd .btn { width: auto; padding: 6px 14px; font-size: 0.83rem; }

@media (max-width: 720px) {
  .page-head.with-action { flex-direction: column; }
  .filters .f, .filters .f.grow { min-width: 100%; }
}

/* ---------- footer ---------- */

.foot {
  border-top: 1px solid var(--line);
  padding: 20px 24px;
  text-align: center;
  font-size: 0.76rem;
  color: var(--ink-faint);
}

/* ---------- responsive ---------- */

@media (max-width: 720px) {
  .masthead-inner { height: auto; padding: 12px 16px; flex-wrap: wrap; gap: 12px; }
  .nav { order: 3; width: 100%; }
  .wrap { padding: 26px 16px 56px; }
  .page-head h1 { font-size: 1.6rem; }
  .who-name { display: none; }
  thead { display: none; }
  tbody td { display: block; padding: 5px 14px; }
  tbody tr { display: block; padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
  tbody td:first-child { font-weight: 500; padding-top: 10px; }
}

/* ---------- admin ---------- */

.banner {
  border-radius: 8px;
  padding: 11px 15px;
  font-size: 0.87rem;
  margin-bottom: 22px;
}
.banner.good { background: var(--good-soft); color: var(--good); }
.banner.warn { background: var(--warn-soft); color: var(--warn); }

.rowform { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; }
.rowform .f { display: flex; flex-direction: column; gap: 5px; min-width: 150px; }
.rowform .f.grow { flex: 1; min-width: 220px; }

.rowform label,
.f label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
}
.f label .opt { text-transform: none; letter-spacing: 0; opacity: 0.7; }

input, select {
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px 11px;
  width: 100%;
}
input:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.btn.compact { width: auto; padding: 9px 20px; font-size: 0.87rem; }

.hint { font-size: 0.79rem; color: var(--ink-faint); margin-top: 5px; }

form.inline { margin: 0; }
form.inline select { font-size: 0.82rem; padding: 5px 9px; min-width: 165px; }

.tick { color: var(--accent); font-size: 0.7rem; }
.tick.off { color: var(--line); }

/* ---------- staff, rota and plans ---------- */
/* The rota is the one page here that is genuinely a grid. Everything else
   reuses the shapes the rest of the application already uses, because a staff
   page that looks like a different product is one people trust less. */

.daynav { display: flex; gap: 8px; align-items: center; }
.daynav .btn { width: auto; }

tr.past td { opacity: 0.55; }
tr.done td { opacity: 0.5; }

.card.uncovered { border-color: var(--warn); background: var(--warn-soft); }
.card.uncovered h3 a { color: var(--warn); }

.progress {
  height: 5px;
  background: var(--line-soft);
  border-radius: 3px;
  overflow: hidden;
  margin-top: 10px;
}
.progress span { display: block; height: 100%; background: var(--accent); }

.daypick { display: flex; gap: 10px; flex-wrap: wrap; padding-top: 4px; }
.daypick label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.83rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink-soft);
}
.daypick input { width: auto; }

.rota-wrap { overflow-x: auto; }
table.rota { font-size: 0.8rem; }
table.rota th, table.rota td { padding: 7px 9px; text-align: center; }
table.rota th.weekend { background: var(--line-soft); }
table.rota .who-cell { text-align: left; white-space: nowrap; font-size: 0.86rem; }
.rota-cell { min-width: 74px; vertical-align: middle; }
.rota-cell.shift { background: var(--accent-soft); }
.rota-cell.off { background: var(--warn-soft); color: var(--warn); }
.rota-label { font-weight: 500; white-space: nowrap; }

.tick-cell { width: 42px; }
.tickbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--paper-raised);
  color: transparent;
  font-size: 0.7rem;
  cursor: pointer;
}
.tickbtn:hover { border-color: var(--accent); color: var(--line); }
.tickbtn.on { background: var(--good); border-color: var(--good); color: var(--paper-raised); }

.linkbtn.approve { color: var(--good); }
.linkbtn.approve:hover { color: var(--good); }

/* The rule an item comes from, kept next to the item rather than in a footnote:
   removing a statutory step should be a decision, not an accident. */
.statutory-note {
  display: block;
  margin-top: 4px;
  padding-left: 9px;
  border-left: 2px solid var(--warn-soft);
  font-style: italic;
  max-width: 52ch;
}

details.inline-edit summary { cursor: pointer; list-style: none; }
details.inline-edit summary::-webkit-details-marker { display: none; }
details.inline-edit[open] { display: block; padding-top: 8px; }
details.inline-edit .rowform { margin-top: 8px; }

.who-name.active { color: var(--accent); }

/* ---------------------------------------------------------------------------
   The mark, and the offer to install
   --------------------------------------------------------------------------- */
.wordmark { display: inline-flex; align-items: center; gap: 9px; }
.wordmark-mark {
  width: 21px;
  height: 21px;
  flex: none;
  color: var(--ink);
  /* The arch sits on a baseline of its own; nudging it down puts its foot on
     the text baseline rather than its bounding box. */
  transform: translateY(1px);
}

/* Offered once, from the corner, and never over the content it interrupts:
   full width at the bottom on a phone, a card on a desktop. */
.installbar {
  position: fixed;
  z-index: 40;
  left: 16px;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 13px 14px;
  background: var(--paper-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 2px 6px rgba(28, 26, 23, 0.06), 0 12px 32px rgba(28, 26, 23, 0.12);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.28s ease, transform 0.28s ease;
}
.installbar.is-in { opacity: 1; transform: none; }
.installbar[hidden] { display: none; }

@media (min-width: 640px) {
  .installbar { left: 22px; right: auto; bottom: 22px; max-width: 30rem; }
}

.installbar-mark { width: 30px; height: 30px; flex: none; color: var(--ink); }

.installbar-copy { display: grid; gap: 2px; line-height: 1.35; min-width: 0; }
.installbar-copy strong { font-family: var(--serif); font-size: 0.97rem; font-weight: 600; }
.installbar-copy span { font-size: 0.84rem; color: var(--ink-soft); }

.installbar-actions { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.installbar .btn { white-space: nowrap; }

.installbar-close {
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--ink-faint);
  font-size: 1.3rem;
  line-height: 1;
  padding: 2px 6px;
  border-radius: 6px;
}
.installbar-close:hover { color: var(--ink); background: var(--line-soft); }

/* Installed, and running in its own window: the masthead is the only chrome
   there is, so give it back the space the browser's toolbar used to occupy. */
@media (display-mode: standalone) {
  .masthead-inner { padding-top: calc(env(safe-area-inset-top) + 4px); }
}


/* "Or just say it" — the alternative to typing a task, on the form somebody
   opened because they did not know there was one. */
.speak-instead {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 18px;
  padding: 14px 16px;
}
.speak-instead .speak-mic {
  width: 26px; height: 26px; flex: none;
  fill: none; stroke: var(--ink); stroke-width: 7;
  stroke-linecap: round; stroke-linejoin: round;
}
.speak-instead div { display: grid; gap: 2px; line-height: 1.35; min-width: 0; }
.speak-instead strong { font-family: var(--serif); font-size: 0.97rem; font-weight: 600; }
.speak-instead span { font-size: 0.86rem; color: var(--ink-soft); }
.speak-instead .btn { margin-left: auto; white-space: nowrap; }

@media (max-width: 560px) {
  .speak-instead { flex-wrap: wrap; }
  .speak-instead .btn { margin-left: 0; width: 100%; text-align: center; }
}


/* A room's own photograph: wide, because a room is wider than it is tall and
   a portrait crop of one tells you nothing about the space. */
.room-hero {
  margin: 0 0 18px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--line-soft);
  aspect-ratio: 16 / 9;
}
.room-hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
.room-hero.broken { display: none; }

.room-description { max-width: 60ch; margin-bottom: 18px; }

.room-photo-form { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; }
.room-photo-form label { cursor: pointer; }
.room-photo-form .dim { font-size: 0.84rem; }


/* A room card leads with its photograph where there is one. Wide, because a
   room is wider than it is tall. */
.roomcard { overflow: hidden; padding-top: 0; }
.roomcard-photo {
  display: block;
  margin: -1px -1px 12px;
  aspect-ratio: 16 / 9;
  background: var(--line-soft);
  overflow: hidden;
}
.roomcard-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }


/* Floors, once a property has enough rooms that a flat grid is a wall. */
.floor-head {
  display: flex; align-items: baseline; gap: 10px;
  margin: 22px 0 10px; font-family: var(--serif); font-size: 1rem;
  color: var(--ink-soft); font-weight: 600;
}
.floor-head:first-of-type { margin-top: 4px; }
.floor-head span { font-family: var(--sans); font-size: 0.8rem; color: var(--ink-faint); font-weight: 400; }

/* Project progress: a count, shown as one. Named apart from .progress, which
   is already a bare bar on the plan pages — sharing the class gave this one
   that rule's 5px height and squashed the count beside it into a stripe. */
.progress-inline { display: inline-flex; align-items: center; gap: 8px; }
.progress-bar {
  display: block; width: 90px; height: 6px; border-radius: 3px;
  background: var(--line); overflow: hidden;
}
.progress-bar span { display: block; height: 100%; background: var(--good); }

/* A project on a property page: name, where it stands, how far along. */
.projectcard { display: block; text-decoration: none; }
.projectcard-name { font-weight: 600; margin-bottom: 2px; }
.projectcard .meta { display: block; margin-bottom: 6px; }

/* Two actions in a page head sit side by side rather than stacking full-width,
   which is what a bare pair of .btn children does inside a flex column. */
.head-actions { display: flex; gap: 8px; flex-shrink: 0; }

/* The reorder arrows and Remove on a template row: side by side, not stacked. */
.rowactions { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
.rowactions .linkbtn[disabled] { opacity: 0.25; cursor: default; }

/* Who is at this house right now. Sits above the counts because it is the
   first question anybody standing in the building asks. */
.onduty { margin-bottom: 16px; padding: 14px 16px; }
.onduty-head {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-faint); margin-bottom: 8px;
}
.onduty .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--line); flex-shrink: 0;
}
.onduty .dot.live { background: var(--good); }
.onduty-people { display: flex; flex-wrap: wrap; gap: 6px 20px; }
.onduty-person { font-size: 0.95rem; }
.onduty-later {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--line-soft);
  font-size: 0.88rem; color: var(--ink-soft);
}
a.card.stat { text-decoration: none; display: block; }
a.card.stat:hover { border-color: var(--accent); }

/* Attaching photographs: two inputs, because "take a photo" and "choose
   photos" are different intentions, and one running count so somebody who does
   both is told how many they are sending. */
.photopick { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.photopick .btn { cursor: pointer; }

/* A focus image with thumbnails beneath it. Several photographs of one thing
   are views of it — the front, the label, the damage — so one leads and the
   rest are a strip rather than a stack you scroll past. */
.gallery-focus { margin-bottom: 10px; }
.gallery-focus figcaption { display: flex; justify-content: space-between; gap: 12px; }
.gallery-strip {
  display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 18px;
}
.gallery-thumb {
  display: block; width: 68px; height: 68px; border-radius: 6px;
  overflow: hidden; border: 2px solid transparent; flex-shrink: 0;
  background: var(--line-soft);
}
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-thumb.current { border-color: var(--accent); }
.gallery-thumb:hover { border-color: var(--ink-faint); }

/* Photographs at the top of the edit form: the picture is how somebody knows
   they have the right thing, so it leads rather than sitting under four
   fieldsets. The controls are visible rather than revealed on hover — half of
   this is used on a phone, where there is no hover. */
.photo-row {
  display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-start;
  margin-bottom: 18px;
}
.photo-edit { position: relative; width: 72px; }
.photo-edit img {
  width: 72px; height: 72px; object-fit: cover; display: block;
  border-radius: 6px; border: 2px solid transparent; background: var(--line-soft);
}
.photo-edit.is-lead img { border-color: var(--accent); }
.photo-x {
  position: absolute; top: -6px; right: -6px;
  width: 20px; height: 20px; line-height: 1; padding: 0;
  border-radius: 50%; border: 1px solid var(--line);
  background: var(--paper-raised); color: var(--ink-soft);
  font-size: 0.66rem; cursor: pointer;
}
.photo-x:hover { color: var(--warn); border-color: var(--warn); }
.photo-tag {
  display: block; margin-top: 4px; text-align: center;
  font-size: 0.68rem; color: var(--ink-faint); letter-spacing: 0.02em;
}
.photo-tag.as-button {
  background: none; border: none; cursor: pointer; width: 100%;
  font-family: inherit;
}
.photo-tag.as-button:hover { color: var(--accent); text-decoration: underline; }

/* The add control, sized to sit in the same row as the thumbnails. */
.photo-add {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  width: 72px;
}
/* Classes rather than `label[for]`: an attribute selector outranks a bare
   class, so styling the tile that way made every label in here 1.4rem — the
   word "Choose" came out the size of a heading and broke the row. */
.photo-add .plus {
  width: 72px; height: 72px; border-radius: 6px;
  border: 1px dashed var(--line); background: var(--paper-raised);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem; line-height: 1; color: var(--ink-faint); cursor: pointer;
}
.photo-add .plus:hover { border-color: var(--accent); color: var(--accent); }
.photo-add .pick {
  font-size: 0.68rem; color: var(--ink-faint); cursor: pointer;
  text-align: center; width: 100%;
}
.photo-add .pick:hover { color: var(--accent); text-decoration: underline; }
.photo-count { align-self: center; font-size: 0.8rem; }

/* Leaving the register: collapsed, so the ordinary business of the page is the
   whole page until somebody is actually getting rid of something. */
.leaving { margin-top: 26px; }
.leaving > summary {
  cursor: pointer; font-size: 0.88rem; color: var(--ink-soft);
  padding: 8px 0; border-top: 1px solid var(--line-soft);
}
.leaving > summary:hover { color: var(--accent); }
.leaving[open] > summary { margin-bottom: 14px; }
.leaving h3 { font-family: var(--serif); font-weight: 400; margin-bottom: 10px; }
.leaving .warn-card { border-color: var(--warn); margin-bottom: 14px; }
.leaving .warn-card ul { margin: 8px 0 0 18px; font-size: 0.9rem; }

/* A fact worth acting on rather than a failure: a donation closed without its
   receipt is fine today and a problem in April. */
.hint.warnish { color: var(--warn); }

/* A fact worth acting on rather than a failure: a donation closed without its
   receipt is fine today and a problem in April. */
.hint.warnish { color: var(--warn); }

/* Where to look, before what to look for. A register heading for thousands of
   rows needs a first question, and the first question is always "where". */
.shelf { display: block; text-decoration: none; }
.shelf-count { font-family: var(--serif); font-size: 1.7rem; line-height: 1.1; }
.shelf-label { font-weight: 600; margin-top: 2px; }
.shelf:hover { border-color: var(--accent); }

/* Paperwork attached to a thing: a manual, a warranty, a receipt. */
.doclist li { display: flex; align-items: center; gap: 10px; padding: 5px 0; }
.doclist .pill { flex-shrink: 0; }

/* A labelled group inside a dropdown. Inventory is a system rather than a
   page — a register, what is running out, where it is kept — and the label is
   what makes those read as one area rather than four unrelated links. */
.navlabel {
  padding: 6px 14px 2px;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}

/* Links found on the web and not yet vouched for by anybody. Set apart from
   attached paperwork on purpose — one is a decision, the other is a
   suggestion. */
.candidates { margin: 12px 0; border-style: dashed; }

/* Your day. The current state is the whole screen, because somebody standing
   in a doorway with a bag in one hand should not have to read. */
.daycard { text-align: center; padding: 28px 20px; }
.daycard.on { border-color: var(--good); }
.daystate {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-faint);
}
.dayclock {
  font-family: var(--serif); font-size: 3.4rem; line-height: 1.05;
  margin: 6px 0 2px;
}
.dayclock span { font-size: 1.4rem; color: var(--ink-faint); }
.dayform { margin-top: 18px; display: grid; gap: 12px; text-align: left; }
.btn.big {
  width: 100%; padding: 16px; font-size: 1.05rem; border-radius: 10px;
}
.warn-text { color: var(--warn); }

/* An entry that has been open long enough to be a forgotten Finish. */
tr.flagged { background: var(--warn-soft); }
