:root {
  --bg: #faf7f2;
  --card: #ffffff;
  --ink: #2b2925;
  --muted: #8a8378;
  --accent: #7c5cbf;
  --accent-soft: #ece5f8;
  --line: #e8e2d8;
  --serif: Georgia, "Times New Roman", serif;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.6;
}

main {
  max-width: 720px;
  margin: 0 auto;
  padding: 1.5rem 1rem 4rem;
}

/* Header */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .5rem;
  padding: .9rem 1.25rem;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
.brand {
  font-family: var(--serif);
  font-size: 1.4rem;
  font-weight: bold;
  color: var(--accent);
  text-decoration: none;
}
#nav-back {
  background: var(--accent-soft);
  color: var(--accent);
  border: none;
  border-radius: 8px;
  font-size: 1.15rem;
  padding: .15rem .6rem;
  cursor: pointer;
  margin-right: .3rem;
}
.site-header nav { display: flex; gap: 1rem; flex-wrap: wrap; align-items: center; }
.site-header nav a { color: var(--ink); text-decoration: none; font-size: .95rem; }
.site-header nav a:hover { color: var(--accent); }
/* Which account is signed in. A label, not a destination -- it is a <span>,
   because as a link it read as a fourth nav item and invited a click that only
   went where Settings already goes. Truncates instead of wrapping the nav onto
   a new line on a narrow phone. */
.nav-account {
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: .1rem .5rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent) !important;
  font-size: .85rem !important;
  cursor: default;
}
.nav-logout {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--muted); font-size: .95rem; font-family: inherit;
  margin-left: 2.5rem; /* distanced from the other links to prevent mis-clicks */
}
.nav-logout:hover { color: var(--accent); }

.site-footer { text-align: center; color: var(--muted); font-size: .85rem; padding: 1rem; }

/* Headings */
h1, h2, h3 { font-family: var(--serif); font-weight: 600; }
.page-head { display: flex; align-items: center; justify-content: space-between; }
.subtitle { color: var(--muted); margin-top: -0.5rem; }

/* Buttons and forms */
.button {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: .55rem 1.1rem;
  font-size: .95rem;
  text-decoration: none;
  cursor: pointer;
}
.button:hover { filter: brightness(1.08); }
.button.small { padding: .35rem .8rem; font-size: .85rem; }
.button.danger { background: #b3453f; }
.button-link { margin-left: .8rem; color: var(--muted); text-decoration: none; }
.button-link:hover { color: var(--ink); }
button.button-link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--muted);
  text-decoration: underline;
  cursor: pointer;
}
button.button-link:hover { color: var(--ink); }

/* Style allauth's plain buttons/links to match ours. `.button-link` is exempt:
   it is the deliberately quiet secondary action ("No thanks", "Not now"), and
   painting it the same purple as the primary button made the two look like a
   pair of equal choices. It reads as a link on an <a>; it now does on a
   <button> too. */
main form button:not(.link-button):not(.button-link) {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: .55rem 1.1rem;
  font-size: .95rem;
  cursor: pointer;
}
main form button.button.danger { background: #b3453f; }

form div { margin-bottom: .9rem; }
label { display: block; font-size: .9rem; color: var(--muted); }
input[type="text"], input[type="date"], input[type="search"],
input[type="email"], input[type="password"], textarea, select {
  width: 100%;
  padding: .55rem .7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
  font: inherit;
  color: var(--ink);
}
textarea { font-family: var(--serif); font-size: 1.05rem; }
.helptext { font-size: .8rem; color: var(--muted); }

/* Entry cards */
.entry-card, .entry-full {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 1.25rem 1.4rem;
  margin: 1.1rem 0;
}
.entry-date {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
.entry-location { color: var(--muted); font-size: .85rem; margin-left: .6rem; }
.entry-body { font-family: var(--serif); font-size: 1.08rem; }
.entry-full .entry-body { font-size: 1.15rem; }
.years-ago { color: var(--accent); font-style: italic; }
.title-time { color: var(--muted); font-size: .7em; font-weight: normal; }
.otd-link { margin: -0.4rem 0 0; }
.otd-link a { color: var(--accent); text-decoration: none; font-size: .92rem; }

/* Archive browser */
.archive {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: .5rem .9rem;
  margin-top: .8rem;
}
.archive summary { cursor: pointer; color: var(--muted); font-size: .92rem; }
.archive-year { margin: .55rem 0; display: flex; gap: .6rem; flex-wrap: wrap; align-items: baseline; }
.archive-year-link {
  font-family: var(--serif);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  min-width: 3.2rem;
}
.archive-months { display: inline-flex; gap: .35rem; flex-wrap: wrap; }
.archive-month {
  color: var(--accent);
  text-decoration: none;
  font-size: .88rem;
  background: var(--accent-soft);
  border-radius: 999px;
  padding: .05rem .55rem;
}
.archive-month .archive-count { color: var(--muted); font-size: .75em; margin-left: .25rem; }
.archive-month.current, .archive-year-link.current { background: var(--accent); color: #fff; border-radius: 999px; padding: .05rem .55rem; }
.archive-month.current .archive-count { color: #eee; }
.filter-note { color: var(--muted); font-size: .92rem; }
.filter-note a { color: var(--accent); }
.written-at { color: var(--muted); font-size: .8rem; float: right; }

.tag {
  display: inline-block;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 999px;
  padding: .1rem .65rem;
  font-size: .8rem;
  margin-right: .35rem;
}
.reply-count { font-size: .85rem; color: var(--accent); text-decoration: none; }

/* Media */
.media-grid { display: flex; flex-wrap: wrap; gap: .6rem; margin: .8rem 0; }
.media-grid img { max-height: 180px; max-width: 100%; border-radius: 8px; display: block; }
.media-grid video { max-height: 260px; max-width: 100%; border-radius: 8px; }
.media-grid audio { width: 100%; }

/* Thread */
.thread { margin-top: 2rem; }
.comment {
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 0 10px 10px 0;
  padding: .8rem 1rem .5rem;
  margin: .8rem 0;
}
.comment-meta { color: var(--muted); font-size: .8rem; }
.comment-body { font-family: var(--serif); }
.comment-body.deleted { color: var(--muted); font-style: italic; }
.comment-actions { margin-left: .6rem; }
.comment-actions a { color: var(--muted); font-size: .8rem; margin-right: .5rem; }
.inline-form { display: inline; margin: 0; }
.link-button {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--muted); font-size: .8rem; text-decoration: underline;
}
.link-button:hover, .comment-actions a:hover { color: #b3453f; }
.edited { font-style: italic; }
.entry-actions a { color: var(--muted); font-size: .85rem; margin-left: .7rem; text-decoration: none; }
.entry-actions a:hover { color: var(--accent); }
.entry-actions a.danger-link:hover { color: #b3453f; }
.entry-card.revision { opacity: .75; border-style: dashed; }
.media-manage { border: 1px solid var(--line); border-radius: 8px; }
.media-manage legend { font-size: .9rem; color: var(--muted); }
.media-remove { display: inline-flex; align-items: center; gap: .4rem; margin-right: 1rem; }
.media-remove img { max-height: 60px; border-radius: 6px; }
.media-remove input { width: auto; }
.comment-children { margin-left: 1.25rem; }
.reply-toggle summary {
  cursor: pointer;
  color: var(--accent);
  font-size: .85rem;
  margin-bottom: .5rem;
}
.comment-form { margin-top: 1rem; }
.empty-thread { color: var(--muted); font-style: italic; }

/* Search */
.search-form { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 1rem 1.2rem; }
.search-filters { display: flex; gap: 1rem; flex-wrap: wrap; }
.search-filters label { flex: 1 1 130px; }
.result-count { color: var(--muted); }

/* Login page */
.login-hero { max-width: 440px; margin: 1.5rem auto 0; text-align: center; }
.login-pitch { font-family: var(--serif); font-size: 1.08rem; }
.login-pitch-sub { color: var(--muted); font-size: .88rem; }
.passkey-big {
  width: 100%;
  padding: 1.05rem 1rem;
  font-size: 1.2rem;
  border-radius: 12px;
  box-shadow: 0 2px 10px rgba(124, 92, 191, .35);
}
.passkey-big::before { content: "👤 "; }
.login-divider { border: 0; border-top: 1px solid var(--line); margin: 1.6rem 0 1rem; }
.login-email { text-align: left; }
.login-email-title { font-size: 1.05rem; text-align: center; margin-bottom: .8rem; }

/* Voice notes */
.recorder { margin: .6rem 0; display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; }
.recorder-preview { flex-basis: 100%; }
.recorder-preview audio { width: 100%; max-width: 360px; display: block; margin-bottom: .3rem; }
.recorder-start.recording {
  background: #b3453f;
  border-color: #b3453f;
  color: #fff;
  animation: recording-pulse 1.4s ease-in-out infinite;
}
@keyframes recording-pulse { 50% { opacity: .72; } }
@media (prefers-reduced-motion: reduce) {
  .recorder-start.recording { animation: none; }
}

/* Draft restored / available */
.draft-banner {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  align-items: center;
  justify-content: space-between;
  background: #fdf6e3;
  border: 1px solid #e8d9a0;
  border-radius: 10px;
  padding: .6rem .9rem;
  margin: 0 0 .8rem;
  font-size: .9rem;
}
.draft-banner-text::before { content: "📝 "; }
/* A disabled button should look disabled — while one button says "Saving…",
   the others on the form are greyed rather than silently inert. */
button[disabled], input[type=submit][disabled], .button[disabled] {
  opacity: .55;
  cursor: default;
  box-shadow: none;
}

.draft-banner-warn { background: #fdecea; border-color: #f5b7b1; }
.draft-banner-warn .draft-banner-text::before { content: "⚠️ "; }
.draft-banner-actions { display: flex; gap: .6rem; align-items: center; }

/* Signup — the privacy choice at the door */
.signup-page { max-width: 620px; margin: 1.5rem auto 0; }
.signup-page h1 { text-align: center; margin-bottom: .2rem; }
.signup-page .login-pitch { text-align: center; margin-top: 0; }
.signup-field { margin: .8rem 0; }
.signup-terms { margin: 1.2rem 0; font-size: .9rem; }
/* Grid, not flex: the label text contains inline links, and flexing the label
   would lay each link out as its own column. */
.signup-terms label {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .55rem;
  align-items: start;
  line-height: 1.5;
}
.signup-terms input { margin-top: .25rem; }
.signup-field .helptext ul { margin: .3rem 0 0; padding-left: 1.1rem; }
.privacy-choice { border: 0; padding: 0; margin: 1.6rem 0 1rem; }
.privacy-choice legend { font-weight: 600; font-size: 1.05rem; padding: 0; }
.privacy-intro { color: var(--muted); font-size: .9rem; margin: .3rem 0 .8rem; }
.privacy-card {
  display: block;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .9rem 1.1rem;
  margin-bottom: .8rem;
  cursor: pointer;
}
.privacy-card:hover { border-color: var(--accent); }
.privacy-card:has(input:checked) {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(124, 92, 191, .25);
}
.privacy-card input { float: left; margin: .35rem .7rem 0 0; }
.privacy-card-body { display: block; overflow: hidden; }
.privacy-card-title { display: block; font-weight: 600; font-size: 1.05rem; }
.privacy-card-sub { display: block; color: var(--muted); font-size: .9rem; margin-bottom: .45rem; }
.privacy-card-points { display: block; font-size: .88rem; line-height: 1.5; }
.privacy-switch { color: var(--muted); font-size: .85rem; }
/* The chooser at /choose-privacy/: each card is its own form, and the
   recommended one is meant to look recommended. Cursor stays default because
   here the button is the click target, not the whole card. */
.privacy-card form, form.privacy-card { cursor: default; }
.privacy-card.recommended {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(124, 92, 191, .25);
}
.privacy-recommended {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .02em;
  border-radius: 999px;
  padding: .15rem .6rem;
  margin-bottom: .5rem;
}
.privacy-card .button, .privacy-card .button-link { margin-top: .8rem; }
.form-errors { color: #b3261e; }

/* Security checklist */
.security-checklist {
  background: #fdf6e3;
  border: 1px solid #e8d9a0;
  border-radius: 12px;
  padding: 1rem 1.4rem;
  margin: 1.2rem 0;
}
.security-checklist h3 { margin: 0 0 .3rem; }
.security-checklist p { margin: .2rem 0; color: var(--muted); font-size: .92rem; }
.security-checklist ul { list-style: none; padding: 0; margin: .6rem 0; }
.security-checklist li { margin: .45rem 0; }
.security-checklist li.done { color: var(--muted); }
.security-checklist a { color: var(--accent); }
.checklist-more { font-size: .9rem; }
.site-footer a { color: var(--muted); }

/* Landing */
.landing { text-align: center; padding-top: 1.5rem; }
/* Smaller than it was (founder 2026-08-18: "it doesn't have to be so big").
   Clamped rather than fixed so it never dominates a narrow phone screen. */
.landing-title { font-size: clamp(1.45rem, 5vw, 1.85rem); line-height: 1.25; }
.landing-lede {
  font-family: var(--serif);
  font-size: 1.12rem;
  max-width: 560px;
  margin: 0 auto 1rem;
}
/* The story row sits directly under the title, so it needs less air above it
   than the principles row further down. */
.landing-story { margin-top: 1.4rem; }
.landing-principles {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 2.2rem 0;
  text-align: left;
}
.principle {
  flex: 1 1 180px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .3rem 1.1rem .8rem;
}
/* Slightly smaller than a default h3: at three-across these headings are only
   ~14 characters wide, and the full size orphaned a word off most of them. */
.principle h3 { margin-bottom: .2rem; font-size: 1.02rem; line-height: 1.3; }
.principle p { color: var(--muted); font-size: .92rem; margin: 0; }
/* The objection-handler above the CTA. Deliberately not a .principle card:
   it answers a question rather than listing a feature, so it gets the full
   width and the serif voice of the lede instead of sitting in the row. */
.landing-answer {
  max-width: 560px;
  margin: 2.2rem auto 0;
  text-align: left;
}
.landing-answer h3 { margin-bottom: .3rem; }
.landing-answer p {
  font-family: var(--serif);
  font-size: 1.05rem;
  color: var(--muted);
  margin: 0;
}
/* The two-factor page's option cards. The recommended one is ringed the same
   way the privacy chooser rings its recommendation, so "this is the one" reads
   identically in both places a new account has to make a choice. */
.mfa-option h2 { margin: .2rem 0 .1rem; font-size: 1.15rem; }
.mfa-option.recommended {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(124, 92, 191, .25);
}
.mfa-option .button, .mfa-option .button-link { margin-top: .6rem; }
/* "Not now" / "Don't remind me again" -- deliberately plain and equal-weight.
   Making the dismissal hard to find would be the dark pattern this product
   says it does not build. */
.checklist-dismiss { margin-top: .6rem; display: flex; gap: 1.2rem; }
.checklist-dismiss .button-link { margin-left: 0; font-size: .85rem; }
/* Authenticator-app setup, step by step. */
.totp-escape { margin: -.4rem 0 1.2rem; }
.totp-apps { margin: .4rem 0 0; padding-left: 1.2rem; font-size: .92rem; color: var(--muted); }
.totp-apps li { margin-bottom: .25rem; }
.totp-qr { text-align: center; margin: .8rem 0; }
/* White plate behind the code: a QR on a cream background scans less reliably
   on a cheap camera, and this page exists for people who will blame
   themselves when it does not work. */
.totp-qr img {
  width: 190px; height: 190px;
  background: #fff; padding: .6rem; border-radius: 10px;
}
.totp-manual summary { cursor: pointer; font-size: .9rem; color: var(--accent); }
.totp-secret {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 1.02rem; letter-spacing: .06em; word-break: break-all;
  background: var(--accent-soft); border-radius: 8px; padding: .5rem .7rem;
}
/* The name, explained. Typographic rather than another card -- six cards
   already sit either side of it, and this is the one beat on the page that
   should feel like someone saying something rather than listing something. */
.landing-name {
  max-width: 560px;
  margin: 2.4rem auto;
  text-align: left;
}
.landing-name p {
  font-family: var(--serif);
  font-size: 1.08rem;
  margin: 0 0 .8rem;
}
.landing-name-mark {
  font-size: 1.6rem !important;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: .01em;
  margin-bottom: .5rem !important;
}
.landing-name-mark span { opacity: .45; padding: 0 .12em; }
.landing-cta { margin-top: 1.5rem; }
/* Sign up and sign in as equals. Wraps rather than shrinking on a narrow
   phone, so neither ever ends up too small to hit. */
.landing-buttons {
  display: flex;
  gap: .8rem;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: .9rem;
}
.landing-note { color: var(--muted); font-size: .9rem; }

/* App lock */
#app-lock {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.app-lock-brand { font-family: var(--serif); font-size: 2rem; font-weight: bold; color: var(--accent); }
.app-lock-inner p { color: var(--muted); }
.app-lock-alt a { color: var(--muted); font-size: .85rem; }
body.app-locked main, body.app-locked .site-header { filter: blur(14px); }

/* Vault / E2EE */
.faceid-nudge {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .8rem;
  flex-wrap: wrap;
  background: var(--accent-soft);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: .6rem 1rem;
  margin-bottom: 1rem;
  font-size: .92rem;
}
.faceid-nudge-actions { display: flex; gap: .5rem; align-items: center; }
.recovery-key {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 1.15rem;
  letter-spacing: .06em;
  background: var(--accent-soft);
  border-radius: 8px;
  padding: .8rem 1rem;
  text-align: center;
  word-break: break-all;
}
.enc-body .enc-note { color: var(--muted); font-style: italic; }
.enc-clamp { max-height: 14em; overflow: hidden; }
/* Encrypted short field (a location): decrypted in place by enc.js. */
.enc-text { color: var(--muted); }
/* Photo viewer (gallery.js): full-screen, swipe or arrows between photos. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .93);
  /* Respect the phone's notch/home indicator. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
.lightbox[hidden] { display: none; }
body.lightbox-open { overflow: hidden; }
.lb-img {
  max-width: 96vw;
  max-height: 88vh;
  object-fit: contain;
  border-radius: 4px;
  /* Let the phone pinch-zoom the photo itself. */
  touch-action: pinch-zoom;
}
.lightbox button {
  background: rgba(255, 255, 255, .12);
  color: #fff;
  border: 0;
  cursor: pointer;
  line-height: 1;
}
.lb-close {
  position: absolute;
  top: calc(env(safe-area-inset-top) + .6rem);
  right: .8rem;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  font-size: 1.6rem;
}
.lb-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 2.8rem;
  height: 4rem;
  border-radius: 6px;
  font-size: 2rem;
}
.lb-nav[hidden] { display: none; }
.lb-prev { left: .5rem; }
.lb-next { right: .5rem; }
.lb-bar {
  position: absolute;
  bottom: calc(env(safe-area-inset-bottom) + .8rem);
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.2rem;
  color: rgba(255, 255, 255, .8);
  font-size: .9rem;
}
.lb-save {
  color: #fff;
  text-decoration: none;
  background: rgba(255, 255, 255, .12);
  padding: .35rem .9rem;
  border-radius: 999px;
}
@media (hover: none) {
  /* On touch devices the swipe is the gesture; keep the arrows small. */
  .lb-nav { opacity: .55; }
}

/* Encrypted media placeholder: swapped for the real element by enc.js. */
.enc-media {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  min-height: 6rem;
  padding: .8rem;
  border-radius: 8px;
  background: rgba(124, 92, 191, .07);
  color: var(--muted);
  font-size: .9rem;
  text-align: center;
}
.helptext.error { color: #b3453f; }

/* Tag manager */
.tag-row {
  display: flex;
  align-items: center;
  gap: .8rem;
  flex-wrap: wrap;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: .55rem .9rem;
  margin: .5rem 0;
}
.tag-count { color: var(--muted); font-size: .85rem; }
.tag-actions { display: flex; gap: .4rem; margin-left: auto; align-items: center; }
.tag-actions input[type="text"] { width: 11rem; padding: .35rem .55rem; }

/* Back to top */
#to-top {
  position: fixed;
  right: 1.1rem;
  bottom: 1.3rem;
  z-index: 900;
  width: 2.9rem;
  height: 2.9rem;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: #fff;
  font-size: 1.3rem;
  cursor: pointer;
  box-shadow: 0 3px 12px rgba(43, 41, 37, .25);
  opacity: .85;
}
#to-top:hover { opacity: 1; }

/* Misc */
.empty-state {
  text-align: center;
  color: var(--muted);
  background: var(--card);
  border: 1px dashed var(--line);
  border-radius: 12px;
  padding: 2.5rem 1rem;
  margin-top: 1.5rem;
}
.pagination { display: flex; justify-content: space-between; align-items: center; color: var(--muted); margin-top: 1.5rem; }
.pagination a { color: var(--accent); text-decoration: none; }
.messages { list-style: none; max-width: 720px; margin: 1rem auto 0; padding: 0 1rem; }
.msg { background: var(--accent-soft); border-radius: 8px; padding: .5rem .9rem; margin-bottom: .4rem; }

/* Attachments on a composer: whatever is on the form right now, playable and
   removable — including files restored from a draft, which used to be
   invisible. */
.attachments { margin: .6rem 0; }
.attachment {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem;
  padding: .5rem .7rem;
  margin-bottom: .4rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.attachment img { max-height: 64px; border-radius: 6px; }
.attachment audio { max-width: 260px; }
.attachment video { max-height: 90px; }
.attachment-name { font-size: .85rem; color: var(--muted); flex: 1 1 8rem; word-break: break-word; }
.attachment-remove { color: #b3453f; }

/* ---------------------------------------------------------------- Emotions --
   Who inside you is speaking on a line (journal/emotions.py). The colour comes
   from the name itself, as a hue set inline by the renderer, so a palette of
   any size stays legible without the stylesheet knowing a single emotion by
   name -- and "Fear" is the same colour in an entry written today, in one
   restored from an export, and in a journal imported into another account. */
.emotion {
  display: inline-block;
  background: hsl(var(--emotion-hue, 265) 70% 94%);
  color: hsl(var(--emotion-hue, 265) 55% 32%);
  border-radius: 999px;
  padding: .02rem .55rem;
  margin-right: .35rem;
  font-family: var(--sans);
  font-size: .82em;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  vertical-align: baseline;
}

/* The chip row above a composer. Scrolls sideways rather than wrapping into
   three rows on a phone: the textarea is what should be on screen, not the
   menu above it. */
.emotion-bar { margin: .2rem 0 .4rem; }
.emotion-bar-row {
  display: flex;
  align-items: center;
  gap: .35rem;
}
/* Only the chips scroll. The label stays put and so does "+ emotion" -- a long
   palette must never push the button that grows it off the screen. */
.emotion-chip-scroll {
  display: flex;
  align-items: center;
  gap: .35rem;
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  padding-bottom: .25rem;
  -webkit-overflow-scrolling: touch;
}
.emotion-bar-label {
  color: var(--muted);
  font-size: .8rem;
  white-space: nowrap;
  margin-right: .15rem;
}
/* Paired selectors, not another :not() on the blanket rule above: adding a
   :not() there raises that rule for EVERY button and turns Delete purple.
   The second half here matches its weight exactly -- three types (main, form,
   button) and two classes, the blanket rule's two coming from its :not()
   arguments -- and wins the tie by sitting later in the file. */
.emotion-chip,
main form .emotion-bar button.emotion-chip {
  flex: none;
  background: hsl(var(--emotion-hue, 265) 70% 96%);
  color: hsl(var(--emotion-hue, 265) 55% 32%);
  border: 1px solid hsl(var(--emotion-hue, 265) 45% 86%);
  border-radius: 999px;
  padding: .2rem .7rem;
  font-size: .85rem;
  font-family: var(--sans);
  cursor: pointer;
  white-space: nowrap;
}
.emotion-chip.is-on,
main form .emotion-bar button.emotion-chip.is-on {
  background: hsl(var(--emotion-hue, 265) 60% 40%);
  border-color: hsl(var(--emotion-hue, 265) 60% 40%);
  color: #fff;
}
.emotion-chip-new,
main form .emotion-bar button.emotion-chip-new { color: var(--muted); border-style: dashed; background: transparent; }
.emotion-add {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
  margin-top: .35rem;
}
/* [hidden] is display:none only while nothing else sets display -- a flex
   row would ignore it and the add-a-emotion box would sit open forever. */
.emotion-add[hidden] { display: none; }
.emotion-add input[type="text"] { padding: .3rem .5rem; }
/* Beats the full-width rule every text input in a form otherwise gets. */
input[type="text"].emotion-add-emoji { width: 3.4rem; text-align: center; }
input[type="text"].emotion-add-name { width: 12rem; }
.emotion-add-note { color: var(--muted); font-size: .78rem; flex: 1 1 12rem; }
.emotion-new-form {
  display: flex;
  gap: .4rem;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.emotion-new-form input[type="text"] { padding: .35rem .55rem; }

/* The landing beat. A worked example, because "each line gets an emotion" is one
   of those ideas that takes a paragraph to explain and a second to see. */
.landing-emotions {
  max-width: 560px;
  margin: 2.4rem auto;
  text-align: left;
}
.landing-emotions h3 { margin-bottom: .3rem; }
.landing-emotions > p {
  font-family: var(--serif);
  font-size: 1.08rem;
  margin: 0 0 .9rem;
}
.landing-demo {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .9rem 1rem;
  font-family: var(--serif);
  font-size: 1rem;
}
.landing-demo p { margin: 0 0 .45rem; }
.landing-demo p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------- passphrase strength
   The verdict under the passphrase field (static/js/passphrase.js). Colour
   carries the level, but never alone -- the message says the same thing in
   words, because a colour is not readable to everyone and this is the one
   field where misunderstanding is unrecoverable. */
.pp-meter {
  font-size: .85rem;
  line-height: 1.45;
  margin: -.4rem 0 .7rem;
}
.pp-meter[data-level="blocked"],
.pp-meter[data-level="weak"] { color: #b3453f; }
.pp-meter[data-level="fair"] { color: #8a6414; }
.pp-meter[data-level="strong"] { color: #2c7a54; }

/* A generated passphrase, shown because one nobody ever saw is a locked
   journal. Same treatment as the recovery key, which is the same kind of
   "write this down now" moment. */
.generated {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 1.05rem;
  letter-spacing: .04em;
  background: var(--accent-soft);
  border-radius: 8px;
  padding: .7rem .9rem;
  word-break: break-word;
  margin: .2rem 0 .8rem;
}
