/* Tokens match the phone themes in Resources/Themes/{Day,Night,Kgb}Theme.xaml */

:root,
html[data-theme="day"],
html[data-theme="auto"] {
  --page: #f3f7f8;
  --surface: #ffffff;
  --muted: #e7eef0;
  --text: #14242b;
  --secondary: #5b6b73;
  --accent: #0f7b6c;
  --accent-soft: #d7f1ec;
  --mint: #d7f1ec;
  --deep: #0a3d3a;
  --hairline: #d5dee2;
  --danger: #b42318;
  --tab: #7a8a92;
  --hero-deep: #0a3d3a;
  --hero-mid: #0f7b6c;
  --hero-mist: #b8e4dc;
  --hero-ink: #d7f1ec;
  --shadow: #3d14242b;
  --on-accent: #ffffff;
  --ink-btn: #14242b;
  --ink-btn-text: #f3f7f8;
}

html[data-theme="night"] {
  --page: #0e1518;
  --surface: #182227;
  --muted: #223038;
  --text: #e8eef0;
  --secondary: #9aabb5;
  --accent: #3dcfb6;
  --accent-soft: #143d38;
  --mint: #d7f1ec;
  --deep: #061816;
  --hairline: #2a383f;
  --danger: #ff7a6e;
  --tab: #a7b7c0;
  --hero-deep: #061816;
  --hero-mid: #1a9e8c;
  --hero-mist: #163a36;
  --hero-ink: #e8f2f0;
  --shadow: #99000000;
  --on-accent: #061816;
  --ink-btn: #e8eef0;
  --ink-btn-text: #0e1518;
}

html[data-theme="kgb"] {
  --page: #14080e;
  --surface: #1f1018;
  --muted: #2a1520;
  --text: #f4e8d0;
  --secondary: #c4a882;
  --accent: #c9a227;
  --accent-soft: #3a1a24;
  --mint: #f4e8d0;
  --deep: #1a0610;
  --hairline: #3a2430;
  --danger: #e85a4f;
  --tab: #c5a37f;
  --hero-deep: #1a0610;
  --hero-mid: #8b1e3f;
  --hero-mist: #3a1524;
  --hero-ink: #f4e8d0;
  --shadow: #99000000;
  --on-accent: #14080e;
  --ink-btn: #f4e8d0;
  --ink-btn-text: #14080e;
}

@media (prefers-color-scheme: dark) {
  html[data-theme="auto"] {
    --page: #0e1518;
    --surface: #182227;
    --muted: #223038;
    --text: #e8eef0;
    --secondary: #9aabb5;
    --accent: #3dcfb6;
    --accent-soft: #143d38;
    --mint: #d7f1ec;
    --deep: #061816;
    --hairline: #2a383f;
    --danger: #ff7a6e;
    --tab: #a7b7c0;
    --hero-deep: #061816;
    --hero-mid: #1a9e8c;
    --hero-mist: #163a36;
    --hero-ink: #e8f2f0;
    --shadow: #99000000;
    --on-accent: #061816;
    --ink-btn: #e8eef0;
    --ink-btn-text: #0e1518;
  }
}

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

html,
body {
  margin: 0;
  min-height: 100%;
  background: #050f0e;
  color: var(--text);
  font-family: "Sora", "Segoe UI", system-ui, sans-serif;
}

/*
  The app shell is a column on a phone and a contained panel on a large screen. Legal pages
  keep their own layout; they are not this shell.
*/
body:not(.legal-page) {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-height: 100dvh;
}

.symbol,
.tab-icon,
.morsel,
.action-tile span,
.trust-lock,
.digest-mark,
.struct-glyph,
.think-glyph,
.story-x,
.prop-glyph,
.prop-icon,
.prop-person li span {
  font-family: "Material Symbols Outlined", sans-serif;
  font-weight: 400;
  font-style: normal;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24;
  -webkit-font-smoothing: antialiased;
}

.phone {
  width: 100%;
  flex: 1 1 auto;
  min-height: 100dvh;
  background: var(--page);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  z-index: 1;
}

/*
  Sign-in shares the page with the public about block. Forcing the panel to a full viewport
  height under that block is how the form and the about were squeezed side by side on a phone.
*/
body.is-login .phone {
  min-height: 0;
  flex: 1 1 auto;
}

.phone:not(.is-home):not(.is-login)::before,
.phone:not(.is-home):not(.is-login)::after {
  content: "";
  position: absolute;
  pointer-events: none;
  border-radius: 50%;
  z-index: 0;
}

/*
  Soft-edged, like PageAtmosphere on the phone. A flat circle draws its own rim, and against a
  translucent nav bar that rim reads as a pane sliding around behind the content.
*/
.phone:not(.is-home):not(.is-login)::before {
  width: 280px;
  height: 280px;
  top: -48px;
  right: -90px;
  background: radial-gradient(circle closest-side, var(--hero-mist), transparent);
  opacity: 0.32;
}

.phone:not(.is-home):not(.is-login)::after {
  width: 190px;
  height: 190px;
  bottom: 100px;
  left: -70px;
  background: radial-gradient(circle closest-side, var(--accent-soft), transparent);
  opacity: 0.24;
}

.phone.is-home,
.phone.is-login {
  background: var(--hero-deep);
}

.phone.is-login {
  background: var(--page);
}

.navbar {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: calc(0.45rem + env(safe-area-inset-top, 0px)) 1rem 0.55rem;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 4;
  background: color-mix(in srgb, var(--page) 62%, transparent);
  backdrop-filter: saturate(1.2) blur(18px);
  -webkit-backdrop-filter: saturate(1.2) blur(18px);
}

.navbar-title {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
}

.stage {
  flex: 1;
  min-height: 0;
  overflow: auto;
  position: relative;
  z-index: 1;
}

.view[hidden],
[hidden] {
  display: none !important;
}

.view:not(.view-home):not(.view-login) {
  padding: calc(3.65rem + env(safe-area-inset-top, 0px)) 1.1rem 5.75rem;
}

.view-login {
  padding: 3rem 1.5rem 2rem;
  background: var(--page);
  min-height: 100%;
}

.login-brand {
  margin: 0 0 0.35rem;
  text-align: center;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--accent);
}

.login-heading {
  margin: 0;
  font-size: 2.25rem;
  font-weight: 600;
  text-align: center;
}

.login-subtitle {
  margin: 0.65rem 0 1.35rem;
  text-align: center;
  color: var(--secondary);
}

.login-card .btn {
  width: 100%;
}

.view-home {
  padding: 0;
}

.hero {
  position: relative;
  overflow: hidden;
  padding: 3rem 1.5rem 1.25rem;
  background: var(--hero-deep);
  color: #fff;
}

.hero-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.hero-orb-a {
  width: 280px;
  height: 280px;
  top: -40px;
  right: -80px;
  background: radial-gradient(circle closest-side, var(--hero-mist), transparent);
  opacity: 0.32;
  animation: drift-a 9s ease-in-out infinite alternate;
}

.hero-orb-b {
  width: 180px;
  height: 180px;
  top: 42%;
  left: -60px;
  background: radial-gradient(circle closest-side, var(--accent-soft), transparent);
  opacity: 0.4;
  animation: drift-b 11s ease-in-out infinite alternate;
}

@keyframes drift-a {
  from { transform: translate(0, 0); }
  to { transform: translate(-18px, 12px); }
}

@keyframes drift-b {
  from { transform: translate(0, 0); }
  to { transform: translate(14px, -10px); }
}

.brand {
  position: relative;
  margin: 0 0 0.7rem;
  font-size: 2.5rem;
  font-weight: 600;
}

.headline {
  position: relative;
  margin: 0 0 0.55rem;
  font-size: 1.85rem;
  line-height: 1.12;
  font-weight: 600;
}

.hero-support {
  position: relative;
  margin: 0 0 0.9rem;
  color: var(--hero-ink);
  font-size: 0.95rem;
}

.trust-banner {
  position: relative;
  display: flex;
  gap: 0.65rem;
  align-items: center;
  background: #d7f1ec;
  color: var(--deep);
  border-radius: 14px;
  padding: 0.7rem 0.85rem;
  margin-bottom: 1rem;
  box-shadow: 0 6px 16px rgba(10, 61, 58, 0.35);
}

.trust-banner p {
  margin: 0;
  font-size: 0.82rem;
}

.trust-lock {
  font-size: 1.15rem;
}

.walk {
  position: relative;
  overflow: hidden;
  min-height: 13.5rem;
  margin: 0 0 1rem;
  padding: 1.15rem 1.2rem 1.25rem;
  border-radius: 22px;
  background: #0a2e2b;
  color: #fff;
  text-align: center;
  cursor: pointer;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
}

html[data-theme="night"] .walk,
html[data-theme="kgb"] .walk {
  background: color-mix(in srgb, var(--hero-deep) 70%, black);
}

.walk-ripples span {
  position: absolute;
  inset: 18% 12%;
  border: 1.5px solid #6fb8ac;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  animation: ripple 4.8s ease-out infinite;
}

.walk-ripples span:nth-child(2) { animation-delay: 1.6s; }
.walk-ripples span:nth-child(3) { animation-delay: 3.2s; }

@keyframes ripple {
  0% { transform: scale(0.55); opacity: 0.35; }
  70% { transform: scale(1.15); opacity: 0; }
  100% { transform: scale(1.15); opacity: 0; }
}

.walk h2 {
  position: relative;
  margin: 0.45rem 0 0.4rem;
  font-size: 1.25rem;
}

.walk p {
  position: relative;
  margin: 0;
}

#walk-body {
  color: #d7f1ec;
  font-size: 0.9rem;
  line-height: 1.4;
}

.walk-progress {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #a8d5cd;
}

.walk-dots {
  display: flex;
  justify-content: center;
  gap: 0.4rem;
  margin: 0.45rem 0 0.2rem;
}

.walk-dots i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #fff;
  opacity: 0.28;
}

.walk-dots i.on {
  opacity: 1;
}

.walk-chip {
  margin: 0.85rem auto 0;
  background: #d7f1ec;
  color: #0a3d3a;
}

.walk:focus-visible {
  outline: 2px solid var(--mint);
  outline-offset: 3px;
}

.hero .btn {
  position: relative;
  width: 100%;
  margin-top: 0.55rem;
  display: flex;
}

.below-fold {
  padding: 1.35rem 1.5rem 6rem;
  background: var(--page);
  color: var(--text);
}

.below-fold h2 {
  margin: 0 0 0.75rem;
  font-size: 1.35rem;
}

.below-fold h2:not(:first-child) {
  margin-top: 1.75rem;
}

h1, h2 {
  font-weight: 600;
}

.page-title {
  margin: 0.2rem 0 0.15rem;
  font-size: 1.5rem;
  text-align: center;
}

.digest-date {
  margin: 0 0 0.65rem;
  text-align: center;
  color: var(--secondary);
  font-size: 0.95rem;
}

.lede,
.hint,
.empty,
.appetite,
.or {
  color: var(--secondary);
}

.lede {
  margin: 0 0 1rem;
  line-height: 1.45;
  font-size: 0.95rem;
}

.center {
  text-align: center;
}

#digest-summary {
  white-space: pre-line;
}

.stack,
.drop,
.ask {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.82rem;
  color: var(--secondary);
}

input,
textarea {
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  padding: 0.85rem 0.95rem;
}

/*
  A borderless field inside a card takes its breathing room from the card, so it keeps no left
  inset of its own and stays flush with the card's other text.
*/
.card textarea,
.compose textarea {
  background: transparent;
  border: 0;
  padding: 0.3rem 0;
  min-height: 5.5rem;
  resize: vertical;
}

/*
  The browser's own focus ring is drawn tight to the text box, which on a field with no inset of
  its own reads as a border touching the first letter. Ours is held off the text.
*/
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 65%, transparent);
  outline-offset: 4px;
}

.card {
  background: var(--surface);
  border-radius: 18px;
  padding: 0.95rem 1rem;
  box-shadow: 0 8px 18px color-mix(in srgb, var(--shadow) 65%, transparent);
}

.btn,
.text-btn {
  font: inherit;
  cursor: pointer;
}

.btn {
  border: 0;
  border-radius: 16px;
  padding: 0.85rem 1rem;
  font-weight: 600;
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  text-decoration: none;
}

.btn-primary {
  background: var(--accent);
  color: #fff;
}

.btn-on-hero {
  background: #fff;
  color: var(--hero-deep);
}

.btn-mint {
  background: #d7f1ec;
  color: #0a3d3a;
}

.btn-ink {
  background: var(--ink-btn);
  color: var(--ink-btn-text);
}

/*
  The two vendor sign-in buttons. Every value below is from Apple's Human Interface Guidelines
  or Google's sign-in branding guidelines rather than from this app's design: the colours, the
  #747775 stroke, the 18px mark with its 12px of clear space, the typefaces. They deliberately
  do not inherit .btn, because matching our styling is exactly what both vendors prohibit.

  Apple has no web font, so the stack asks for San Francisco by the route a browser offers it
  and falls back to whatever the system calls its own.
*/
.signin-apple,
.signin-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  height: 48px;
  padding: 0 12px;
  border-radius: 24px;
  cursor: pointer;
  white-space: nowrap;
}

.signin-mark {
  width: 18px;
  height: 18px;
  flex: none;
}

.signin-apple {
  background: #000;
  color: #fff;
  border: none;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: 17px;
  font-weight: 400;
}

.signin-apple .signin-mark {
  /* Apple's mark is taller than it is wide; height leads, width follows. */
  width: 17px;
  height: 21px;
  margin-bottom: 2px;
}

.signin-google {
  background: #fff;
  color: #1f1f1f;
  border: 1px solid #747775;
  font-family: "Roboto", system-ui, sans-serif;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.25px;
}

.signin-apple:hover {
  background: #1a1a1a;
}

.signin-google:hover {
  background: #f7f8f8;
}

.btn-outline,
.btn-ghost,
.btn-chip {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--hairline);
}

.btn-chip.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.text-btn {
  background: none;
  border: 0;
  color: var(--secondary);
  padding: 0.4rem 0;
}

/*
  The switch under Sign in / Create account. The sentence is secondary; the act is the
  accent, so "Sign in" and "Create an account" read as something you can press.
*/
.login-switch {
  text-align: center;
}

.login-switch-action {
  color: var(--accent);
  font-weight: 600;
}

.or {
  text-align: center;
  font-size: 0.75rem;
}

.error {
  color: var(--danger);
  margin: 0.4rem 0;
}

.chip {
  display: inline-flex;
  align-items: center;
  border-radius: 12px;
  padding: 0.35rem 0.85rem;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 600;
}

.dark-on-mint {
  background: var(--mint);
  color: var(--deep);
}

.insight,
.answer,
.feed li {
  background: var(--surface);
  border-radius: 18px;
  padding: 0.95rem 1.05rem;
  box-shadow: 0 8px 18px color-mix(in srgb, var(--shadow) 55%, transparent);
}

/*
  The bucket in days. A list that only grows cannot be a list: without a heading saying what a
  day holds and a cap on what it draws, every screen of it looks like the one before.
*/
.bucket-head {
  margin-top: 1.2rem;
}

.bucket-head .chips {
  margin: 0.5rem 0 0;
}

.chip-btn {
  border: 0;
  cursor: pointer;
  font-family: inherit;
}

.chip-btn.on {
  background: var(--accent);
  color: #fff;
}

.bucket-day {
  margin-top: 1.1rem;
}

.bucket-day-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}

.bucket-day-head h3 {
  margin: 0;
  font-size: 0.95rem;
}

.bucket-day-head .meta {
  margin: 0.1rem 0 0;
}

.bucket-day .feed {
  margin-top: 0.55rem;
}

#bucket-older {
  margin-top: 1.1rem;
  width: 100%;
}

.insight {
  background: var(--accent-soft);
  margin-bottom: 0.9rem;
}

.insight-kicker {
  margin: 0 0 0.25rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--accent);
}

.insight p,
.answer p {
  margin: 0.2rem 0 0;
  line-height: 1.45;
}

/* One row per person, the same as the phone draws under an answer. */
.sources-heading {
  margin: 0.8rem 0 0.15rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--secondary);
}

.sources {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sources .source {
  padding: 0.2rem 0;
  font-size: 0.8rem;
  color: var(--accent);
}

.feed {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

/*
  A card that follows the feed needs its own air. Both draw the same surface with the same
  radius and the same shadow, so with nothing between them the last row and the card behind it
  read as one control with a seam through it — on People, "You" and the Ask box looked like a
  single broken card.

  A general sibling rather than an adjacent one: every list here has an empty-state paragraph
  sitting between it and whatever follows, and that paragraph is still a sibling when it is
  hidden. Written with "+" this rule matched nothing at all on the screen it was written for.
*/
.feed ~ .card,
.card + .card {
  margin-top: 0.9rem;
}

.feed li button {
  all: unset;
  cursor: pointer;
  display: block;
  width: 100%;
}

/*
  A photo row shows the photo. The grid only appears once the picture has actually landed, so
  a row that has nothing to show, or has not had its signed URL come back yet, keeps the plain
  single-column layout instead of holding an empty square open.
*/
.feed li.has-shot {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: 0.8rem;
  align-items: center;
}

.bucket-shot {
  width: 56px;
  height: 56px;
  border-radius: 12px;
  object-fit: cover;
  grid-row: span 2;
  animation: shot-in 260ms ease-out both;
}

@keyframes shot-in {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .bucket-shot {
    animation: none;
  }
}

.meta {
  color: var(--secondary);
  font-size: 0.78rem;
  margin-top: 0.35rem;
}

/*
  The notices the server raised. Each card deals itself in, one after another, because they
  arrive after Home is already drawn and appearing all at once reads as a repaint rather than
  as the app having found something. The stagger is per-card so the order is visible.
*/
.notices {
  list-style: none;
  margin: 0.8rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.notices li {
  display: grid;
  grid-template-columns: 40px 1fr auto;
  gap: 0.8rem;
  align-items: start;
  background: var(--surface);
  border-radius: 18px;
  padding: 0.85rem 0.95rem;
  box-shadow: 0 6px 14px color-mix(in srgb, var(--shadow) 50%, transparent);
  cursor: pointer;
  animation: notice-in 380ms cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--notice-index, 0) * 90ms);
}

.notices li:hover {
  transform: translateY(-1px);
}

.notice-mark {
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1.25rem;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 14px;
  background: var(--mint);
  color: var(--deep);
}

.notice-body strong {
  display: block;
  font-size: 0.95rem;
}

.notice-body p {
  margin: 0.2rem 0 0;
  color: var(--secondary);
  font-size: 0.85rem;
  line-height: 1.4;
}

.notice-when {
  margin: 0.3rem 0 0;
  color: var(--secondary);
  font-size: 0.72rem;
}

.notice-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  margin-top: 0.35rem;
}

@keyframes notice-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .notices li {
    animation: none;
  }

  .notices li:hover {
    transform: none;
  }
}

/*
  Your memory, joined up. The counts run up from zero in script and the bars grow to length via
  a width transition, so the section reads as being counted rather than as a chart that was
  already there. Both end where the data is, so the motion cannot say anything untrue.
*/
.memory-counts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.6rem;
}

.memory-counts strong {
  display: block;
  font-family: "Sora", sans-serif;
  font-size: 1.8rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.memory-counts span {
  color: var(--secondary);
  font-size: 0.78rem;
}

.memory-waiting {
  margin: 0.15rem 0 0;
  color: var(--accent);
  font-size: 0.85rem;
  font-weight: 600;
}

.memory-block {
  margin-top: 1rem;
  border-top: 1px solid var(--hairline);
  padding-top: 0.9rem;
}

.memory-kicker {
  margin: 0 0 0.6rem;
  color: var(--secondary);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.memory-bars {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.memory-bar-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
  font-size: 0.85rem;
}

.memory-bar-head strong {
  font-variant-numeric: tabular-nums;
}

.memory-bar {
  margin-top: 0.3rem;
  height: 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--secondary) 18%, transparent);
  overflow: hidden;
}

.memory-bar i {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
  transition: width 620ms cubic-bezier(0.22, 1, 0.36, 1);
}

.memory-chips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

.memory-chips li {
  background: var(--mint);
  color: var(--deep);
  border-radius: 12px;
  padding: 0.45rem 0.75rem;
  font-size: 0.83rem;
}

.memory-people {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.memory-people li {
  display: grid;
  grid-template-columns: 38px 1fr;
  gap: 0.75rem;
  align-items: center;
  cursor: pointer;
}

.memory-people strong {
  display: block;
  font-size: 0.92rem;
}

.memory-people p {
  margin: 0.1rem 0 0;
  color: var(--secondary);
  font-size: 0.82rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.memory-initial,
.avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--mint);
  color: var(--deep);
  font-family: "Sora", sans-serif;
  font-weight: 600;
}

/*
  The same circle whether it holds a letter or a face, so a list of people has one shape down
  it and a row does not move when a picture arrives after the names have been drawn.
*/
.avatar {
  flex: 0 0 auto;
  overflow: hidden;
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: shot-in 260ms ease-out both;
}

.avatar-lg {
  width: 72px;
  height: 72px;
  font-size: 1.6rem;
}

/* Written past ".feed li button", which unsets everything and then lays the row out as a block. */
.feed li button.person-row {
  display: flex;
  align-items: center;
  gap: 0.8rem;
}

.profile-face-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 0.6rem 0 0.2rem;
}

.profile-face-row .hint {
  margin: 0 0 0.5rem;
}

/* Two short buttons beside a 72px circle: they wrap onto their own line before they wrap
   inside themselves, because "Choose a / photo" reads as a broken control. */
.profile-face-row .row {
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Past ".row .btn" and ".view-settings .btn-outline", which stretch a button to the width it
   is given. Sign out is the full-width button on this screen; these two are not. */
.profile-face-row .row .btn {
  flex: 0 0 auto;
  width: auto;
  margin-top: 0;
  min-height: 40px;
  padding: 0.5rem 0.85rem;
  font-size: 0.88rem;
  white-space: nowrap;
}

.agenda {
  margin-top: 0.8rem;
}

.agenda-head {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 0.8rem;
  align-items: center;
}

.agenda-head strong {
  font-size: 1.05rem;
}

.agenda-head .hint {
  margin: 0.15rem 0 0;
}

.agenda-mark {
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1.35rem;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 15px;
  background: var(--mint);
  color: var(--deep);
}

.agenda-days {
  list-style: none;
  margin: 0.9rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.agenda-days li {
  display: grid;
  grid-template-columns: 76px 1fr;
  gap: 0.75rem;
  align-items: start;
  border-left: 3px solid color-mix(in srgb, var(--accent) 28%, transparent);
  padding-left: 0.7rem;
  animation: agenda-in 340ms cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--agenda-index, 0) * 70ms);
}

/* The next thing up is the only row drawn in full, so the list has one obvious answer. */
.agenda-days li.is-next {
  border-left-color: var(--accent);
}

.agenda-when {
  color: var(--secondary);
  font-size: 0.8rem;
  padding-top: 0.1rem;
}

.agenda-days strong {
  display: block;
  font-size: 0.92rem;
  line-height: 1.35;
}

.agenda-days p {
  margin: 0.15rem 0 0;
  color: var(--secondary);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

@keyframes agenda-in {
  from {
    opacity: 0;
    transform: translateX(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .agenda-days li {
    animation: none;
  }

  .memory-bar i {
    transition: none;
  }
}

.row {
  display: flex;
  gap: 0.6rem;
  align-items: center;
}

.row .btn {
  flex: 1;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0.9rem 0;
}

/*
  Geometry copied from CapturePage.xaml so the browser bucket is the phone bucket: a 200x186
  stage with the handle behind the rim, a vessel that rounds off at the bottom, and the well
  and mouth stacked on top so the opening reads as a hole, not a lid.
*/
.bucket-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--surface);
  border-radius: 32px;
  box-shadow: 0 10px 24px color-mix(in srgb, var(--shadow) 70%, transparent);
  margin-bottom: 0.85rem;
  padding-top: 8px;
  overflow: hidden;
}

.bucket-body {
  position: relative;
  width: 200px;
  height: 186px;
  flex: none;
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  cursor: pointer;
  transform-origin: 50% 100%;
}

.bucket-body > span {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: block;
}

.bucket-handle {
  top: 2px;
  width: 108px;
  height: 74px;
  border: 9px solid var(--accent);
  border-radius: 50%;
  background: transparent;
}

.bucket-vessel {
  top: 58px;
  width: 168px;
  height: 128px;
  border-radius: 16px 16px 52px 52px;
  background: var(--accent);
}

.bucket-well {
  top: 52px;
  width: 148px;
  height: 34px;
  border-radius: 50%;
  background: var(--hero-deep);
}

.bucket-rim {
  top: 48px;
  width: 168px;
  height: 40px;
  border-radius: 50%;
  border: 3px solid #fff;
  background: var(--accent-soft);
}

.bucket-mouth {
  top: 56px;
  width: 138px;
  height: 22px;
  border-radius: 50%;
  background: var(--hero-deep);
  opacity: 0.55;
}

.bucket-body .bucket-dots {
  top: 104px;
  width: 78px;
  height: 48px;
  transform: translateX(-50%) rotate(-18deg);
}

.bucket-dots i {
  position: absolute;
  border-radius: 50%;
  background: #fff;
  display: block;
}

.bucket-dots i:nth-child(1) {
  width: 12px;
  height: 12px;
  left: 4px;
  bottom: 2px;
}

.bucket-dots i:nth-child(2) {
  width: 16px;
  height: 16px;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.bucket-dots i:nth-child(3) {
  width: 20px;
  height: 20px;
  right: 2px;
  top: 0;
}

/* The mouthful that falls in when something is dropped. */
.morsel {
  position: absolute;
  top: 4px;
  left: 50%;
  width: 48px;
  height: 48px;
  margin-left: -24px;
  border-radius: 16px;
  background: var(--muted);
  color: var(--accent);
  font-size: 24px;
  display: grid;
  place-items: center;
  opacity: 0;
  pointer-events: none;
}

.appetite {
  margin: 10px 0 16px;
  padding: 0 1rem;
  font-weight: 600;
  color: var(--accent);
  text-align: center;
  min-height: 20px;
}

.action-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
  margin: 1rem 0 0.4rem;
}

.action-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  background: none;
  border: 0;
  color: var(--secondary);
  font: inherit;
  font-size: 0.7rem;
  cursor: pointer;
  text-decoration: none;
}

.action-tile span {
  width: 52px;
  height: 52px;
  border-radius: 26px;
  display: grid;
  place-items: center;
  background: var(--surface);
  color: var(--text);
  font-size: 1.35rem;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--shadow) 50%, transparent);
}

/*
  What only the handset can do: the muted look of a control that will not act, and a phone in
  the corner saying which handset. Not the disabled attribute — a disabled control cannot be
  tapped, and the whole point is that tapping it explains itself.
*/
.phone-only {
  position: relative;
  cursor: not-allowed;
}

.phone-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent);
  color: #fff;
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 12px;
  font-variation-settings: "FILL" 0, "wght" 500, "GRAD" 0, "opsz" 20;
  line-height: 1;
}

/*
  Over the icon's shoulder rather than the tile's, since the tile is wider than what it draws.
  Written past ".action-tile span", which turns every span in a tile into the 52px disc the
  glyph sits in — without this the badge became a second tile icon on top of the first.
*/
.action-tile .phone-badge {
  top: -3px;
  right: calc(50% - 31px);
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  box-shadow: none;
}

.action-tile.phone-only > span:not(.phone-badge) {
  opacity: 0.45;
}

.action-tile.phone-only {
  color: color-mix(in srgb, var(--secondary) 55%, transparent);
}

/*
  A card for something that is not here. Same surface and radius as the cards that work, at the
  weight of a thing being described rather than offered.
*/
.app-only-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 0.6rem 0 0.4rem;
}

.app-only-card {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.85rem 1.05rem;
  margin-top: 0.7rem;
  border: 1px dashed color-mix(in srgb, var(--secondary) 35%, transparent);
  border-radius: 18px;
  background: color-mix(in srgb, var(--surface) 70%, transparent);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.app-only-list .app-only-card {
  margin-top: 0;
}

/*
  A source that does work here is a link rather than a button, and a link brings its underline
  and its own colour with it. The row it sits in is the row the others are in.
*/
a.app-only-card,
a.app-only-card:hover {
  text-decoration: none;
  color: var(--text);
}

/* A dashed border says "not here". One that works is drawn like the cards that do. */
a.app-only-card {
  border-style: solid;
  border-color: color-mix(in srgb, var(--accent) 30%, transparent);
}

.app-only-mark {
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--surface);
  color: var(--secondary);
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1.15rem;
  opacity: 0.75;
}

.app-only-words {
  display: block;
  opacity: 0.7;
}

.app-only-words strong {
  display: block;
  font-size: 0.95rem;
}

.app-only-words .hint {
  margin: 0.15rem 0 0;
}

/* The popup that says so, with the same phone on it that the badge showed. */
.notice-phone h3 {
  margin: 0 0 0.4rem;
  font-size: 1.05rem;
}

.notice-phone h3::before {
  content: "smartphone";
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1.1rem;
  vertical-align: -0.15rem;
  margin-right: 0.4rem;
  color: var(--accent);
}

/* The same lock the phone draws: a badge on the tile, not a disabled button. */
.action-tile.needs-pro span {
  position: relative;
}

.action-tile.needs-pro span::after {
  content: "PRO";
  position: absolute;
  top: -2px;
  right: -2px;
  padding: 0 5px;
  border-radius: 7px;
  background: var(--accent);
  color: #fff;
  font-family: inherit;
  font-size: 0.5rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.35;
}

.plan-card {
  margin-top: 0.75rem;
}

.plan-card .lede {
  margin: 0;
}

.plan-list {
  list-style: none;
  margin: 0.2rem 0 0.4rem;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}

.plan-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.85rem;
  color: var(--text);
}

.plan-detail {
  color: var(--accent);
  font-size: 0.8rem;
}

.plan-detail.locked {
  color: var(--secondary);
}

.digest-mark {
  display: block;
  text-align: center;
  font-size: 1.75rem;
  color: var(--accent);
  margin: 0.4rem 0 0.2rem;
}

.period {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0.5rem;
  margin: 0.4rem 0 0.9rem;
}

.period-btn {
  border: 0;
  border-radius: 14px;
  padding: 0.7rem 0.4rem;
  font: inherit;
  font-weight: 600;
  font-size: 0.82rem;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--shadow) 50%, transparent);
}

.period-btn.active {
  background: var(--accent);
  color: #fff;
}

#digest-generate {
  width: 100%;
}

.appearance {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.55rem;
  margin-bottom: 1.5rem;
}

.view-settings h2 {
  margin: 1.35rem 0 0.4rem;
  font-size: 1.05rem;
}

.view-settings h2:first-child {
  margin-top: 0.4rem;
}

.view-settings .btn-outline {
  width: 100%;
  margin-top: 1.25rem;
}

/*
  Camera, Photo, Video, Record and File are labels over hidden inputs, because a button cannot
  open a file picker and a label can. They have to look and behave exactly like the tiles that
  really are buttons, which .action-tile handles, plus the pointer a label does not get.
*/
label.action-tile {
  cursor: pointer;
}

/* One tap starts recording, the next stops; the tile has to say which state it is in. */
#record-voice.recording {
  background: var(--accent);
  color: #fff;
  animation: listening 1.4s ease-in-out infinite;
}

@keyframes listening {
  50% {
    box-shadow: 0 0 0 8px color-mix(in srgb, var(--accent) 22%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  #record-voice.recording {
    animation: none;
  }
}

/* The import wizard. The steps are the page; everything else frames them. */
.wizard {
  max-width: 30rem;
  width: calc(100vw - 2rem);
}

.wizard h3 {
  margin: 0 0 0.35rem;
  font-size: 1.15rem;
}

.wizard-steps {
  margin: 0 0 1rem;
  padding-left: 1.3rem;
  display: grid;
  gap: 0.65rem;
  line-height: 1.45;
  font-size: 0.95rem;
}

.wizard-steps li::marker {
  color: var(--accent);
  font-weight: 600;
}

.wizard .hint {
  font-size: 0.8rem;
  color: var(--secondary);
  line-height: 1.4;
}

.wizard-pick {
  display: block;
  text-align: center;
  margin-top: 0.9rem;
}

.wizard-findings {
  margin: 0.9rem 0 0;
  font-size: 0.9rem;
  text-align: center;
  line-height: 1.4;
}

.wizard-actions {
  display: grid;
  gap: 0.5rem;
  margin-top: 1rem;
}

/*
  How it works, as one evening. Dark on purpose and edge to edge on a phone: it is the only
  thing on screen while it plays, and a story in a small white box with the app visible around
  it is a tooltip. Each prop builds itself when its act turns on, which is the whole point —
  the line being typed, the chips flying out, the notification dropping in.
*/
.story {
  width: min(32rem, calc(100vw - 1.5rem));
  max-width: none;
  padding: 1.25rem 1.2rem 1.1rem;
  border: 0;
  border-radius: 24px;
  background: #0a2422;
  color: #fff;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}

.story::backdrop {
  background: rgba(4, 18, 17, 0.82);
  backdrop-filter: blur(3px);
}

.story-head {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  justify-content: space-between;
}

.story-head h3 {
  margin: 0;
  font-size: 1.15rem;
}

.story-head .lede {
  margin: 0.2rem 0 0;
  font-size: 0.78rem;
  line-height: 1.35;
  color: #a8d5cd;
}

.story-x {
  flex: 0 0 auto;
  width: 2.2rem;
  height: 2.2rem;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  cursor: pointer;
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1.15rem;
  line-height: 1;
}

.story-stage {
  position: relative;
  display: grid;
  min-height: 12.5rem;
  margin: 1rem 0 0.9rem;
  cursor: pointer;
}

/* Every prop sits on the same cell; only the lit one is visible. */
.story-prop {
  grid-area: 1 / 1;
  align-self: center;
  margin: 0;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.22s ease;
}

.story-prop.on {
  visibility: visible;
  opacity: 1;
}

.prop-note {
  padding: 1rem 1.05rem;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.1);
}

.prop-glyph {
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1.3rem;
  color: #6fb8ac;
}

.prop-typed {
  margin: 0.6rem 0 0;
  font-size: 1.02rem;
  line-height: 1.4;
  min-height: 2.8rem;
}

.prop-caret {
  display: inline-block;
  width: 2px;
  height: 1.05rem;
  margin-left: 2px;
  vertical-align: -2px;
  background: #6fb8ac;
  animation: caret 0.9s steps(1, end) infinite;
}

@keyframes caret {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0.1; }
}

.prop-chips {
  display: grid;
  gap: 0.55rem;
  justify-items: stretch;
}

.prop-chip {
  justify-self: start;
  padding: 0.7rem 0.95rem;
  border-radius: 14px;
  background: #d7f1ec;
  color: #0a3d3a;
  font-weight: 600;
  font-size: 0.92rem;
}

.prop-chip:nth-child(2) { justify-self: center; background: #c6e9e1; }
.prop-chip:nth-child(3) { justify-self: end; background: #b4e0d6; }

.story-prop.on .prop-chip {
  animation: pop 0.34s cubic-bezier(0.2, 1.3, 0.4, 1) backwards;
}

.story-prop.on .prop-chip:nth-child(2) { animation-delay: 0.22s; }
.story-prop.on .prop-chip:nth-child(3) { animation-delay: 0.44s; }

@keyframes pop {
  from { opacity: 0; transform: translateY(10px) scale(0.86); }
  to { opacity: 1; transform: none; }
}

.prop-person {
  padding: 1rem 1.05rem;
  border-radius: 20px;
  background: #fff;
  color: #1b3b38;
}

.prop-person header {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.prop-avatar {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: #0a3d3a;
  color: #fff;
  font-weight: 600;
}

.story-prop.on .prop-avatar {
  animation: pop 0.45s cubic-bezier(0.2, 1.4, 0.4, 1) backwards;
}

.prop-person ul {
  margin: 0.8rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.5rem;
  font-size: 0.9rem;
}

.prop-person li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.prop-person li span {
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1rem;
  color: #2e8b7a;
}

.story-prop.on .prop-person li {
  animation: slide-in 0.34s ease backwards;
}

.story-prop.on .prop-person li:nth-child(1) { animation-delay: 0.28s; }
.story-prop.on .prop-person li:nth-child(2) { animation-delay: 0.46s; }
.story-prop.on .prop-person li:nth-child(3) { animation-delay: 0.64s; }

@keyframes slide-in {
  from { opacity: 0; transform: translateX(-12px); }
  to { opacity: 1; transform: none; }
}

.prop-nudge {
  align-self: start;
  display: flex;
  gap: 0.75rem;
  padding: 0.8rem 0.85rem;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.95);
  color: #1b3b38;
  box-shadow: 0 14px 30px rgba(0, 0, 0, 0.45);
}

.story-prop.on.prop-nudge {
  animation: drop-in 0.55s cubic-bezier(0.2, 1.25, 0.4, 1);
}

@keyframes drop-in {
  from { opacity: 0; transform: translateY(-42px); }
  to { opacity: 1; transform: none; }
}

.prop-icon {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 9px;
  background: #0a3d3a;
  color: #fff;
  font-family: "Material Symbols Outlined", sans-serif;
  font-size: 1.05rem;
}

.prop-nudge strong {
  display: block;
  font-size: 0.78rem;
  color: #0a3d3a;
}

.prop-nudge p {
  margin: 0.15rem 0 0;
  font-size: 0.95rem;
  line-height: 1.35;
}

.prop-report {
  padding: 1rem 1.05rem;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.1);
}

.prop-report strong {
  font-size: 1rem;
}

.prop-report p {
  margin: 0.5rem 0 0;
  font-size: 0.9rem;
  color: #d7f1ec;
}

.prop-tiles {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.8rem;
}

.prop-tiles img {
  width: 4.4rem;
  height: 3.3rem;
  object-fit: cover;
  border-radius: 10px;
  background: #1a3d38;
  pointer-events: none;
}

.prop-tiles-caption {
  margin: 0.45rem 0 0;
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: #6fb8ac;
}

.story-prop.on.prop-report > * {
  animation: rise 0.3s ease backwards;
}

.story-prop.on.prop-report > *:nth-child(2) { animation-delay: 0.16s; }
.story-prop.on.prop-report > *:nth-child(3) { animation-delay: 0.32s; }
.story-prop.on.prop-report > *:nth-child(4) { animation-delay: 0.48s; }

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.prop-ask {
  display: grid;
  gap: 0.55rem;
}

.prop-bubble {
  margin: 0;
  padding: 0.7rem 0.9rem;
  max-width: 85%;
  font-size: 0.95rem;
  line-height: 1.35;
}

.prop-question {
  justify-self: end;
  border-radius: 16px 16px 4px 16px;
  background: #d7f1ec;
  color: #0a3d3a;
}

.prop-answer {
  justify-self: start;
  min-height: 2.6rem;
  border-radius: 16px 16px 16px 4px;
  background: rgba(255, 255, 255, 0.1);
}

.story-prop.on .prop-bubble {
  animation: pop 0.34s cubic-bezier(0.2, 1.3, 0.4, 1) backwards;
}

.story-prop.on .prop-answer { animation-delay: 0.4s; }

.prop-finale {
  justify-self: center;
  text-align: center;
}

.prop-finale .prop-bucket {
  width: 10rem;
  height: 10rem;
  display: block;
  margin: 0 auto;
}

.story-prop.on.prop-finale .prop-bucket {
  animation: pop 0.6s cubic-bezier(0.2, 1.4, 0.4, 1);
}

.story-when {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: #6fb8ac;
  min-height: 1rem;
}

.story-caption h4 {
  margin: 0.35rem 0 0.3rem;
  font-size: 1.3rem;
  line-height: 1.2;
}

.story-caption > p:last-of-type {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.4;
  color: #d7f1ec;
}

.story-dots {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.7rem;
}

.story-dots i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #fff;
  opacity: 0.28;
}

.story-dots i.on {
  opacity: 1;
}

/* Skip is the smaller half: the other button is the only thing the story is for. */
.story-actions {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.6rem;
  margin-top: 1rem;
}

.story-actions .btn {
  width: 100%;
  justify-content: center;
  white-space: nowrap;
}

.story-actions .btn-ghost {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  border-color: transparent;
}

/* Everything above is motion. Somebody who asked for less gets the words, in order. */
@media (prefers-reduced-motion: reduce) {
  .story-prop,
  .story-prop.on *,
  .story-prop.on {
    animation: none !important;
  }

  .prop-caret {
    animation: none;
  }
}

.connect-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}

.view-settings .connect-grid .btn,
.view-settings [data-connect] {
  width: 100%;
}

/* An odd last one takes the whole row rather than standing in a column on its own. */
.connect-grid > :last-child:nth-child(odd) {
  grid-column: 1 / -1;
}

.tabbar {
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  padding: 0.35rem 0.2rem calc(0.45rem + env(safe-area-inset-bottom));
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  /*
    Nearly opaque, and with a hairline above it. At 72% the page scrolled through the bar, so
    in Night and KGB the labels were sitting on whatever card happened to be behind them and
    could not be read at all.
  */
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: saturate(1.3) blur(20px);
  -webkit-backdrop-filter: saturate(1.3) blur(20px);
  border-top: 1px solid color-mix(in srgb, var(--hairline) 70%, transparent);
}

.tabbar a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  color: var(--tab);
  text-decoration: none;
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.25rem 0;
}

.tabbar a .tab-icon {
  font-size: 1.45rem;
}

.tabbar a.active {
  color: var(--accent);
}

.tabbar a.active .tab-icon {
  font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 24;
}

/*
  Digest's loading curtain, mirroring DigestPage's structuring overlay: a dark room with
  drifting orbs, one breathing ring, three ripples leaving it, and the chips arriving in turn.
*/
.structuring {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: #050f0e;
  animation: struct-in 240ms ease-out both;
}

.structuring.leaving {
  animation: struct-out 380ms ease-in both;
}

@keyframes struct-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes struct-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

.struct-orb,
.struct-ring,
.struct-ripple {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.struct-orb-a {
  width: 240px;
  height: 240px;
  top: 40px;
  right: -70px;
  opacity: 0.32;
  background: var(--hero-mist);
  animation: struct-breathe 1280ms ease-in-out infinite alternate;
}

.struct-orb-b {
  width: 170px;
  height: 170px;
  bottom: 80px;
  left: -50px;
  opacity: 0.24;
  background: var(--accent);
  animation: struct-breathe 1280ms ease-in-out 200ms infinite alternate-reverse;
}

.struct-orb-c {
  width: 90px;
  height: 90px;
  top: calc(50% - 165px);
  left: calc(50% + 35px);
  opacity: 0.35;
  background: var(--hero-mist);
  animation: struct-breathe 1280ms ease-in-out 420ms infinite alternate;
}

@keyframes struct-breathe {
  from { transform: scale(0.9); }
  to { transform: scale(1.16); }
}

.struct-ring {
  width: 280px;
  height: 280px;
  opacity: 0.18;
  border: 2px solid var(--accent);
  animation: struct-pulse 1800ms ease-in-out infinite alternate;
}

@keyframes struct-pulse {
  from { transform: scale(0.88); }
  to { transform: scale(1.12); }
}

.struct-ripple {
  width: 200px;
  height: 200px;
  opacity: 0;
  border: 1.6px solid var(--accent);
  animation: struct-ripple 1600ms linear infinite;
}

.struct-ripple-b {
  border-color: #d7f1ec;
  border-width: 1.2px;
  animation-delay: 480ms;
}

.struct-ripple-c {
  border-color: var(--hero-mist);
  border-width: 1px;
  animation-delay: 960ms;
}

@keyframes struct-ripple {
  from { transform: scale(0.42); opacity: 0.5; }
  to { transform: scale(1.7); opacity: 0; }
}

.struct-copy {
  position: relative;
  padding: 32px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
}

.struct-glyph {
  margin: 0;
  font-size: 40px;
  color: var(--hero-mist);
  animation: struct-glyph 460ms ease-in-out 280ms alternate 2;
}

@keyframes struct-glyph {
  from { transform: scale(1); }
  to { transform: scale(1.08); }
}

.struct-title {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  color: #fff;
}

.struct-hint {
  margin: 0;
  font-size: 14px;
  color: #d7f1ec;
}

.struct-chips {
  display: flex;
  gap: 8px;
}

.struct-chip {
  opacity: 0;
  animation: struct-chip 300ms cubic-bezier(0.2, 1.4, 0.4, 1) forwards;
}

.struct-chip:nth-child(1) { animation-delay: 280ms; }
.struct-chip:nth-child(2) { animation-delay: 580ms; }
.struct-chip:nth-child(3) { animation-delay: 880ms; }

@keyframes struct-chip {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .struct-orb,
  .struct-ring,
  .struct-ripple,
  .struct-glyph {
    animation: none;
  }

  .struct-chip {
    opacity: 1;
    animation: none;
  }
}

.back-btn {
  display: block;
  font-weight: 600;
  color: var(--accent);
}

#person-brief {
  width: 100%;
  margin-top: 0.6rem;
}

#person-name {
  margin-top: 0.4rem;
}

.section-heading {
  margin: 1.5rem 0 0.2rem;
  font-size: 1.05rem;
}

dialog {
  border: 0;
  border-radius: 18px;
  background: var(--surface);
  color: var(--text);
  padding: 1.2rem;
  width: min(92vw, 360px);
}

dialog::backdrop {
  background: rgba(10, 61, 58, 0.55);
}

dialog p {
  margin: 0 0 1rem;
  line-height: 1.45;
}

dialog .btn {
  width: 100%;
}

/*
  The gate above the sign-in buttons. Deliberately not styled down: it is the one thing on this
  page somebody is being asked to agree to, so it gets the full text size rather than the
  small-print treatment that would make it look like something to skip past.
*/
.terms-gate {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.6rem;
  align-items: start;
  margin: 0 0 1.35rem;
}

.terms-gate input[type="checkbox"] {
  width: 20px;
  height: 20px;
  margin: 0.1rem 0 0;
  accent-color: var(--accent);
  flex: none;
}

.terms-gate label {
  display: block;
  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--text);
  cursor: pointer;
}

.terms-hint {
  margin: 0.2rem 0 0;
  text-align: center;
}

.text-link {
  border: 0;
  background: none;
  padding: 0;
  margin-top: 0.2rem;
  font: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
}

/* The document itself: long, so it scrolls inside the dialog rather than off the screen. */
dialog.terms {
  width: min(94vw, 560px);
}

.terms-body {
  max-height: min(62vh, 520px);
  overflow-y: auto;
  padding-right: 0.4rem;
}

.terms-body h4 {
  margin: 1.1rem 0 0.3rem;
  font-family: "Sora", sans-serif;
  font-size: 0.95rem;
}

.terms-body p {
  margin: 0 0 0.2rem;
  font-size: 0.9rem;
  line-height: 1.5;
}

/*
  The answer, for when the terms are opened as a question rather than as a document. Agree first
  and full width: it is the one the reader came here to press. Declining is beneath it and quiet,
  because it is a real choice and not one to be nudged out of.
*/
#terms-decide {
  display: grid;
  gap: 0.5rem;
}

.empty {
  margin-top: 1rem;
  text-align: center;
}

.hint {
  font-size: 0.82rem;
}

/*
  The wait, for the seconds a briefing or an answer actually takes. Same language as the
  Structuring film — rings opening out of a mark — at the size of one card, so it sits under the
  button that started the work instead of covering the page. Mirrors ThinkingBox.xaml.
*/
.waiting:not([hidden]) {
  margin-top: 0.9rem;
}

.thinking {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: 14px;
  align-items: center;
  padding: 14px 16px;
  border: 1px solid color-mix(in srgb, var(--hairline) 70%, transparent);
  border-radius: 18px;
  background: var(--surface);
  animation: think-in 220ms ease-out both;
}

@keyframes think-in {
  from { opacity: 0; transform: scale(0.97); }
  to { opacity: 1; transform: scale(1); }
}

.think-mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
}

.think-mark::before {
  content: "";
  position: absolute;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--accent-soft);
  animation: think-breathe 780ms ease-in-out infinite alternate;
}

.think-mark i {
  position: absolute;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1.4px solid var(--accent);
  opacity: 0;
  animation: think-ripple 1400ms linear infinite;
}

.think-mark i:nth-of-type(2) {
  border-color: var(--hero-mid);
  border-width: 1.1px;
  animation-delay: 460ms;
}

.think-mark i:nth-of-type(3) {
  border-color: var(--hero-mist);
  border-width: 1px;
  animation-delay: 920ms;
}

@keyframes think-ripple {
  from { transform: scale(0.55); opacity: 0.55; }
  to { transform: scale(1.42); opacity: 0; }
}

@keyframes think-breathe {
  from { transform: scale(0.94); }
  to { transform: scale(1.08); }
}

.think-glyph {
  position: relative;
  font-size: 20px;
  color: var(--accent);
  animation: think-breathe 780ms ease-in-out infinite alternate;
}

.think-copy {
  display: grid;
  gap: 10px;
}

.think-line {
  font-size: 0.9rem;
  color: var(--text);
  transition: opacity 180ms ease;
}

.think-line.turning {
  opacity: 0;
}

/*
  A bar that sweeps rather than fills: nothing here knows how far along it is, and a progress bar
  that guesses is a progress bar that stalls at 90%.
*/
.think-track {
  width: 132px;
  height: 4px;
  border-radius: 2px;
  background: var(--muted);
  overflow: hidden;
}

.think-track i {
  display: block;
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: var(--accent);
  animation: think-sweep 1640ms ease-in-out infinite;
}

@keyframes think-sweep {
  0% { transform: translateX(0); }
  50% { transform: translateX(88px); }
  100% { transform: translateX(0); }
}

/* A button holding a request open should look held, not merely stop answering taps. */
.btn[aria-busy="true"] {
  opacity: 0.6;
  cursor: progress;
}

/*
  A label cannot be disabled - the attribute does nothing on one - and a file picker is a label
  over a hidden input, which is the only way a browser will open one. So the tap is refused in
  CSS while the upload it already started is still running.
*/
label.btn[aria-busy="true"] {
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .thinking,
  .think-mark::before,
  .think-mark i,
  .think-glyph,
  .think-track i {
    animation: none;
  }

  .think-mark i:first-of-type {
    opacity: 0.4;
  }
}

/*
  The counted half of the report. Same shapes as the phone's cards (DigestPage.xaml): a figure
  with a bar that fills to it, and a week that reads down a rail.
*/
.board {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  margin-top: 1rem;
}

.board-card {
  background: var(--surface);
  border-radius: 18px;
  padding: 1rem 1.05rem;
  box-shadow: 0 8px 18px color-mix(in srgb, var(--shadow) 55%, transparent);
}

.board-kicker {
  margin: 0 0 0.15rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--accent);
}

.board-card h3 {
  margin: 0 0 0.75rem;
  font-size: 1.05rem;
}

.signal + .signal {
  margin-top: 0.85rem;
}

.signal-head,
.signal-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}

.signal-label {
  font-size: 0.85rem;
  color: var(--secondary);
}

.signal-value {
  font-size: 1.2rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.signal-bar {
  margin: 0.35rem 0 0.3rem;
  height: 8px;
  border-radius: 4px;
  background: var(--accent-soft);
  overflow: hidden;
}

.signal-fill {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--accent);
  transition: width 760ms cubic-bezier(0.22, 1, 0.36, 1);
}

.signal-foot {
  font-size: 0.72rem;
  color: var(--secondary);
}

.signal-trend {
  font-weight: 600;
  white-space: nowrap;
}

.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
  The rail beside a row, drawn in full only for the next thing up. Every part names its row as
  well as its column: a pseudo-element counts as the first grid item, so leaving the rest to
  auto-placement puts the time on a row of its own and leaves the rail nothing to stretch to.
*/
.slot {
  display: grid;
  grid-template-columns: 4.4rem 3px 1fr;
  gap: 0.65rem;
  padding: 0.4rem 0;
}

.slot::before {
  content: "";
  grid-column: 2;
  grid-row: 1;
  align-self: stretch;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0.3;
}

.slot-when {
  grid-column: 1;
  grid-row: 1;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--accent);
  align-self: center;
}

.slot > div {
  grid-column: 3;
  grid-row: 1;
}

.slot.next::before {
  opacity: 1;
}

.slot-title {
  margin: 0;
  font-size: 0.9rem;
}

.slot-where {
  margin: 0.1rem 0 0;
  font-size: 0.72rem;
  color: var(--secondary);
}

.plain {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.9rem;
}

.plain li {
  padding: 0.25rem 0;
}

@media (prefers-reduced-motion: reduce) {
  .signal-fill {
    transition: none;
  }
}

/* Public legal pages. Crawlable HTML for Google OAuth and anyone who is not signed in. */
.legal-page {
  margin: 0;
  min-height: 100vh;
  background: var(--page);
  color: var(--text);
  font-family: Sora, system-ui, sans-serif;
}

.legal-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--hairline);
}

.legal-brand {
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
}

.legal-bar nav {
  display: flex;
  gap: 1rem;
}

.legal-bar nav a {
  color: var(--secondary);
  text-decoration: none;
  font-size: 0.95rem;
}

.legal-bar nav a[aria-current="page"] {
  color: var(--accent);
  font-weight: 600;
}

.legal-doc {
  max-width: 40rem;
  margin: 0 auto;
  padding: 2rem 1.25rem 4rem;
}

.legal-doc h1 {
  margin: 0 0 0.35rem;
  font-size: 2rem;
}

.legal-doc h2 {
  margin: 1.75rem 0 0.5rem;
  font-size: 1.15rem;
}

.legal-doc p {
  margin: 0 0 0.85rem;
  line-height: 1.55;
}

.legal-doc a {
  color: var(--accent);
}

.legal-links {
  display: flex;
  justify-content: center;
  gap: 1.25rem;
  margin: 1rem 0 0;
  font-size: 0.8rem;
}

.legal-links a {
  color: var(--secondary);
  text-decoration: none;
}

/*
  Public homepage. Must stay visible in the raw HTML so a crawler that never runs the
  app still reads the name and the purpose. It sits on the dark stage, never on --page,
  so the ink is the hero's — dark text on #050f0e is how the purpose vanished on a phone.
*/
.site-about {
  position: relative;
  z-index: 1;
  max-width: 40rem;
  margin: 0 auto;
  padding: 2rem 1.25rem 1.25rem;
  text-align: center;
  color: #e8f2f0;
}

.site-about img {
  display: block;
  margin: 0 auto 1.25rem;
  border-radius: 1.35rem;
}

.site-about h1 {
  margin: 0 0 0.4rem;
  font-size: 2.5rem;
  color: #ffffff;
}

.site-about-slogan {
  margin: 0 0 1.25rem;
  color: #b8e4dc;
  font-weight: 600;
}

.site-about p {
  margin: 0 0 0.85rem;
  line-height: 1.55;
  text-align: left;
  color: #d7f1ec;
}

.site-about-slogan,
.site-about-links {
  text-align: center;
}

.site-about-links {
  display: flex;
  justify-content: center;
  gap: 1.25rem;
  margin: 1.5rem 0 0;
}

.site-about-links a {
  color: #9ee8d8;
}

.site-atmosphere {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
  background:
    radial-gradient(ellipse 70% 45% at 85% -5%, rgba(26, 158, 140, 0.42), transparent 58%),
    radial-gradient(ellipse 55% 40% at 5% 95%, rgba(15, 123, 108, 0.34), transparent 55%);
}

.site-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.site-orb-a {
  width: 520px;
  height: 520px;
  top: -120px;
  right: -140px;
  background: radial-gradient(circle closest-side, #1a9e8c, transparent);
  opacity: 0.55;
}

.site-orb-b {
  width: 340px;
  height: 340px;
  bottom: 4%;
  left: -110px;
  background: radial-gradient(circle closest-side, #0f7b6c, transparent);
  opacity: 0.48;
}

.site-orb-c {
  width: 200px;
  height: 200px;
  top: 40%;
  left: 36%;
  background: radial-gradient(circle closest-side, #b8e4dc, transparent);
  opacity: 0.28;
}

/*
  A phone-width window is the app: one column, full bleed, about stacked above sign-in.
  Wider than that, the orbs keep the window and the app sits in a panel larger than the
  handset — wide enough to read, not stretched across a desktop.
*/
@media (min-width: 840px) {
  body:not(.legal-page) {
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: center;
    gap: clamp(2rem, 5vw, 5rem);
    padding: 2.25rem;
  }

  .site-about {
    max-width: 26rem;
    margin: 0;
    padding: 0;
    text-align: left;
  }

  .site-about img {
    margin-left: 0;
  }

  .site-about-slogan,
  .site-about-links {
    text-align: left;
    justify-content: flex-start;
  }

  .phone {
    width: min(640px, calc(100vw - 36rem));
    max-width: 640px;
    height: min(900px, calc(100dvh - 4.5rem));
    min-height: 640px;
    flex: 0 0 auto;
    border-radius: 28px;
    box-shadow: 0 28px 80px rgba(0, 0, 0, 0.45);
  }

  body.is-login .phone {
    min-height: 640px;
  }
}
