/* Reminisce web app.
 *
 * Tokens, typography and shapes are taken from apps/marketing-site/styles.css
 * so the signed-in app reads as the same product as the page that sold it. The
 * marketing header is white-on-navy over a photographic hero; the app has no
 * hero, so the bar is navy with cream on it -- the same palette, inverted,
 * rather than a second design.
 */

:root {
  --ink: #10222e;
  --navy: #071c29;
  --navy-2: #0d2d3e;
  /* The top bar. --navy is all but black, which read as a heavy slab above
     the warm paper; this keeps the family and lifts it off black. */
  --bar: #16394e;
  --paper: #fbf8f2;
  --cream: #f3eee5;
  --gold: #efc16d;
  --gold-dark: #bf7d25;
  --muted: #65717a;
  --line: rgba(16, 34, 46, .12);
  --good: #2f9e5b;
  --bad: #c8392f;
  --radius: 16px;
  --radius-lg: 24px;
  --shadow: 0 18px 44px rgba(3, 20, 30, .10);
  --shadow-lg: 0 30px 70px rgba(3, 20, 30, .20);
}

* { box-sizing: border-box; }

/* Reserve the vertical scrollbar's width at all times. Without it, a filter
   that shortens the page removes the scrollbar and every column shifts
   sideways -- the layout twitches as you type. scrollbar-gutter is the modern
   spelling; overflow-y keeps older browsers steady the same way.
   overflow-x is clipped rather than hidden so position: sticky still works,
   which the top bar depends on. */
html {
  scrollbar-gutter: stable;
  overflow-y: scroll;
}
html, body { overflow-x: clip; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "DM Sans", system-ui, -apple-system, sans-serif;
  line-height: 1.5;
  font-size: 15px;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

h1, h2, .serif {
  font-family: "Newsreader", Georgia, serif;
  font-weight: 400;
  letter-spacing: -.03em;
}
h1 { font-size: 40px; line-height: 1.05; margin: 0 0 6px; }
h2 { font-size: 26px; margin: 0 0 12px; }

.eyebrow {
  text-transform: uppercase;
  letter-spacing: .16em;
  font-size: 11px;
  font-weight: 700;
  color: var(--gold-dark);
}
.mono { font-variant-numeric: tabular-nums; font-family: "SF Mono", Consolas, monospace; }
.muted { color: var(--muted); }

/* ---------------- Top bar ---------------- */

.appbar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--bar);
  color: #fff;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.appbar-inner {
  width: min(1560px, calc(100% - 40px));
  margin: 0 auto;
  height: 64px;
  display: flex;
  align-items: center;
  gap: 28px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -.04em;
  flex: 0 0 auto;
}
/* White cards, as on the marketing site's own header. */
.brand-mark { width: 25px; height: 25px; color: #fff; display: inline-grid; place-items: center; }
.brand-mark svg { width: 100%; height: 100%; }

.appnav {
  display: flex;
  gap: 4px;
  margin-right: auto;
  font-size: 14px;
  font-weight: 600;
  overflow-x: auto;
  scrollbar-width: none;
}
.appnav::-webkit-scrollbar { display: none; }
.appnav a {
  padding: 7px 13px;
  border-radius: 999px;
  color: rgba(255, 255, 255, .74);
  white-space: nowrap;
}
.appnav a:hover { color: #fff; background: rgba(255, 255, 255, .08); }
.appnav a[aria-current="page"] { color: var(--navy); background: var(--gold); }

.appbar form { margin: 0; }
.signout {
  flex: 0 0 auto;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, .28);
  color: rgba(255, 255, 255, .82);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  padding: 7px 14px;
  border-radius: 999px;
  cursor: pointer;
}
.signout:hover { border-color: var(--gold); color: var(--gold); }

/* ---------------- Layout ---------------- */

main { width: min(1560px, calc(100% - 40px)); margin: 0 auto; padding: 30px 0 70px; }

/* Title on the left, figures on the right, one band instead of two. The old
   stacked arrangement cost ~90px of height above every grid. */
.page-bar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 30px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.page-head p { margin: 4px 0 0; color: var(--muted); }

.card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.stats { display: flex; gap: 30px; flex-wrap: wrap; margin: 0; }
.page-bar .stats { justify-content: flex-end; }
.stat { display: flex; flex-direction: column; gap: 2px; }
/* One size for every figure: a "span" reading as smaller than the counts
   beside it made the row look misaligned rather than deliberate. */
.stat-value {
  font-size: 26px;
  font-weight: 600;
  font-family: "Newsreader", Georgia, serif;
  line-height: 1.1;
  white-space: nowrap;
}

/* ---------------- Controls ---------------- */

.toolbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 20px;
}
input[type="text"], input[type="search"], input[type="date"], select, textarea {
  background: #fff;
  border: 1px solid var(--line);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  padding: 9px 12px;
  border-radius: 10px;
}
input:focus-visible, select:focus-visible, button:focus-visible {
  outline: 2px solid var(--gold-dark);
  outline-offset: 1px;
}
.grow { flex: 1 1 220px; min-width: 180px; }

.button {
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 9px 16px;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  background: var(--gold);
  color: var(--navy);
}
.button:hover { background: #e7b355; }
.button-quiet {
  background: #fff;
  border-color: var(--line);
  color: var(--ink);
  font-weight: 600;
}
.button-quiet:hover { background: var(--cream); }
.button-danger { background: var(--bad); color: #fff; }
.button-danger:hover { background: #ad3128; }
.button:disabled { opacity: .45; cursor: not-allowed; }
.button:disabled:hover { background: var(--bad); }

.range-filter { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.range-filter input[type="range"] { width: 130px; accent-color: var(--gold-dark); }

.chip {
  display: inline-block;
  font-size: 12px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--cream);
  border: 1px solid var(--line);
  color: var(--muted);
  white-space: nowrap;
}
.chip-gold { background: rgba(239, 193, 109, .28); border-color: rgba(191, 125, 37, .3); color: var(--gold-dark); }

.empty-state {
  text-align: center;
  color: var(--muted);
  padding: 60px 20px;
  background: #fff;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}
.loading { text-align: center; color: var(--muted); padding: 50px 20px; }

/* ---------------- Photos ---------------- */

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 15px;
}
.photo-tile {
  /* A <figure> carries the browser default margin: 1em 40px. Left alone it
     stacked on top of the grid gap, which is where the very wide gutters came
     from -- the gap was never the whole story. */
  margin: 0;
  position: relative;
  aspect-ratio: 1;
  border-radius: 12px;
  overflow: hidden;
  background: var(--cream);
  border: 1px solid var(--line);
  cursor: zoom-in;
}
.photo-tile img { width: 100%; height: 100%; object-fit: cover; }
.photo-tile figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 20px 11px 9px;
  font-size: 12px;
  color: #fff;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, .72));
  opacity: 0;
  transition: opacity .15s ease;
}
.photo-tile:hover figcaption, .photo-tile:focus-within figcaption { opacity: 1; }
.photo-tile .tile-missing {
  display: grid;
  place-items: center;
  height: 100%;
  color: var(--muted);
  font-size: 12px;
  text-align: center;
  padding: 10px;
}

/* ---------------- People ---------------- */

.people-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); gap: 14px; }
.person-card { padding: 16px; }
.person-head { display: flex; gap: 13px; align-items: center; }
.person-avatar {
  width: 60px; height: 60px; border-radius: 50%; object-fit: cover;
  background: var(--cream); flex: 0 0 auto; border: 1px solid var(--line);
}
.person-name { font-weight: 700; }
.person-fields { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.person-fields input { flex: 1 1 120px; min-width: 100px; }
.person-appearances { display: flex; gap: 5px; margin-top: 12px; flex-wrap: wrap; }
.person-appearances img {
  width: 52px; height: 52px; object-fit: cover; border-radius: 8px;
  cursor: zoom-in; background: var(--cream);
}
.save-state { font-size: 12px; color: var(--good); margin-top: 8px; min-height: 16px; }
.save-state.error { color: var(--bad); }

/* ---------------- Events ---------------- */

.events-list { display: flex; flex-direction: column; gap: 16px; }
.event-card { padding: 18px 20px; }
.event-top { display: flex; gap: 14px; align-items: flex-start; justify-content: space-between; }
.event-title { font-family: "Newsreader", Georgia, serif; font-size: 24px; letter-spacing: -.02em; }
.event-meta { color: var(--muted); font-size: 13px; margin-top: 2px; }
.event-summary { margin: 12px 0 0; color: #3d4850; max-width: 80ch; }
.event-photos { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 14px; }
.event-photos img {
  width: 104px; height: 104px; object-fit: cover; border-radius: 10px;
  cursor: zoom-in; background: var(--cream);
}
.event-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 13px; }
.score-badge {
  flex: 0 0 auto; font-size: 12px; font-weight: 700; color: #fff;
  background: #767b84; padding: 3px 9px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

/* ---------------- Lightbox ---------------- */

/* Above the memory and person sheets: a photo is opened *from* one of them,
   so it has to land on top rather than behind. */
.lightbox {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(7, 28, 41, .90);
  display: flex; align-items: center; justify-content: center;
  padding: 28px;
}
.lightbox[hidden] { display: none; }
.lightbox-panel {
  display: flex;
  gap: 0;
  max-width: 1400px;
  max-height: 100%;
  background: #fff;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.lightbox-image { background: #0b1c26; display: grid; place-items: center; min-width: 0; }
.lightbox-image img { max-height: min(84vh, 900px); max-width: 100%; object-fit: contain; }
.lightbox-side {
  width: 320px;
  flex: 0 0 320px;
  padding: 22px;
  overflow-y: auto;
  max-height: min(84vh, 900px);
}
.lightbox-side h3 { margin: 0 0 2px; font-size: 16px; word-break: break-word; }
.lightbox-close {
  position: absolute; top: 18px; right: 22px;
  background: transparent; border: 0; color: #fff; font-size: 34px;
  cursor: pointer; line-height: 1;
}
.detail-rows { margin-top: 16px; border-top: 1px solid var(--line); }
.detail-row {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 13px;
}
.detail-row dt { color: var(--muted); flex: 0 0 auto; }
.detail-row dd { margin: 0; text-align: right; word-break: break-word; }
.detail-section-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin: 18px 0 8px; font-weight: 700;
}

/* ---------------- Modal ---------------- */

.modal-backdrop {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(7, 28, 41, .62);
  display: grid; place-items: center; padding: 24px;
}
.modal-backdrop[hidden] { display: none; }
.modal {
  background: #fff; border-radius: var(--radius-lg); padding: 28px;
  max-width: 460px; width: 100%; box-shadow: var(--shadow-lg);
}
.modal h2 { margin-top: 0; }
.modal p { color: var(--muted); }
.modal input[type="text"] { width: 100%; margin-top: 6px; }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }

/* ---------------- Settings ---------------- */

.settings-sections { display: flex; flex-direction: column; gap: 16px; max-width: 720px; }
.settings-section { padding: 20px 22px; }
.settings-section h2 { font-size: 20px; margin-bottom: 4px; }
.settings-section p { margin: 0 0 14px; color: var(--muted); font-size: 14px; }
.settings-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.danger-zone { border-color: rgba(200, 57, 47, .34); }
.danger-zone h2 { color: var(--bad); }

/* ---------------- Home ---------------- */

.home-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; }
.home-card { padding: 22px; display: block; transition: transform .12s ease, box-shadow .12s ease; }
.home-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.home-card .stat-value { font-size: 38px; }
.home-card .label { font-weight: 600; margin-top: 2px; }
.home-card .hint { color: var(--muted); font-size: 13px; margin-top: 6px; }

/* ---------------- Upload ---------------- */

.upload-drop {
  border: 2px dashed var(--line);
  border-radius: var(--radius-lg);
  padding: 46px 24px;
  text-align: center;
  background: #fff;
}
.upload-drop input[type="file"] { margin-top: 14px; }

#upload-status { margin-top: 24px; }
.upload-summary {
  font-weight: 600; font-variant-numeric: tabular-nums;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}

/* One bar for the whole batch: green for what is in, red for what failed,
   and the track's own grey for what is still to come. */
.upload-bar {
  margin-top: 10px;
  height: 10px;
  border-radius: 999px;
  background: rgba(16, 34, 46, .1);
  overflow: hidden;
  display: flex;
}
.upload-bar > span {
  display: block; width: 0; height: 100%;
  transition: width .25s ease;
}
.upload-bar-done { background: var(--good); }
/* Deliberately not green: these photos were already here, so counting them as
   freshly uploaded would overstate what the run actually did. */
.upload-bar-skipped { background: rgba(16, 34, 46, .28); }
.upload-bar-failed { background: var(--bad); }

.upload-actions:not(:empty) { margin-top: 14px; }
.upload-logs { margin-top: 18px; }
.upload-logs .disclosure-body { max-height: 420px; padding: 6px; }

#progress { display: flex; flex-direction: column; }
.upload-row {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; padding: 7px 10px;
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
}
.upload-row:nth-child(even) { background: rgba(16, 34, 46, .03); }
.upload-row-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  background: var(--muted); opacity: .35;
}
.upload-row-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.upload-row-detail { flex: 0 0 auto; color: var(--muted); }
.upload-row.is-checking .upload-row-dot { background: var(--muted); opacity: .6; }
.upload-row.is-active .upload-row-dot { background: var(--muted); opacity: 1; }
.upload-row.is-skipped .upload-row-dot { background: rgba(16, 34, 46, .28); opacity: 1; }
.upload-row.is-skipped .upload-row-name { color: var(--muted); }
.upload-row.is-done .upload-row-dot { background: var(--good); opacity: 1; }
.upload-row.is-failed .upload-row-dot { background: var(--bad); opacity: 1; }
.upload-row.is-failed .upload-row-detail { color: var(--bad); }

@media (max-width: 860px) {
  h1 { font-size: 30px; }
  .lightbox-panel { flex-direction: column; }
  .lightbox-side { width: auto; flex: 1 1 auto; max-height: none; }
  .appbar-inner { gap: 14px; }
}

/* ---------------- Timeline ----------------
 * Ported from scripts/verification_page_template.html. The palette is neutral
 * on purpose: colour-coding events carried no meaning and made a dense axis
 * noisier, not clearer.
 */

.tl-wrap { margin: 0 calc(50% - 50vw); padding: 0 20px; }
/* The real scroller hides its own bar; a proxy above the ruler drives it.
   A bar under a 3,000px-tall canvas is off-screen exactly when you need it,
   and the ruler is what you steer by. */
.tl-scroll { overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.tl-scroll::-webkit-scrollbar { display: none; }

.tl-scrollbar { overflow-x: auto; overflow-y: hidden; height: 14px; margin-bottom: 4px; }
.tl-scrollbar div { height: 1px; }
.tl-canvas { position: relative; }

.tl-year-line { position: absolute; top: 28px; bottom: 0; border-left: 1px dashed var(--line); z-index: 0; }
.tl-year-label { position: absolute; top: 5px; font-size: 15px; font-weight: 700; color: var(--ink);
                 letter-spacing: .04em; white-space: nowrap; font-family: "Newsreader", Georgia, serif; }
.tl-month-label { position: absolute; font-size: 11px; color: var(--muted); white-space: nowrap; }
.tl-month-tick { position: absolute; width: 1px; background: var(--line); }
.tl-axis-line { position: absolute; height: 2px; background: #8a6f5c; }
.tl-axis-arrow { position: absolute; width: 0; height: 0; border-left: 7px solid #8a6f5c;
                 border-top: 5px solid transparent; border-bottom: 5px solid transparent;
                 transform: translateY(-50%); }
.tl-today { position: absolute; width: 16px; height: 16px; border-radius: 50%; border: 3px solid #4a3a30;
            background: #fff; transform: translate(-50%, -50%); }
.tl-today-label { position: absolute; transform: translateX(-50%); white-space: nowrap; font-size: 12px;
                  font-weight: 600; background: #fff; border: 1px solid var(--line);
                  border-radius: 999px; padding: 2px 10px; }

/* z-index, not document order, decides what a drop line passes behind: a line
   from a deep lane crosses the rows above it and must go under their cards. */
.tl-dot { position: absolute; width: 9px; height: 9px; border-radius: 50%; transform: translate(-50%, -50%);
          background: #8d939b; box-shadow: 0 0 0 3px var(--paper); z-index: 1; }
.tl-stem { position: absolute; width: 2px; background: #c6cad0; z-index: 1; }

.tl-card { position: absolute; background: #fff; border: 1px solid var(--line);
           border-radius: 12px; box-shadow: var(--shadow); padding: 11px 13px 12px; z-index: 2; }
.tl-card.tl-open { z-index: 5; box-shadow: var(--shadow-lg); }
.tl-head { display: flex; align-items: flex-start; gap: 8px; }
.tl-title { font-weight: 700; line-height: 1.25; flex: 1 1 auto; overflow: hidden;
            display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
/* A quiet figure, not a badge: it is context, not the headline. */
.tl-score { flex: 0 0 auto; font-size: 11px; font-weight: 600; color: #9aa1a8;
            font-variant-numeric: tabular-nums; letter-spacing: .01em; }
.tl-line { font-size: 12px; color: var(--muted); margin-top: 4px; white-space: nowrap;
           overflow: hidden; text-overflow: ellipsis; }
.tl-summary { font-size: 13px; line-height: 1.4; color: var(--muted); margin-top: 8px; overflow: hidden;
              display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.tl-strip { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 9px; }
.tl-strip img { object-fit: cover; border-radius: 6px; display: block; cursor: zoom-in; background: var(--cream); }
.tl-more { position: relative; border-radius: 6px; overflow: hidden; cursor: pointer; flex: 0 0 auto; }
.tl-more img { filter: brightness(.42); cursor: pointer; }
.tl-more span { position: absolute; left: 0; right: 0; top: 0; bottom: 0; display: flex;
                align-items: center; justify-content: center; color: #fff; font-weight: 700;
                font-size: 13px; pointer-events: none; }
.tl-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 9px; }
.tl-tag { font-size: 11px; padding: 2px 8px; border-radius: 999px; background: var(--cream);
          border: 1px solid var(--line); color: var(--muted); white-space: nowrap; }
.tl-collapse { font-size: 12px; color: var(--gold-dark); cursor: pointer; margin-top: 8px;
               display: inline-block; font-weight: 600; }


/* ---------------- Signed-out page ----------------
 * The marketing site's header and footer, so this is not a dead end.
 */

/* The signed-out page is the marketing site's front door with a sign-in card
   in it, so these values are the marketing stylesheet's own rather than
   approximations of them: header 82px over the hero, brand 23px with a 29px
   white mark, nav 14px/600 at .88 opacity. Two products that are one product
   should not disagree by four pixels. */

.login-page main {
  /* Full bleed. `main` is otherwise a centred 1560px column with padding,
     which would inset the hero and leave the footer floating in the middle of
     a tall window. */
  width: 100%;
  max-width: none;
  padding: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.login-hero {
  position: relative;
  flex: 1 0 auto;          /* takes the slack, so the footer sits at the bottom */
  background: var(--navy);
  color: #fff;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.login-hero-backdrop {
  position: absolute;
  inset: 0;
  /* Sized by Unsplash rather than fetched whole, using the same parameters
     the marketing site uses for its own photographs: 299 kB instead of the
     3.3 MB the bare URL returns, for a picture nobody looks at closely. */
  background-image: url('https://images.unsplash.com/photo-1642841220705-b03194dd9de7?auto=format&fit=crop&fm=jpg&q=82&w=2400');
  background-size: cover;
  background-position: center 44%;
  transform: scale(1.015);
}
.login-hero-shade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(4,21,31,.68) 0%, rgba(4,21,31,.34) 38%,
                    rgba(4,21,31,.62) 72%, rgba(4,21,31,.94) 100%),
    linear-gradient(90deg, rgba(5,20,29,.4), transparent 50%);
}

.site-header {
  position: relative;
  z-index: 20;
  height: 82px;
  width: min(1320px, calc(100% - 48px));
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 38px;
  color: #fff;
}
.site-header .brand { color: #fff; font-size: 23px; }
.site-header .brand-mark { color: #fff; width: 29px; height: 29px; }
.site-header nav { display: flex; gap: 30px; margin-left: auto; font-size: 14px; font-weight: 600; }
.site-header nav a { color: #fff; opacity: .88; }
.site-header nav a:hover { opacity: 1; }
.site-header .button-gold {
  background: var(--gold);
  color: var(--navy);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .08);
  border-radius: 10px;
  padding: 12px 17px;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
}

.login-hero-content {
  position: relative;
  z-index: 2;
  width: min(1180px, calc(100% - 48px));
  margin: 0 auto;
  padding: clamp(48px, 9vh, 110px) 0 clamp(56px, 10vh, 120px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.login-hero-content .eyebrow { color: #f5cf89; }
.login-hero-content h1 {
  font-family: "Newsreader", Georgia, serif;
  font-weight: 400;
  letter-spacing: -.04em;
  font-size: clamp(38px, 5.2vw, 64px);
  line-height: 1.0;
  margin: 0;
  text-wrap: balance;
  text-shadow: 0 2px 20px rgba(0, 0, 0, .16);
}
.login-lead {
  font-size: 18px;
  max-width: 560px;
  margin: 22px auto 0;
  color: rgba(255, 255, 255, .87);
}

/* The card the buttons live on: light, so the provider marks sit on the
   background each vendor's guidelines assume, rather than on a photograph. */
.login-card {
  margin-top: 38px;
  width: min(420px, 100%);
  background: rgba(253, 251, 247, .97);
  color: var(--ink);
  border-radius: 20px;
  padding: 30px 28px 26px;
  box-shadow: 0 46px 38px -26px rgba(3, 20, 30, .45);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.login-fineprint { font-size: 12.5px; margin: 18px 0 0; color: var(--muted); }

/* Sign in with Apple. Apple publishes requirements for this control: their
   mark, their wording, a black pill, and a minimum height. */
.apple-signin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-width: 0;
  height: 48px;
  padding: 0 22px;
  background: #000;
  color: #fff;
  border-radius: 10px;
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -.01em;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
}
.apple-signin:hover { background: #1a1a1a; }
.apple-signin .apple-logo { width: 15px; height: 18px; margin-top: -2px; }
.apple-signin + .apple-signin { margin-top: 12px; }

/* Google's guidelines want their mark on white, not on Apple's black. */
.google-signin { background: #fff; color: #3c4043; border: 1px solid #dadce0; box-shadow: none; }
.google-signin:hover { background: #f7f8f8; }
.google-signin .google-logo { width: 18px; height: 18px; }

.login-page .site-footer {
  margin: 0;
  padding: 56px max(24px, calc(50% - 780px)) 24px;
}
.site-footer {
  margin: 0 calc(50% - 50vw);
  padding: 56px calc(50vw - 50% + 4px) 24px;
  background: var(--navy);
  color: #fff;
}
.site-footer .footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 60px;
  max-width: 1560px;
  margin: 0 auto;
}
.site-footer .brand { color: #fff; font-size: 21px; }
.site-footer .brand-mark { color: #fff; }
.site-footer p { color: rgba(255, 255, 255, .55); max-width: 250px; font-size: 14px; }
.site-footer h3 { font-size: 13px; margin: 0 0 15px; color: var(--gold); }
.site-footer .footer-grid > div:not(:first-child) { display: flex; flex-direction: column; gap: 10px; }
.site-footer .footer-grid a:not(.brand) { font-size: 13px; color: rgba(255, 255, 255, .68); }
.site-footer .footer-grid a:not(.brand):hover { color: #fff; }
.site-footer .footer-bottom {
  max-width: 1560px;
  margin: 44px auto 0;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, .1);
  font-size: 11px;
  color: rgba(255, 255, 255, .38);
}

@media (max-width: 860px) {
  .site-footer .footer-grid { grid-template-columns: 1fr 1fr; gap: 30px; }
  .site-header { gap: 18px; }
  .site-header nav { gap: 16px; }
}

/* ---------------- Label browser (Photos) ---------------- */

.disclosure { margin-bottom: 20px; }
.disclosure summary {
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
}
.disclosure summary::-webkit-details-marker { display: none; }
.disclosure summary::after { content: "▾"; color: var(--muted); }
.disclosure[open] summary::after { content: "▴"; }
.disclosure-body {
  margin-top: 12px;
  padding: 14px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  max-height: 260px;
  overflow-y: auto;
}
.label-list { display: flex; flex-wrap: wrap; gap: 6px; }
.label-chip {
  font-size: 12px;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--cream);
  border: 1px solid var(--line);
  color: var(--ink);
  cursor: pointer;
  font-family: inherit;
}
.label-chip:hover { border-color: var(--gold-dark); }
.label-chip[aria-pressed="true"] {
  background: var(--gold);
  border-color: var(--gold-dark);
  color: var(--navy);
  font-weight: 600;
}
.label-chip .n { color: var(--muted); margin-left: 5px; }
.label-chip[aria-pressed="true"] .n { color: rgba(7, 28, 41, .6); }

/* ---------------- People: show every appearance ---------------- */

.appearances-more {
  align-self: center;
  font-size: 12px;
  font-weight: 600;
  color: var(--gold-dark);
  background: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  padding: 4px 6px;
}
.appearances-more:hover { text-decoration: underline; }

/* ---------------- Timeline: skipped time, no-wrap strips ---------------- */

/* Four photos on one row, never two. A wrapped strip makes cards in the same
   lane different heights, which is what the uniform box was meant to avoid. */
.tl-strip { flex-wrap: nowrap; }

/* A run of empty months is drawn as a break in the axis rather than as
   distance, so a decade with no photos costs a centimetre instead of a metre.
   The stroke is an inline SVG polyline that starts and ends exactly on the
   axis, rising above it and dipping below, so the break reads as part of the
   line rather than as a shape floating near it. */
.tl-jump {
  position: absolute;
  width: 30px;
  height: 22px;
  /* translate up by half the box, then down one pixel: the axis is a 2px
     rule positioned by its top edge, so its centre line is at AXIS_Y + 1.
     Centring the break on AXIS_Y itself left it a pixel high. */
  transform: translate(-50%, calc(-50% + 1px));
  z-index: 2;
  /* Two layers, zigzag on top of a short opaque band. The band is only as tall
     as the axis rule it interrupts -- an opaque box the full height of the
     glyph also swallowed the month ticks, which sit in the 9px directly above
     the axis. */
  background-repeat: no-repeat, no-repeat;
  background-position: center, center;
  background-size: 30px 22px, 30px 4px;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 22'%3E%3Cpolyline points='0,11 6,11 11,3 19,19 24,11 30,11' fill='none' stroke='%238a6f5c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"),
    linear-gradient(var(--paper), var(--paper));
}

.scale-end { font-size: 11px; color: var(--muted); text-transform: lowercase; }


/* ---------------- Memory overlay ----------------
 * The shape the digest email uses: the event's own photo behind its title,
 * with the content flush against it -- no gap, and no rounded corners at the
 * join, so the two read as one card rather than two stacked ones.
 */

.event-overlay {
  position: fixed; inset: 0; z-index: 95;
  background: rgba(7, 28, 41, .90);
  display: flex; align-items: center; justify-content: center;
  padding: 28px;
}
.event-overlay[hidden] { display: none; }
.event-sheet {
  width: min(860px, 100%);
  max-height: 100%;
  overflow-y: auto;
  background: #fff;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.event-hero {
  position: relative;
  min-height: 320px;
  background-size: cover;
  background-position: center;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  display: flex;
  align-items: flex-end;
}
.event-hero-bare { background: var(--navy-2); }
.event-hero-scrim {
  width: 100%;
  padding: 90px 34px 26px;
  color: #fff;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: linear-gradient(180deg, rgba(4, 21, 31, .05) 0%, rgba(4, 21, 31, .55) 55%, rgba(4, 21, 31, .88) 100%);
}
.event-hero-ago {
  margin: 0 0 8px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .14em;
  font-weight: 700;
  color: var(--gold);
}
.event-hero h2 {
  margin: 0;
  font-size: 38px;
  line-height: 1.05;
  color: #fff;
}
.event-hero-meta { margin: 10px 0 0; font-size: 14px; color: rgba(255, 255, 255, .82); }

.event-body { padding: 26px 34px 30px; }
.event-overlay-summary { margin: 0 0 16px; color: #3d4850; font-size: 15.5px; line-height: 1.6; }
.event-overlay-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 6px;
  margin-top: 16px;
}
.event-overlay-grid img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: 8px; cursor: zoom-in; background: var(--cream);
}

/* A memory card is itself a button on the Memories tab. */
.event-card { cursor: pointer; transition: transform .12s ease, box-shadow .12s ease; }
.event-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.tl-card { cursor: pointer; }

/* ---------------- People overlay ---------------- */

.person-sheet {
  width: min(1000px, 100%);
  max-height: 100%;
  overflow-y: auto;
  background: #fff;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 26px 30px 30px;
}
.person-sheet-head { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.person-sheet-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 6px;
}
.person-sheet-grid img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: 8px; cursor: zoom-in; background: var(--cream);
}
.person-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; align-items: center; }
.person-card.is-hidden { opacity: .62; }
.toggle-hidden { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--muted); }

/* The buttons keep their place on one row; whichever panel is open unfolds
   across the full width beneath them, so opening a filter never shuffles the
   other one sideways. Only one is open at a time. */
.filter-row { margin-bottom: 18px; }
.filter-tabs { display: flex; gap: 10px; flex-wrap: wrap; }
.filter-tabs { align-items: center; }
.filter-tab, .filter-daterange {
  /* One height for everything on this row: the range sits beside the tabs, and
     a couple of pixels out is the sort of thing you cannot stop seeing. */
  min-height: 38px;
  box-sizing: border-box;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  display: inline-flex;
  align-items: center;
}
.filter-tab {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  gap: 8px;
  padding: 0 14px;
  cursor: pointer;
}
.filter-tab::after { content: "▾"; color: var(--muted); }
.filter-tab[aria-expanded="true"] { border-color: var(--gold-dark); }
.filter-tab[aria-expanded="true"]::after { content: "▴"; }
.filter-panel {
  margin-top: 10px;
  padding: 14px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  max-height: 300px;
  overflow-y: auto;
}
.filter-panel[hidden] { display: none; }


/* ---------------- People as filters ----------------
 * A face is what you recognise; a name is what you read when you are not sure.
 * So the chip is the crop, and the name arrives on hover or keyboard focus.
 */

.face-list { display: flex; flex-wrap: wrap; gap: 10px; }
.face-chip {
  position: relative;
  width: 58px;
  height: 58px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 50%;
  background: var(--cream);
  cursor: pointer;
  overflow: visible;
}
.face-chip img {
  width: 100%; height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}
.face-chip[aria-pressed="true"] { border-color: var(--gold-dark); }
.face-chip[aria-pressed="true"] img { box-shadow: 0 0 0 2px #fff inset; }
.face-chip .face-name {
  position: absolute;
  left: 50%;
  top: calc(100% + 6px);
  transform: translateX(-50%);
  background: var(--navy);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 6px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease;
  z-index: 3;
}
.face-chip:hover .face-name,
.face-chip:focus-visible .face-name { opacity: 1; }

/* ---------------- Memorability ----------------
 * A heart that shrinks and drains to grey, rather than a number nobody can
 * calibrate. The score still rides along as the tooltip for anyone who wants it.
 */

.score-heart { display: inline-flex; flex: 0 0 auto; align-items: center; }
.score-heart svg { width: 100%; height: 100%; display: block; }

/* ---------------- People cards ----------------
 * Six across, two rows: a fixed column count is what makes "two full rows" a
 * promise rather than something that depends on the window width.
 */

.person-appearances {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 5px;
}
.person-appearances img,
.person-appearances .more-tile {
  width: 100%;
  aspect-ratio: 1;
  height: auto;
}
.more-tile {
  position: relative;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  background: var(--cream);
  border: 0;
  padding: 0;
}
.more-tile img { filter: brightness(.42); }
.more-tile span {
  position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%);
  color: #fff; font-weight: 700; font-size: 12px;
  text-align: center; pointer-events: none;
}

/* Stepping between memories from inside the overlay. Sat against the edges of
   the screen rather than the sheet, so they stay put as sheets of different
   heights come and go. */
.event-step {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .34);
  background: rgba(255, 255, 255, .12);
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
  z-index: 2;
}
.event-step:hover { background: rgba(255, 255, 255, .26); }
.event-step:disabled { opacity: .25; cursor: default; }
.event-step:disabled:hover { background: rgba(255, 255, 255, .12); }
.event-prev { left: 18px; }
.event-next { right: 18px; }

@media (max-width: 900px) {
  .event-step { width: 38px; height: 38px; }
  .event-step svg { width: 18px; height: 18px; }
  .event-prev { left: 6px; }
  .event-next { right: 6px; }
}

/* ---------------- Places as a hierarchy ---------------- */

/* Cascading columns: country, then region, then city. An indented tree of four
   levels spends most of its width on indentation and still makes you hunt for
   the row you want. */
.place-columns { display: flex; gap: 10px; align-items: stretch; }
.place-column {
  flex: 0 0 236px;
  max-height: 300px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  padding: 5px;
}
.place-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  border: 0;
  border-radius: 8px;
  background: none;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  text-align: left;
  padding: 7px 8px;
  cursor: pointer;
}
.place-item:hover { background: rgba(16, 34, 46, .05); }
.place-item.is-active { background: var(--cream); font-weight: 600; }
.place-item[aria-pressed="true"] { background: rgba(239, 193, 109, .3); }
.place-item-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.place-item-count { flex: 0 0 auto; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.place-item-check { flex: 0 0 auto; width: 13px; color: var(--gold-dark); font-weight: 700; }
.place-item-more { flex: 0 0 auto; width: 9px; color: var(--muted); }
.place-item-all { font-style: italic; color: var(--muted); }
.place-item-all[aria-pressed="true"] { font-style: normal; color: var(--ink); }

/* Places need room for three columns; the other panels do not. */
#panel-places, #events-panel-places, #tl-panel-places { max-height: none; }

/* ---------------- A named person, with their face ----------------
 * The crop overlaps the chip's leading edge rather than sitting inside it, so
 * the name keeps its full width and is never pushed out by the picture.
 */
.person-chip { position: relative; padding-left: 26px; }
.person-chip-face {
  position: absolute;
  left: -7px;
  top: 50%;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid #fff;
  background: var(--cream);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
}
.event-tags.with-faces { gap: 12px; padding-left: 8px; }

/* The heart on a memory's hero: top right, over the photograph. */
.score-heart.hero-heart {
  position: absolute;
  top: 18px;
  right: 22px;
  z-index: 2;
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, .45));
  opacity: 1 !important;
}

/* Chevrons as SVG rather than as text glyphs: a "‹" carries the font's own
   side bearings and sat off-centre in its circle whatever the line-height. */
.event-step svg { width: 22px; height: 22px; display: block; }

/* ---------------- Time range ----------------
 * Two handles on one rail. A from/to pair of date fields lets you state half a
 * range, which is a filter that silently does nothing until you remember the
 * other box; a range with two ends cannot be half-said.
 */

.filter-daterange { padding: 0 14px; flex: 1 1 340px; max-width: 460px; min-width: 260px; }
.time-range-inline { display: flex; align-items: center; gap: 10px; width: 100%; }

.time-range {
  position: relative;
  flex: 1 1 auto;
  min-width: 60px;
  height: 22px;
}
.time-range-rail {
  position: absolute;
  top: 50%;
  left: 0; right: 0;
  height: 5px;
  transform: translateY(-50%);
  background: var(--line);
  border-radius: 3px;
}
.time-range-fill {
  position: absolute;
  top: 0; bottom: 0;
  background: var(--gold);
  border-radius: 3px;
}
/* Both inputs stack on the rail. The track ignores the pointer so a click
   lands on whichever handle is nearest rather than on the input on top. */
.tr-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 22px;
  margin: 0;
  padding: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  pointer-events: none;
}
.tr-input::-webkit-slider-thumb {
  -webkit-appearance: none;
  pointer-events: auto;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--gold-dark);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .22);
  cursor: grab;
}
.tr-input::-moz-range-thumb {
  pointer-events: auto;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--gold-dark);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .22);
  cursor: grab;
}
.tr-input::-moz-range-track { background: none; }
.tr-input:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--ink); outline-offset: 2px; }

.tr-label {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Each end of the range is a label and a date field at once: the input lies
   transparent over the text, so a click opens the browser's own calendar
   without the control needing a second row of widgets. */
.tr-label { position: relative; display: inline-flex; align-items: center; }
.tr-label-text { pointer-events: none; }
.tr-date {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  border: 0;
  padding: 0;
  margin: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  /* Enough of a target to hit even when the label reads just "Today". */
  min-width: 70px;
}
.tr-label:hover .tr-label-text { color: var(--gold-dark); text-decoration: underline dotted; }
.tr-date:focus-visible + .tr-label-text,
.tr-label:focus-within .tr-label-text { outline: 2px solid var(--gold-dark); outline-offset: 2px; }

/* Upload progress */

/* ---------------- Hiding and sharing ---------------- */

/* Hidden things are dimmed rather than absent when the page is deliberately
   showing them, so which is which is obvious without reading each one. */
.photo-tile.is-hidden, .event-card.is-hidden { opacity: .45; }
.photo-tile.is-hidden:hover, .event-card.is-hidden:hover { opacity: .75; }

.filter-showhidden {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 38px; padding: 0 12px;
  font-size: 14px; color: var(--muted); cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
  white-space: nowrap;
}
.filter-showhidden input { margin: 0; cursor: pointer; }

.overlay-actions {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line);
}
.overlay-note { font-size: 12.5px; }

.button.subtle {
  background: #fff; color: var(--ink);
  border: 1px solid var(--line); font-weight: 600;
}
.button.subtle:hover { background: rgba(16, 34, 46, .04); }
.button.subtle:disabled { opacity: .5; cursor: default; }

.share-panel { margin-top: 14px; }
.share-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.share-email {
  flex: 1 1 220px; min-width: 0; min-height: 38px; padding: 0 12px;
  font: inherit; font-size: 14px;
  border: 1px solid var(--line); border-radius: 10px; background: #fff;
}
.share-status { margin: 8px 0 0; font-size: 13px; min-height: 1.2em; }
.share-status.is-error { color: var(--bad); }

.share-list { margin-top: 12px; }
.share-entry {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0; font-size: 13.5px;
}
.share-entry.is-revoked .share-who { text-decoration: line-through; color: var(--muted); }
.share-who { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.share-when { flex: 0 0 auto; font-size: 12.5px; }
.share-empty, .share-caveat { font-size: 12.5px; margin: 8px 0 0; }

.link-button {
  border: 0; background: none; padding: 0; font: inherit; font-size: 12.5px;
  color: var(--bad); cursor: pointer; text-decoration: underline;
}
.link-button:disabled { opacity: .5; cursor: default; }

/* The account block on Settings: label/value pairs, not a form. */
.account-rows { margin: 0 0 16px; }
.account-rows .detail-row { padding: 7px 0; }

@media (max-width: 900px) {
  /* Matching the marketing site's own breakpoint behaviour: the nav and the
     call to action step aside rather than wrapping into a second row. */
  .site-header nav, .site-header .button-gold { display: none; }
  .login-hero-content h1 { font-size: clamp(34px, 8vw, 46px); }
  .site-footer .footer-grid { grid-template-columns: 2fr 1fr 1fr; gap: 38px; }
  .site-footer .footer-grid > div:last-child { display: none; }
}
@media (max-width: 600px) {
  .site-header { width: calc(100% - 30px); }
  .login-card { padding: 24px 20px 20px; }
  .site-footer .footer-grid { grid-template-columns: 1fr 1fr; }
  .site-footer .footer-grid > div:first-child { grid-column: 1 / -1; }
}

/* A person chip you can name from where you found them. */
.person-chip.is-editable { cursor: text; }
.person-chip.is-editable:hover { background: rgba(16, 34, 46, .07); }
.person-chip.is-editable:focus-visible { outline: 2px solid var(--gold-dark); outline-offset: 1px; }
/* Unnamed reads as an invitation rather than a label, so it is deliberately
   quieter than a name but not so quiet it looks disabled. */
.person-chip.is-unnamed .person-chip-label { color: var(--muted); font-style: italic; }
.person-chip-input {
  font: inherit;
  font-size: inherit;
  width: 9em;
  min-width: 0;
  padding: 0 2px;
  border: 0;
  border-bottom: 1px solid var(--gold-dark);
  background: transparent;
  color: var(--ink);
  outline: none;
}

/* A failure worth saying out loud but not worth a page for. Sits above the
   overlays, since that is where the actions that can fail live. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 12px);
  z-index: 200;
  max-width: min(520px, calc(100% - 40px));
  padding: 12px 18px;
  border-radius: 10px;
  background: var(--bad);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 14px 32px rgba(3, 20, 30, .32);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* Stopped is not failed: the run was halted, nothing went wrong. Grey rather
   than red, and the row says so. */
.upload-row.is-stopped .upload-row-dot { background: var(--muted); opacity: .75; }
.upload-row.is-stopped .upload-row-name { color: var(--muted); }
.upload-row.is-checking .upload-row-dot { background: var(--muted); opacity: .6; }

/* How much of the allowance is gone. One bar, because the photo count and the
   byte count are two limits but only the nearer one matters. */
.quota-bar {
  height: 8px;
  border-radius: 999px;
  background: rgba(16, 34, 46, .1);
  overflow: hidden;
  margin: 12px 0 0;
}
.quota-bar > span { display: block; height: 100%; background: var(--gold-dark); }
.quota-note { font-size: 12.5px; margin: 10px 0 0; }

/* Files a run cannot admit: named before they are attempted, rather than
   discovered as a refusal partway through. */
.upload-row.is-overquota .upload-row-dot { background: var(--bad); opacity: .55; }
.upload-row.is-overquota .upload-row-detail { color: var(--bad); }
