/* Hold Your Line — calm, legible, unclinical.
   Palette: oat paper, spruce ink, heather accent, amber for "come back to this". */

:root {
  --paper: #F2EFE7;
  --card: #FBF9F3;
  --ink: #33403A;
  --ink-soft: #6C7770;
  --line: #DDD8C9;
  --accent: #7D5A68;
  --accent-soft: #EDE3E7;
  --amber: #a97b2f;
  --amber-soft: #F4EAD8;
  --danger: #9C4A3C;
  --spine: #CFC9B8;
  --field: #FFFFFF;
  --report-bg: #FFFFFF;
  --accent-strong: #7D5A68;
  --accent-strong-hover: #6D4D5A;
  --serif: 'Charter', 'Bitstream Charter', 'Georgia', serif;
  font-size: 106.25%; /* 17px base — generous for dyslexic reading */
}

/* Dark mode — the same family: deep spruce paper, oat ink, heather accent. */
:root[data-theme-resolved="dark"] {
  --paper: #1E2420;
  --card: #272E29;
  --ink: #E8E5D9;
  --ink-soft: #A3ACA1;
  --line: #3C443E;
  --accent: #C69CAE;
  --accent-soft: #3B3036;
  --amber: #C9A25B;
  --amber-soft: #38301D;
  --danger: #C77F71;
  --spine: #49514A;
  --field: #1A201C;
  --report-bg: #232A25;
  --accent-strong: #7D5A68;
  --accent-strong-hover: #8D6678;
}
:root[data-textsize="large"] { font-size: 118.75%; }
:root[data-textsize="xlarge"] { font-size: 131.25%; }

* { box-sizing: border-box; }

/* The hidden attribute always wins, whatever display an element's class
   sets — without this, any styled element ignores hidden. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Atkinson Hyperlegible', system-ui, sans-serif;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.25; margin: 0 0 .4rem; }
p { margin: .3rem 0; }
a { color: var(--accent); }

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

#app {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  min-height: 100vh;
  max-width: 1100px;
  margin: 0 auto;
}

.sidebar {
  padding: 2.2rem 1.4rem;
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
}
.brand h1 { font-family: var(--serif); font-weight: 400; font-size: 1.5rem; }
.brand p { color: var(--ink-soft); font-size: .85rem; margin: 0; }

.nav { display: flex; flex-direction: column; gap: .15rem; }
.nav a {
  text-decoration: none;
  color: var(--ink);
  padding: .45rem .7rem;
  border-radius: .5rem;
}
.nav a:hover { background: var(--card); }
.nav a.active { background: var(--accent-soft); color: var(--accent); font-weight: 700; }
.nav-short { display: none; }

.nav-lock {
  background: none;
  border: none;
  font: inherit;
  color: var(--ink-soft);
  text-align: left;
  padding: .45rem .7rem;
  border-radius: .5rem;
  cursor: pointer;
  margin-top: .4rem;
}
.nav-lock::before { content: '🔒 '; font-size: .8em; }
.nav-lock:hover { background: var(--card); color: var(--ink); }
.nav-break::before { content: '🍵 '; }

.nav .donate-hide {
  font-size: .78rem;
  color: var(--ink-soft);
  text-align: left;
  padding: 0 .7rem .3rem;
}
@media (max-width: 760px) {
  /* No room in the phone nav row — the Donate page carries the same link. */
  .donate-hide { display: none; }
}

@media (max-width: 760px) {
  .nav-lock { margin-top: 0; padding: .35rem .6rem; font-size: .95rem; }
}

.sidebar-foot {
  margin-top: auto;
  color: var(--ink-soft);
  font-size: .85rem;
  font-style: italic;
  /* stays at the bottom of the window, not the bottom of a long page */
  position: sticky;
  bottom: 1.4rem;
}

.offline-note {
  background: var(--amber-soft);
  border: 1px solid var(--amber);
  color: var(--ink);
  border-radius: .5rem;
  padding: .5rem .7rem;
  font-size: .85rem;
}

main {
  padding: 2.2rem clamp(1rem, 4vw, 3rem) 4rem;
  min-width: 0;
}

@media (max-width: 760px) {
  /* One column, and the header row keeps its content height — otherwise a
     view shorter than the screen lets the grid stretch the header, and the
     centred nav drifts downward on (say) a near-empty timeline. */
  #app { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .sidebar {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: .8rem;
    padding: .9rem 1rem;
    border-right: none;
    border-bottom: 1px solid var(--line);
    position: sticky;
    top: 0;
    background: var(--paper);
    z-index: 10;
  }
  .sidebar { flex-wrap: nowrap; }
  /* The brand text is redundant on a phone (the tab/home-screen already says
     "Hold Your Line"), so the four nav items get the whole width on one tidy row
     with short labels — no awkward wrapping to a second line. */
  .brand, .sidebar-foot { display: none; }
  .nav {
    flex: 1 1 auto;
    min-width: 0; /* let the row shrink instead of widening the page */
    flex-direction: row;
    /* six items don't always fit one row — larger text sizes especially —
       so the row wraps rather than hiding Break and Lock off-screen; items
       flow left so wrapped rows read naturally instead of spreading out */
    flex-wrap: wrap;
    gap: 0 .3rem;
  }
  .nav a, .nav-lock { padding: .4rem .45rem; font-size: .95rem; white-space: nowrap; }
  /* words over symbols, and every item stays on screen */
  .nav-lock::before, .nav-break::before { content: none; }
  /* Break and Lock live as floating buttons on a phone, not menu items */
  #take-break, #lock-now { display: none; }
  .nav-full { display: none; }
  .nav-short { display: inline; }
  main { padding: 1.2rem 1rem 4rem; }
}

/* ------------------------------------------------------------------ shared */

.view-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.4rem;
}
.view-head h2 { font-family: var(--serif); font-weight: 400; font-size: 1.7rem; }
/* Two flex children only — box and text. The wording wraps (and may carry a
   link), so the text lives in one span rather than becoming its own column. */
.pdf-photos-toggle { display: flex; align-items: flex-start; gap: .5rem; margin-top: .55rem; }
.pdf-photos-toggle input { flex: none; margin-top: .15rem; }
.lede { color: var(--ink-soft); max-width: 46ch; }

.button {
  display: inline-block;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  padding: .5rem 1rem;
  border-radius: .6rem;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
}
.button:hover { border-color: var(--accent); }
.button.primary { background: var(--accent-strong); border-color: var(--accent-strong); color: #fff; }
.button.primary:hover { background: var(--accent-strong-hover); }
.button.danger { color: var(--danger); border-color: var(--danger); background: transparent; }
.button-row { display: flex; gap: .6rem; flex-wrap: wrap; }
/* The four export buttons are too wide to share a phone screen tidily — left
   to wrap they land in ragged rows of one and two. One apiece, full width,
   reads as a deliberate list and gives every one an easy target. */
@media (max-width: 760px) {
  .export-actions .button-row { display: grid; }
  .export-actions .button-row > .button { width: 100%; }
}

.link-button {
  background: none; border: none; padding: 0;
  color: var(--accent); font: inherit; font-size: .9rem;
  text-decoration: underline; cursor: pointer;
}
.link-button.danger { color: var(--danger); }
/* The backup tip is a quiet card of its own: soft box, text one side,
   snooze button the other, wrapping on narrow screens. */
.backup-nudge {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .7rem 1.1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: .8rem;
  padding: .8rem 1rem;
  margin-bottom: 1rem;
}
.backup-nudge p { margin: 0; flex: 1 1 18rem; }
.backup-nudge .chip { white-space: nowrap; color: var(--ink-soft); }
.backup-nudge .chip:hover { border-color: var(--accent); color: var(--ink); }

/* The plan line opens the Donate page in the same quiet card as the backup
   tip — seen before the pitch, not hidden under the button. The thank-you
   for donators gets a soft accent edge. */
.donate-status {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: .8rem;
  padding: .8rem 1rem;
  margin-bottom: 1rem;
}
.donate-status p { margin: 0; }
.donate-status.thanks { border-left: 4px solid var(--accent); }

/* Support signposting — warm and reassuring, never alarming. The full card sits
   at the top of Help; a compact <details> version sits under the lock screen so
   it's reachable before signing in too. */
.support-card {
  background: var(--accent-soft);
  border: 1px solid var(--line);
  border-radius: .8rem;
  padding: 1rem 1.2rem;
  margin-bottom: 1.4rem;
}
.support-card h3 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.15rem;
  margin: 0 0 .4rem;
  color: var(--accent);
}
.support-card h4 { font-size: .95rem; margin: .9rem 0 .3rem; color: var(--ink); }
.support-note { color: var(--ink-soft); font-size: .9rem; margin: 0 0 .3rem; }
.support-group ul { margin: .2rem 0 0; padding-left: 1.15rem; }
.support-group li { margin: .3rem 0; }
.support-card a { color: var(--accent-strong); }

.lock-support {
  width: 100%;
  max-width: 22rem;
  font-size: .9rem;
  color: var(--ink-soft);
}
.lock-support summary { cursor: pointer; color: var(--accent-strong); text-align: center; }
.lock-support ul { margin: .6rem 0 0; padding-left: 1.15rem; text-align: left; }
.lock-support li { margin: .3rem 0; }

.chip {
  border: 1px solid var(--line);
  background: var(--card);
  border-radius: 2rem;
  padding: .2rem .75rem;
  font: inherit;
  font-size: .88rem;
  cursor: pointer;
  color: var(--ink);
  white-space: nowrap; /* a pill never wraps its own text */
  flex: 0 0 auto;      /* nor shrinks — the row wraps whole pills instead */
}
.chip span { color: var(--ink-soft); font-size: .8em; }
.chip.on { background: var(--accent-strong); border-color: var(--accent-strong); color: #fff; }
.chip.on span { color: #eee; }
.chip.clear-filters { border-style: dashed; color: var(--ink-soft); }

.tag {
  display: inline-block;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1.5px solid transparent;
  border-radius: 2rem;
  padding: .08rem .65rem;
  font-size: .85rem;
  margin: 0 .25rem .25rem 0;
}

/* Per-tag colour, hashed from the tag's name in JS — an outline only, so the
   text never sits on a coloured fill. Same slots, lifted for dark mode. */
[data-tagc="0"] { --tagc: #7C9161; }
[data-tagc="1"] { --tagc: #64809C; }
[data-tagc="2"] { --tagc: #B07A5E; }
[data-tagc="3"] { --tagc: #4F8F8B; }
[data-tagc="4"] { --tagc: #8E7BAB; }
[data-tagc="5"] { --tagc: #B99432; }
[data-tagc="6"] { --tagc: #B06A78; }
[data-tagc="7"] { --tagc: #5C7D72; }
:root[data-theme-resolved="dark"] [data-tagc="0"] { --tagc: #9DB37E; }
:root[data-theme-resolved="dark"] [data-tagc="1"] { --tagc: #86A3C0; }
:root[data-theme-resolved="dark"] [data-tagc="2"] { --tagc: #C99878; }
:root[data-theme-resolved="dark"] [data-tagc="3"] { --tagc: #6FB0AB; }
:root[data-theme-resolved="dark"] [data-tagc="4"] { --tagc: #AC9BC9; }
:root[data-theme-resolved="dark"] [data-tagc="5"] { --tagc: #D4AF5A; }
:root[data-theme-resolved="dark"] [data-tagc="6"] { --tagc: #CE8B99; }
:root[data-theme-resolved="dark"] [data-tagc="7"] { --tagc: #7EA093; }
.tag[data-tagc] {
  background: transparent;
  color: var(--ink);
  border-color: var(--tagc);
}
.chip[data-tagc]:not(.on) { border-color: var(--tagc); }
.tag.removable button {
  background: none; border: none; cursor: pointer;
  color: inherit; font-size: 1em; padding: 0 0 0 .3rem;
}

.hint { color: var(--ink-soft); font-size: .9rem; }

/* Demo mode — an unmistakable coat, so nobody takes the shared example for
   their own private account and types real details into it. A fixed top bar
   on every screen, plus a louder version of the timeline hint. */
#demo-banner { display: none; }
body.demo-mode #demo-banner {
  display: block;
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 2000;
  background: var(--amber);
  color: #fff;
  text-align: center;
  padding: .45rem 1rem;
  font-size: .9rem;
  line-height: 1.4;
  box-shadow: 0 1px 5px rgba(0, 0, 0, .25);
}
body.demo-mode #demo-banner strong { letter-spacing: .1em; }
.demo-countdown { white-space: nowrap; opacity: .85; font-variant-numeric: tabular-nums; }
/* Reserve exactly the banner's height (measured in JS — it wraps differently
   by width and text-size) so nothing hides beneath it. */
body.demo-mode #app { padding-top: var(--demo-bar-h, 2.7rem); }
.demo-hint {
  background: var(--amber-soft);
  border-left: 3px solid var(--amber);
  padding: .6rem .8rem;
  border-radius: 4px;
  color: var(--ink);
}
/* On a phone the nav is a sticky top bar; in demo mode it must stick below
   the fixed banner, not underneath it. */
@media (max-width: 760px) {
  body.demo-mode .sidebar { top: var(--demo-bar-h, 2.7rem); }
}
.error { color: var(--danger); min-height: 1.4em; }
/* Empty holds one line of space; with a message it becomes a proper alert
   box — colour alone is too easy to skim past. */
.error:not(:empty) {
  background: color-mix(in srgb, var(--danger) 9%, var(--card));
  border: 2px solid var(--danger);
  border-radius: .7rem;
  padding: .75rem .95rem;
}
.save-status { color: var(--ink-soft); font-size: .88rem; font-style: italic; }

fieldset {
  border: 1px solid var(--line);
  border-radius: .8rem;
  padding: .9rem 1.1rem 1.1rem;
  margin: 0 0 1.1rem;
  background: var(--card);
  min-width: 0;
}
legend {
  font-weight: 700;
  padding: 0 .5rem;
  display: flex;
  gap: .8rem;
  align-items: center;
}

input[type="text"], input[type="search"], input[type="password"],
input[type="email"], input[type="date"], input[type="number"], select, textarea {
  font: inherit;
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: .5rem;
  padding: .45rem .65rem;
  max-width: 100%;
}
input:focus-visible, select:focus-visible, textarea:focus-visible,
button:focus-visible, [tabindex]:focus-visible, a:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------- timeline */

.filters {
  display: flex;
  gap: .5rem;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: .7rem;
}
/* The search sits on its own row so the filter chips stay a tidy group below
   it, instead of the chips wrapping unevenly around a shrinking search box. */
.filters input[type="search"] { flex: 1 1 100%; }
.tags-row { margin-bottom: 1.3rem; }

.empty {
  background: var(--card);
  border: 1px dashed var(--line);
  border-radius: 1rem;
  padding: 2.5rem 1.5rem;
  text-align: center;
  max-width: 34rem;
  margin: 3rem auto;
}
.empty .button { margin-top: 1rem; }
.empty-help { margin-top: 1.4rem; color: var(--ink-soft); font-size: .92rem; }
.empty-help a { color: var(--accent); }

/* The user guide, fetched from user-guide.html and rendered in-app. Styled with
   the app's own theme/vars — colour, spacing, the legible font — instead of the
   print styling the same file carries for the PDF. Figures float on a roomy
   screen and stack on a narrow one. */
.guide { max-width: 46rem; }
.guide h2 { font-family: var(--serif); font-weight: 400; color: var(--accent); font-size: 1.4rem; margin: 1.9rem 0 .5rem; }
.guide h3 { font-size: 1.05rem; margin: 1.15rem 0 .3rem; }
.guide p, .guide li { line-height: 1.65; }
.guide ul { padding-left: 1.3rem; margin: 0 0 1rem; }
.guide li { margin: 0 0 .35rem; }
.guide .note { background: var(--amber-soft); border-left: 3px solid var(--amber); padding: .7rem 1rem; border-radius: 6px; margin: 1rem 0; }
.guide .note strong:first-child { color: var(--amber); }
.guide code { background: var(--accent-soft); padding: 0 .3rem; border-radius: 3px; font-size: .92em; }
.guide figure { float: right; width: 12rem; max-width: 40%; margin: .2rem 0 .9rem 1.3rem; }
.guide figure img { width: 100%; border: 1px solid var(--line); border-radius: 8px; }
.guide figcaption { font-size: .82rem; color: var(--ink-soft); margin-top: .3rem; }
.guide .with-figure::after { content: ''; display: block; clear: both; }
.guide .foot { margin-top: 2rem; padding-top: .8rem; border-top: 1px solid var(--line); color: var(--ink-soft); font-size: .85rem; }
@media (max-width: 620px) {
  .guide figure { float: none; width: 100%; max-width: 100%; margin: .5rem 0 1rem; }
}

.unplaced {
  border: 1px dashed var(--amber);
  background: var(--amber-soft);
  border-radius: 1rem;
  padding: 1rem 1.2rem;
  margin-bottom: 2rem;
}
.unplaced h3 { font-family: var(--serif); font-weight: 400; }
.unplaced .cards { margin-top: .8rem; }

.spine { position: relative; padding-left: .4rem; }
.spine::before {
  content: '';
  position: absolute;
  left: .4rem; top: 0; bottom: 0;
  width: 2px;
  background: var(--spine);
}
.year-group {
  position: relative;
  padding: 0 0 1.6rem 1.6rem;
}
.year-marker {
  font-family: var(--serif);
  font-size: 2.4rem;
  color: var(--ink-soft);
  line-height: 1;
  margin-bottom: .6rem;
  position: relative;
}
.year-marker::before {
  content: '';
  position: absolute;
  left: -1.63rem; top: .95rem;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--paper);
  border: 3px solid var(--spine);
}

.cards { display: flex; flex-direction: column; gap: .7rem; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: .8rem;
  padding: .85rem 1.1rem;
  cursor: pointer;
  transition: border-color .15s, transform .15s;
}
.card:hover { border-color: var(--accent); transform: translateX(2px); }
.card h3 { font-size: 1.08rem; margin: .1rem 0 .2rem; }
.card-date { color: var(--ink-soft); font-size: .85rem; display: flex; align-items: center; gap: .1rem .5rem; flex-wrap: wrap; }
.card .snippet {
  color: var(--ink-soft);
  font-size: .92rem;
  margin: .15rem 0 .4rem;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .15rem .4rem; }
.refs { color: var(--ink-soft); font-size: .82rem; }

/* Cover / reveal — a quiet word-button that sits at the end of the date line
   and never opens the entry. Words over symbols, like the rest of the app. */
.card-cover {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--accent);
  font-size: .82rem;
  cursor: pointer;
  padding: .1rem .45rem;
  border-radius: .5rem;
}
.card-cover:hover { background: var(--accent-soft); }
.card.covered { cursor: pointer; }
.covered-tag { color: var(--ink-soft); font-style: italic; font-size: .82rem; }

.card.flagged { border-left: 4px solid var(--amber); }
.flag-chip {
  background: var(--amber-soft);
  color: var(--amber);
  border-radius: 2rem;
  font-size: .78rem;
  padding: .02rem .6rem;
  margin-left: .6rem;
}

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

/* ------------------------------------------------------------------ editor */

.editor { max-width: 46rem; }
.editor-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
}
.back { text-decoration: none; font-size: .95rem; }

.title-input {
  width: 100%;
  font-size: 1.35rem;
  font-weight: 700;
  padding: .6rem .8rem;
  margin-bottom: 1.1rem;
}

.seg { display: inline-flex; flex-wrap: wrap; gap: .3rem; }
.seg-btn {
  border: 1px solid var(--line);
  background: var(--field);
  font: inherit;
  font-size: .9rem;
  padding: .3rem .8rem;
  border-radius: 2rem;
  cursor: pointer;
  color: var(--ink);
}
.seg-btn.on { background: var(--ink); border-color: var(--ink); color: var(--paper); }

.date-block .date-inputs { margin-top: .7rem; }
.date-inputs input[type="number"] { width: 9rem; }
.range-rows { margin-top: .7rem; }
.range-rows [data-range-row] {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}
.range-rows input[type="number"] { width: 7rem; }
.range-sep { color: var(--ink-soft); font-size: .92rem; }

.tag-editor { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
#f-tag-form { display: contents; } /* the form is plumbing, not layout */
.tag-list { display: inline; }
.tag-suggestions { margin-top: .6rem; color: var(--ink-soft); font-size: .88rem; }
.tag-suggestions .chip { margin: 0 .2rem .2rem 0; }

.body-block textarea {
  width: 100%;
  min-height: 14rem;
  resize: vertical;
  line-height: 1.7;
}
.write-preview { display: inline-flex; gap: .3rem; font-weight: 400; }
.md-hints { margin-top: .5rem; }
.md-hints code {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: .3rem;
  padding: .02rem .35rem;
  font-size: .85em;
  white-space: nowrap;
}
.md-preview {
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: .5rem;
  padding: .8rem 1rem;
  min-height: 14rem;
}
.md-preview blockquote, .report-body blockquote {
  border-left: 3px solid var(--line);
  margin: .5rem 0;
  padding: .1rem 0 .1rem .9rem;
  color: var(--ink-soft);
}
.md-preview code, .report-body code {
  background: var(--paper);
  border-radius: .3rem;
  padding: .05rem .3rem;
}

.attachment-list { list-style: none; padding: 0; margin: .4rem 0; }
.attachment-list li {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .45rem 0;
  border-bottom: 1px dashed var(--line);
}
.attach-thumb img {
  width: 52px; height: 52px;
  object-fit: cover;
  border-radius: .4rem;
  display: block;
}
.attach-name { flex: 1; overflow-wrap: anywhere; }
.attach-buttons { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; margin-top: .6rem; }

.ref-badge {
  font-variant-numeric: tabular-nums;
  background: var(--ink);
  color: var(--paper);
  border-radius: .35rem;
  font-size: .78rem;
  padding: .1rem .45rem;
  white-space: nowrap;
}

.flag-toggle {
  display: flex;
  gap: .7rem;
  align-items: flex-start;
  background: var(--amber-soft);
  border: 1px solid var(--amber);
  border-radius: .8rem;
  padding: .8rem 1rem;
  margin-bottom: 1.4rem;
  cursor: pointer;
}
.flag-toggle input { margin-top: .3rem; width: 1.1rem; height: 1.1rem; }

.editor-bottom {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

/* On a phone the editor top bar scrolls away, so the save indicator floats
   where it can always be seen. */
@media (max-width: 760px) {
  #save-status {
    position: fixed;
    bottom: .9rem;
    right: .9rem;
    z-index: 30;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 2rem;
    padding: .3rem .9rem;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .12);
  }
  #save-status:empty { display: none; }
}

.profile-fields {
  display: flex;
  flex-direction: column;
  gap: .7rem;
  max-width: 26rem;
  margin-bottom: .5rem;
}
.field {
  display: flex;
  flex-direction: column;
  gap: .25rem;
  font-weight: 700;
  font-size: .92rem;
}
.field input { font-weight: 400; }

.report-who { font-size: 1.05rem; margin: .1rem 0 .25rem; }

.tag-manage {
  list-style: none;
  padding: 0;
  margin: .8rem 0 0;
}
.tag-manage li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .15rem .8rem;
  padding: .4rem 0;
  border-bottom: 1px dashed var(--line);
}
.tag-manage .tag { margin: 0; }
.tag-count { color: var(--ink-soft); font-size: .85rem; flex: 1 1 14rem; }

/* Rows whose numbers run long (admin timelines, invites, the trash): the
   name and its actions share the first line, and the numbers get a whole
   line to themselves beneath — they never fight the name for width. */
.tag-manage.stacked li { align-items: baseline; row-gap: 0; }
.tag-manage.stacked li > .trash-title { flex: 1 1 auto; }
.tag-manage.stacked li > .tag-count { flex: 1 1 100%; order: 5; }
.trash-title { font-weight: 700; overflow-wrap: anywhere; }
.no-split { white-space: nowrap; }

/* On a phone the row becomes three tidy lines: the name, then the
   details, then the actions together on a line of their own. */
@media (max-width: 760px) {
  .tag-manage.stacked li { row-gap: .1rem; }
  .tag-manage.stacked li > .trash-title { flex-basis: 100%; }
  .tag-manage.stacked li > .tag-count { order: 0; }
}

/* ------------------------------------------------------------------- about */

#about {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--paper);
  overflow-y: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem 1rem;
}
.about-photo {
  width: 7.5rem;
  height: 7.5rem;
  object-fit: cover;
  border-radius: 50%;
  border: 1px solid var(--line);
  margin-bottom: .9rem;
}
.about-link { font-size: .85rem; font-style: normal; }

/* Settings carries the About link only on phones, where the sidebar foot
   (its desktop home) is hidden — it never shows in two places at once. */
.about-settings-line { display: none; }
@media (max-width: 760px) {
  .about-settings-line { display: block; }
}

/* --------------------------------------- floating break/lock (phones only) */

#float-actions {
  display: flex;
  position: fixed;
  right: .7rem;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  flex-direction: column;
  gap: .55rem;
  z-index: 40;
}
#float-actions button {
  width: 2.8rem;
  height: 2.8rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 1.25rem;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .12);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Break and Lock are phone conveniences — the sidebar carries them on wider
   screens. The arrow shows everywhere: a long timeline is a long way back
   whatever you're reading it on. */
#float-actions button.phone-only { display: none; }
@media (max-width: 760px) {
  #float-actions button.phone-only { display: flex; }
}
/* The arrow is the only floater that comes and goes — it waits until there's
   a real scroll behind you. Kept out of the tab order while it's away. */
#float-top {
  opacity: 0;
  visibility: hidden;
  transform: translateY(.4rem);
  transition: opacity .2s ease, transform .2s ease, visibility .2s;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--ink); /* it's the only way back now — it can hold its own */
}
#float-top.on { opacity: 1; visibility: visible; transform: none; }
/* While typing, the on-screen keyboard covers the bottom of the screen and
   would sit over these — so they step aside until the field loses focus. */
body:has(input:focus, textarea:focus) #float-actions { display: none; }

/* The stack hovers over the page, so the foot of every page needs room beneath
   it — otherwise the last row stays pinned under the buttons however far you
   scroll. Three buttons (2.8rem each), two gaps (.55rem), and the offset from
   the bottom edge. Wider screens show the arrow alone, which the 4rem already
   there clears. */
@media (max-width: 760px) {
  main { padding-bottom: calc(9.5rem + 1rem + env(safe-area-inset-bottom, 0px)); }
}

/* ------------------------------------------------ take a break (grounding) */

#break {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--paper);
  overflow-y: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem 1rem;
}
.break-card { max-width: 34rem; margin: auto; }
.break-card h1 { font-family: var(--serif); font-weight: 400; }
.break-steps {
  list-style: none;
  padding: 0;
  margin: .9rem 0;
  display: flex;
  flex-direction: column;
  gap: .55rem;
}
.break-steps li {
  display: flex;
  gap: .55rem;
  align-items: baseline; /* wrapped lines hang clear of the number */
}
.break-n {
  flex: 0 0 1.2rem;
  text-align: right;
  font-weight: 700;
  font-size: 1.15em;
  color: var(--accent);
}
.break-reassure { color: var(--ink-soft); margin: 1.1rem 0; }
#break .button-row { margin-top: 1rem; }

/* -------------------------------------------------------------------- lock */

#lock[hidden], #app[hidden] { display: none; }

#lock:not([hidden]) {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1rem;
}
.lock-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 1rem;
  padding: 2.2rem 2rem;
  max-width: 22rem;
  width: 100%;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: .8rem;
}
.lock-card h1 { font-family: var(--serif); font-weight: 400; }
.lock-card p { color: var(--ink-soft); margin: 0; }
.lock-section { display: flex; flex-direction: column; gap: .8rem; }
.lock-section[hidden] { display: none; }
.lock-label {
  text-align: left;
  color: var(--ink-soft);
  font-size: .9rem;
  margin-bottom: -.5rem;
}
.lock-show {
  display: flex;
  gap: .5rem;
  align-items: center;
  color: var(--ink-soft);
  font-size: .95rem;
}
.lock-toggle {
  background: none;
  border: none;
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
  font-size: .95rem;
  padding: .2rem;
}
.lock-ask {
  font-size: .95rem;
  line-height: 1.6;
  border-top: 1px solid var(--line);
  padding-top: .9rem;
  margin-top: .2rem;
}
.lock-ask a { color: var(--accent); }
.lock-note {
  background: var(--amber-soft);
  border-left: 3px solid var(--amber);
  padding: .6rem .8rem;
  border-radius: 4px;
  font-size: .95rem;
  line-height: 1.5;
  color: var(--ink);
}
.lock-note[hidden] { display: none; }

/* Busy guard — holds the whole screen while attachment files move */
#busy {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: color-mix(in srgb, var(--paper) 72%, transparent);
  backdrop-filter: blur(2px);
}
#busy[hidden] { display: none; }
.busy-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: .9rem;
  padding: 1.1rem 1.5rem;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .12);
  max-width: 24rem;
  display: flex;
  align-items: center;
  gap: .8rem;
  text-align: left;
}
.busy-spin {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  border: 2.5px solid var(--line);
  border-top-color: var(--accent);
  animation: busy-turn .9s linear infinite;
}
@keyframes busy-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .busy-spin {
    animation: busy-breathe 1.6s ease-in-out infinite;
    border-top-color: var(--line);
    background: var(--accent);
  }
  @keyframes busy-breathe { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
}

/* Admin — invite form rows */
.admin-invite-form {
  display: flex;
  gap: .6rem;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: .6rem;
}
.admin-invite-form input { flex: 1 1 220px; min-width: 0; }
.admin-invite-form .lock-show { white-space: nowrap; }
.admin-invite-result {
  display: flex;
  gap: .6rem;
  align-items: center;
  margin-bottom: .6rem;
}
.admin-invite-result input { flex: 1; font-size: .85rem; color: var(--ink-soft); }

/* Admin user/invite tables: search + sortable headers + a scroll box, so long
   lists stay contained instead of running down the page. */
.admin-controls { display: flex; align-items: center; gap: .8rem; margin: .2rem 0 .6rem; flex-wrap: wrap; }
.search-box { position: relative; flex: 1 1 220px; min-width: 0; display: flex; }
.search-box input[type="search"] { flex: 1; min-width: 0; padding-right: 2.1rem; }
/* Hide the browser's own clear button so there aren't two ✕s. */
.search-box input[type="search"]::-webkit-search-cancel-button { display: none; }
.search-clear {
  position: absolute; right: .3rem; top: 50%; transform: translateY(-50%);
  border: none; background: none; cursor: pointer; color: var(--ink-soft);
  font-size: .95rem; line-height: 1; padding: .25rem .4rem; border-radius: 50%;
}
.search-clear:hover { color: var(--ink); background: var(--paper); }
.admin-table-wrap { max-height: 60vh; overflow: auto; border: 1px solid var(--line); border-radius: .6rem; }
.admin-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.admin-table th, .admin-table td { text-align: left; padding: .5rem .7rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.admin-table tbody tr:last-child td { border-bottom: none; }
.admin-table thead th { position: sticky; top: 0; background: var(--card); z-index: 1; white-space: nowrap; }
.admin-table th.sortable { cursor: pointer; user-select: none; }
.admin-table th.sortable:hover { color: var(--accent); }
.admin-table th.sort-asc::after { content: ' ▲'; font-size: .7em; color: var(--accent); }
.admin-table th.sort-desc::after { content: ' ▼'; font-size: .7em; color: var(--accent); }
.admin-table tbody tr:hover { background: var(--paper); }
.admin-name { font-weight: 600; }
.admin-email, .admin-sub { display: block; color: var(--ink-soft); font-size: .82rem; }
.admin-badge { display: inline-block; margin-left: .35rem; font-size: .72rem; padding: 0 .4rem; border-radius: 1rem; background: var(--accent-soft); color: var(--accent); vertical-align: middle; }
.admin-actions .link-button { margin-right: .55rem; white-space: nowrap; }
.admin-table td:last-child { min-width: 8rem; }
.admin-table td:nth-child(3), .admin-table td:nth-child(4) { white-space: nowrap; }

/* Full-screen account journeys (invite setup, recovery, passphrase change) —
   the same calm card as the lock screen, a little roomier. */
#gate {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: var(--paper);
}
.gate-card { max-width: 28rem; text-align: left; }
.gate-card h1 { text-align: center; }
.gate-heading {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.35rem;
  margin: 0;
}
.suggest-box {
  background: var(--accent-soft);
  border-radius: .75rem;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: .4rem;
  align-items: center;
}
.suggest-words {
  font-family: var(--serif);
  font-size: 1.45rem;
  color: var(--accent);
  letter-spacing: .02em;
  text-align: center;
}
.phrase-chips {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .5rem .9rem;
  margin: .4rem 0;
  padding: 0;
  list-style: none;
}
.phrase-chips li {
  font-family: var(--serif);
  font-size: 1.3rem;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: .5rem;
  padding: .35rem .7rem;
  display: flex;
  align-items: baseline;
  gap: .55rem;
  min-width: 0;
}
.phrase-n {
  font-family: inherit;
  font-size: .85rem;
  color: var(--ink-soft);
}
/* ----------------------------------------------------------- modal + toast */

#modal {
  border: 1px solid var(--line);
  border-radius: 1rem;
  background: var(--card);
  color: var(--ink);
  padding: 1.6rem 1.5rem 1.3rem;
  max-width: 24rem;
  width: calc(100vw - 3rem);
  box-shadow: 0 10px 40px rgba(0, 0, 0, .18);
}
#modal::backdrop {
  background: rgba(51, 64, 58, .35);
  backdrop-filter: blur(2px);
}
#modal p { margin: 0 0 1rem; line-height: 1.55; }
#modal input { width: 100%; margin-bottom: 1rem; }
.modal-buttons {
  display: flex;
  justify-content: flex-end;
  gap: .6rem;
}
/* An offer that isn't available — greyed, and unclickable because the input
   inside it is disabled. Used when there's no storage room left for files. */
.button.is-disabled { opacity: .5; cursor: not-allowed; }

.button.danger-solid {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

#toast {
  position: fixed;
  bottom: 1.2rem;
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100vw - 2rem);
  text-align: center;
  text-wrap: balance;
  background: var(--ink);
  color: var(--paper);
  border-radius: 2rem;
  padding: .45rem 1.2rem;
  font-size: .92rem;
  /* Above the busy guard (200): a message that arrives just as the screen is
     held is exactly the one worth reading, so it must never be covered. */
  z-index: 210;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .2);
  transition: opacity .25s;
}
#toast[hidden] { display: none; }

/* ------------------------------------------------------------------ report */

.report {
  background: var(--report-bg);
  border: 1px solid var(--line);
  border-radius: .8rem;
  padding: clamp(1.2rem, 4vw, 3rem);
  max-width: 46rem;
}
.report-head {
  border-bottom: 2px solid var(--ink);
  padding-bottom: .8rem;
  margin-bottom: 1.6rem;
}
.report-head h1 { font-family: var(--serif); font-weight: 400; font-size: 1.8rem; }
.report-head p { color: var(--ink-soft); font-size: .9rem; }

.report-entry {
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--line);
  break-inside: avoid;
}
.report-gap {
  text-align: center;
  color: var(--ink-soft);
  font-style: italic;
  font-size: .9rem;
  padding: .8rem 0 .2rem;
}

.report-group { margin-top: 1.6rem; }
.report-group:first-of-type { margin-top: 0; }
.report-group-head {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.45rem;
  border-bottom: 2px solid var(--line);
  padding-bottom: .3rem;
  break-after: avoid;
}
.report-entry h2 { font-family: var(--serif); font-weight: 400; font-size: 1.25rem; }
.report-date { color: var(--ink-soft); font-size: .88rem; }
.report-attachments figure { margin: .8rem 0 0; }
.report-attachments img { max-width: 100%; max-height: 420px; border-radius: .4rem; }
.report-attachments figcaption { font-size: .85rem; color: var(--ink-soft); margin-top: .25rem; }
/* Photos unticked: the preview shows what the PDF will — the files listed by
   reference and name, without the pictures themselves. */
.report.no-photos .report-attachments figure[data-mime^="image/"] .attach-slot { display: none; }

@media print {
  :root, :root[data-theme-resolved="dark"] {
    --paper: #fff; --card: #fff; --report-bg: #fff; --field: #fff;
    --ink: #222; --ink-soft: #555; --line: #ccc;
    --accent: #7D5A68; --accent-soft: #eee; --amber: #a97b2f; --amber-soft: #f6f0e2;
  }
  .no-print, .sidebar { display: none !important; }
  #app { display: block; }
  body { background: #fff; }
  main { padding: 0; }
  .report { border: none; padding: 0; max-width: none; }
  a { color: inherit; text-decoration: none; }
}
