/* Shared styling for the auth pages (signup/login/dashboard) — a plain,
   lightweight echo of the timeline prototype's warm palette, not the
   full app styling. Phase 2+ will bring the real tree/timeline UI over
   to run against these same accounts. */
:root {
  --paper: #F4EFE6;
  --paper-2: #EBE4D6;
  --card: #FBF8F1;
  --ink: #1A1714;
  --ink-soft: #4A443D;
  --ink-faint: #8A7F6C;
  --line: #D8CFBD;
  --accent: #9A2A2A;
  --accent-glow: #C24B4B;
  --on-accent: #FBF8F1;
  --error: #9A2A2A;
  --error-bg: #F1DCDC;
  /* Phase 85: was only ever defined locally inside tree.php's and
     timeline.php's own :root overrides (identical value in both) --
     centralized here now that .segmented (below) needs it on every
     page that uses that format, including pages that never defined
     it themselves (calendar.php, edit_person.php, pending.php). */
  --shadow: 0 1px 2px rgba(26,23,20,0.08), 0 10px 26px -14px rgba(26,23,20,0.28);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 32px;
  width: 100%;
  max-width: 380px;
  box-shadow: 0 1px 3px rgba(26, 23, 20, 0.06);
}

.brand {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 22px;
}

.brand-mark { width: 44px; height: 44px; flex: none; display: block; }

.brand-text { display: flex; flex-direction: column; }

.wordmark {
  font-size: 22px;
  font-weight: 700;
  margin: 0;
}

.wordmark .tld { font-weight: 500; color: var(--ink-faint); }

.subtitle {
  font-family: Georgia, serif;
  font-style: italic;
  color: var(--ink-soft);
  font-size: 14px;
  margin: 3px 0 0;
}

label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 16px 0 6px;
}

input[type="text"],
input[type="email"],
input[type="password"] {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-size: 15px;
  background: #fff;
  color: var(--ink);
}

input:focus { outline: 2px solid var(--accent-glow); outline-offset: 1px; }

.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

button.btn-primary {
  width: 100%;
  margin-top: 22px;
  padding: 11px 16px;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

button.btn-primary:hover { background: var(--accent-glow); }

/* Phase 46: a secondary, outlined counterpart to .btn-primary -- same
   size and shape, so a genuine alternative action (e.g. "start a new
   family tree" on login.php) reads as an equally real choice rather
   than a footnote link. */
a.btn-secondary, button.btn-secondary {
  display: block;
  cursor: pointer;
  font-family: inherit;
  box-sizing: border-box;
  width: 100%;
  margin-top: 22px;
  padding: 10px 16px;
  border: 2px solid var(--accent);
  border-radius: 999px;
  background: transparent;
  color: var(--accent);
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
}

a.btn-secondary:hover, button.btn-secondary:hover { background: var(--paper-2); }

.error {
  background: var(--error-bg);
  color: var(--error);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 14px;
  margin-top: 16px;
}

/* Phase 45: a neutral explanatory box, distinct from .error -- used on
   signup.php to warn that it starts a brand-new, disconnected family
   tree before anyone fills the form in. */
.notice {
  background: var(--paper-2);
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  line-height: 1.45;
  margin-top: 16px;
}

.foot-link {
  margin-top: 20px;
  font-size: 14px;
  color: var(--ink-soft);
  text-align: center;
}

.foot-link a { color: var(--accent); text-decoration: none; }
.foot-link a:hover { text-decoration: underline; }

/* ---------- onboarding tour (Phase 28; shared across every page that
   runs it since Phase 42 -- see includes/tour_engine.php and /tour.js) ---------- */
/* Phase 57: z-index raised from 200/201/202 to clear 1000 -- the ceiling
   already used by this app's own modals (postcard-overlay, edit-popup-
   overlay, invite-draft-overlay). A step can now open the postcard/letter
   composer on timeline.php mid-tour (see TOUR_ACTIONS in /tour.js), so the
   tour itself has to render on top of it, not underneath. */
.tour-scrim { position:fixed; inset:0; background:rgba(20,16,12,.55); z-index:1500; opacity:0; pointer-events:none; transition:opacity .15s ease; }
.tour-scrim.open { opacity:1; pointer-events:auto; }
.tour-highlight { position:fixed; border:3px solid var(--accent); border-radius:14px; box-shadow:0 0 0 4px rgba(154,42,42,.25); pointer-events:none; transition:top .2s ease, left .2s ease, width .2s ease, height .2s ease; z-index:1501; }
.tour-tooltip { position:fixed; background:var(--card); border:1px solid var(--line); border-radius:16px; padding:18px 20px; width:280px; box-shadow:0 20px 46px -18px rgba(26,23,20,.5); z-index:1502; transition:top .2s ease, left .2s ease; }
.tour-tooltip.tour-centered { position:fixed; top:50% !important; left:50% !important; transform:translate(-50%,-50%); width:300px; }
.tour-tooltip h4 { margin:0 0 8px; font-family:"Fraunces",Georgia,serif; font-size:17px; color:var(--ink); }
.tour-tooltip p { margin:0 0 16px; font-size:13.5px; color:var(--ink-soft); line-height:1.5; }
.tour-footer { display:flex; align-items:center; justify-content:space-between; gap:10px; }
.tour-step-label { font-size:11.5px; color:var(--ink-faint); }
.tour-skip { font-size:12.5px; background:transparent; border:none; color:var(--ink-faint); cursor:pointer; padding:0; text-decoration:underline; }
.tour-next { padding:8px 16px; border:none; border-radius:999px; background:var(--accent); color:var(--on-accent); font-size:13.5px; font-weight:600; cursor:pointer; }
.tour-next:hover { background:var(--accent-glow); }
/* Phase 70: "go back to the previous step at any point" -- grouped with
   Next rather than off on its own next to Skip, since the two read as a
   pair of controls stepping through the same sequence. */
.tour-nav-btns { display:flex; align-items:center; gap:8px; }
.tour-prev { padding:8px 14px; border:1px solid var(--line); border-radius:999px; background:transparent; color:var(--ink-soft); font-size:13px; font-weight:600; cursor:pointer; font-family:inherit; }
.tour-prev:hover:not(:disabled) { background:var(--paper-2); }
.tour-prev:disabled { opacity:.35; cursor:default; }

/* Phase 42: a small illustrative diagram inline in the tooltip, for a step
   explaining a concept (what a family tree is) rather than pointing at
   something real on screen -- see the DIAGRAMS map in /tour.js. */
.tour-diagram { margin:0 0 16px; }
.tour-diagram-svg { display:block; width:100%; height:auto; max-height:120px; }
.tour-diagram-line { stroke:var(--ink-faint); stroke-width:2; }
.tour-diagram-node { fill:var(--card); stroke:var(--ink); stroke-width:2; }
.tour-diagram-node-me { stroke:var(--accent); stroke-width:2.5; }
.tour-diagram-label { font-size:11px; font-weight:700; fill:var(--ink-soft); text-anchor:middle; dominant-baseline:middle; }
.tour-diagram-caption { margin:6px 0 0; font-size:11px; color:var(--ink-faint); text-align:center; }

/* Phase 42: animated arrows/labels a step can draw over the live page to
   call out specific spots -- see renderAnnotations() in /tour.js. Nested
   inside #tourScrim so it fades in/out together with the scrim itself. */
.tour-anno-layer { position:fixed; inset:0; z-index:1501; pointer-events:none; }
.tour-anno-svg { position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.tour-anno-path { fill:none; stroke:var(--accent); stroke-width:2.5; stroke-linecap:round; }
.tour-anno-path-traveling { stroke-dasharray:6 7; opacity:.85; animation:tourAnnoTravel 1.1s linear infinite; }
#tourArrowHead path { fill:var(--accent); }
.tour-anno-label { position:fixed; background:var(--accent); color:var(--on-accent); font-size:12.5px; font-weight:700; padding:5px 10px; border-radius:999px; white-space:nowrap; box-shadow:0 6px 16px -6px rgba(26,23,20,.45); opacity:0; animation:tourAnnoFadeIn .35s ease .3s forwards; }
.tour-anno-pulse { animation:tourAnnoFadeIn .35s ease .3s forwards, tourAnnoPulse 1.7s ease-in-out .8s infinite; }
.tour-anno-drop { position:fixed; color:var(--accent); opacity:0; animation:tourAnnoDrop 1.9s ease-in-out infinite; }
@keyframes tourAnnoFadeIn { from { opacity:0; transform:scale(.85); } to { opacity:1; transform:scale(1); } }
@keyframes tourAnnoPulse { 0%,100% { transform:scale(1); } 50% { transform:scale(1.07); } }
@keyframes tourAnnoTravel { to { stroke-dashoffset:-52; } }
@keyframes tourAnnoDrop { 0% { transform:translate(0,0); opacity:0; } 14% { opacity:1; } 82% { opacity:1; } 100% { transform:translate(var(--tour-dx),var(--tour-dy)); opacity:0; } }

/* ---------- shared multi-file attach widget ("photo-drop") ----------
   Phase 25/36: originally add_entry.php's own composer widget --
   an empty-state dropzone that turns into a grid of small
   thumbnails/icons once one or more files are attached, with a
   spinner tile while a HEIC/HEIF file is being converted client-side.
   Phase 43: moved here (was duplicated inline in add_entry.php) since
   timeline.php's memory-viewer "add media" form now uses it too. */
  .photo-drop { border:2px dashed var(--line); border-radius:14px; padding:16px; cursor:pointer; background:var(--paper-2); transition:border-color .15s ease, background .15s ease; }
  .photo-drop:hover, .photo-drop.dragover { border-color:var(--accent); background:var(--accent-bg); }
  .media-picker-empty { display:flex; align-items:center; gap:13px; flex-wrap:wrap; }
  .media-picker-empty[hidden] { display:none; }
  .photo-drop .thumb { width:44px; height:44px; border-radius:10px; background:var(--paper); display:flex; align-items:center; justify-content:center; overflow:hidden; flex:0 0 auto; color:var(--ink-faint); }
  .photo-drop .thumb svg { width:20px; height:20px; }
  .photo-drop .copy { font-size:13.5px; color:var(--ink-soft); }
  .photo-drop .copy b { color:var(--ink); }
  .photo-drop .copy .paste-hint { display:block; font-size:11.5px; opacity:.75; margin-top:2px; }
  .media-picker-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(72px,1fr)); gap:8px; }
  .media-picker-grid[hidden] { display:none; }
  .pick-tile { position:relative; aspect-ratio:1; border-radius:10px; border:1px solid var(--line); background:var(--paper); overflow:hidden; display:flex; align-items:center; justify-content:center; color:var(--ink-faint); }
  .pick-tile img { width:100%; height:100%; object-fit:cover; }
  .pick-tile.has-video, .pick-tile.has-doc { flex-direction:column; gap:4px; padding:6px 4px; text-align:center; }
  .tile-spinner { width:18px; height:18px; border:2px solid var(--line); border-top-color:var(--accent); border-radius:50%; animation:ourthology-spin .8s linear infinite; }
  @keyframes ourthology-spin { to { transform:rotate(360deg); } }
  .pick-tile.has-video svg, .pick-tile.has-doc svg { width:22px; height:22px; flex:0 0 auto; }
  .pick-tile .media-tile-badge { font-size:8.5px; font-weight:800; letter-spacing:.04em; color:var(--ink-soft); background:rgba(255,255,255,.75); border-radius:5px; padding:1px 5px; }
  .pick-tile .media-tile-name { font-size:9px; font-weight:700; color:var(--ink-soft); max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; padding:0 2px; }
  .pick-tile--add { border:2px dashed var(--line); background:transparent; cursor:pointer; color:var(--ink-faint); transition:border-color .15s ease, color .15s ease, background .15s ease; }
  .pick-tile--add svg { width:18px; height:18px; }
  .pick-tile--add:hover { border-color:var(--accent); color:var(--accent); background:var(--accent-bg); }
  .pick-remove { position:absolute; top:3px; right:3px; width:18px; height:18px; border-radius:50%; border:none; background:rgba(26,23,20,.7); color:#fff; font-size:13px; line-height:1; cursor:pointer; padding:0; display:flex; align-items:center; justify-content:center; }
  .pick-remove:hover { background:var(--accent); }
  .media-picker-note { display:block; font-size:12px; color:var(--ink-faint); margin-top:6px; }
  .media-picker-error { display:none; font-size:12.5px; color:var(--accent); margin-top:6px; }
  .media-picker-status { display:none; font-size:12.5px; color:var(--ink-soft); margin-top:6px; }

  /* Phase 72: an explicit "Paste" button beside every picker that already
     supports an image paste, for iOS/Android where there's no Ctrl-V to
     press -- see /clipboard_paste.js. Sits in the empty-state row next to
     "Click to attach"; hidden automatically once files are picked, same
     as the rest of .media-picker-empty. */
  .picker-paste-btn { flex:0 0 auto; display:inline-flex; align-items:center; gap:5px; font-size:12.5px; font-weight:600; padding:6px 12px; border-radius:999px; border:1px solid var(--accent); color:var(--accent); background:#fff; cursor:pointer; font-family:inherit; margin-left:auto; white-space:nowrap; }
  .picker-paste-btn:hover { background:var(--accent-bg); }
  .picker-paste-btn svg { width:14px; height:14px; flex:0 0 auto; }
  /* Phase 103: the Paste button stays once there are photos -- docked in
     its own tile after the "+" (clipboard_paste.js dock()) */
  .pick-tile--paste { border:2px dashed var(--line); background:transparent; display:flex; align-items:center; justify-content:center; cursor:default; }
  .pick-tile--paste .picker-paste-btn { margin:0; padding:6px 10px; font-size:12px; }
  /* Phase 103: a memory holding the most files it can (25) */
  .media-full-note { margin:8px 0 0; font-size:12.5px; color:var(--ink-faint); }
  .year-only-hint { margin:6px 0 0; font-size:12.5px; color:var(--ink-faint); } /* Phase 105 */
  .photo-drop.is-full { cursor:default; }

/* ---------- post-tour nudge (Phase 44) ----------
   Shown once, right after the onboarding tour finishes (Done or Skip) --
   see tour.js's finishTour()/showPostTourNudge(). Deliberately NOT part
   of the tour's own #tourScrim/#tourAnnoLayer machinery, which darkens
   and captures clicks across the whole page while open -- this needs to
   sit quietly on an otherwise fully usable page. */
  .post-tour-nudge { display:flex; align-items:flex-start; gap:10px; background:var(--accent-bg); border:1px solid var(--accent); border-radius:10px; padding:10px 14px; margin:0 0 14px; }
  .post-tour-nudge[hidden] { display:none; }
  .post-tour-nudge p { margin:0; font-size:14px; color:var(--ink-soft); line-height:1.5; }
  .post-tour-nudge p a { color:var(--accent); font-weight:600; }
  .post-tour-nudge button { flex:0 0 auto; border:none; background:transparent; color:var(--ink-faint); font-size:18px; line-height:1; cursor:pointer; padding:0 2px; }
  .post-tour-nudge button:hover { color:var(--accent); }
  .post-tour-arrow { position:fixed; z-index:150; pointer-events:none; transform:translate(-50%, -100%); color:var(--accent); }
  .post-tour-arrow-inner { animation: postTourArrowBounce .7s ease-in-out 4 both, postTourArrowFadeOut .5s ease-in 2.9s forwards; }
  @keyframes postTourArrowBounce { 0%, 100% { transform:translateY(0); } 50% { transform:translateY(10px); } }
  @keyframes postTourArrowFadeOut { to { opacity:0; } }

/* ---------- segmented pill groups (Phase 85) ----------
   Started life inline in timeline.php, styling only the River/Rings/
   Spiral view toggle. Centralized here now that includes/nav.php's
   shared primary nav (My tree / My timeline / Family calendar /
   Pending) and every page's own secondary "other buttons" group both
   use this same format too, across pages that didn't all define the
   same CSS variables locally (--shadow in particular -- see :root
   above). button/a/span all get the same pill treatment: a real toggle
   button (River/Rings/Spiral), a real link (nav items, most of the
   "other buttons"), and a plain non-interactive "you are here" label
   (the current-page item in the primary nav) all render identically. */
.segmented { display:inline-flex; flex-wrap:wrap; background:var(--paper-2); border:1px solid var(--line); border-radius:999px; padding:4px; gap:2px; box-shadow:var(--shadow); }
.segmented button, .segmented a, .segmented span { border:none; background:transparent; color:var(--ink-soft); font-weight:700; font-size:13px; padding:7px 13px; border-radius:999px; cursor:pointer; transition:background .15s ease,color .15s ease,transform .1s ease; white-space:nowrap; text-decoration:none; display:inline-block; font-family:inherit; }
.segmented button:hover, .segmented a:hover { color:var(--ink); }
.segmented button.active, .segmented a.active, .segmented span.active { background:var(--accent); color:var(--on-accent); transform:scale(1.04); cursor:default; }
/* The one item that's always brand-red regardless of active/current-page
   state -- "Send a Message" in each page's secondary button group. */
.segmented .accent-item, .segmented .accent-item:hover { background:var(--accent); color:var(--on-accent); }
/* Pending, when there's something waiting on you, in a group where it
   isn't the active/current-page item -- replaces the old .nav a.badge
   treatment (a different pill shape that doesn't fit inside .segmented). */
.segmented a.has-pending { color:var(--accent); font-weight:800; }
/* Phase 106: "Mailbox" -- a red count bubble, with a soft pulse, when
   something is waiting for you to act on it (includes/nav.php). */
.nav-badge, .segmented span.nav-badge { display:inline-flex; font-weight:800; transform:none; cursor:inherit; transition:none; align-items:center; justify-content:center; min-width:18px; height:18px; padding:0 5px; margin-left:6px; border-radius:999px; background:var(--accent); color:#fff; font:800 11px/18px system-ui, sans-serif; vertical-align:1px; box-sizing:border-box; animation:ourthologyMailPulse 2.4s ease-out infinite; }
.segmented .active span.nav-badge { background:#fff; color:var(--accent); }
@keyframes ourthologyMailPulse { 0% { box-shadow:0 0 0 0 rgba(154,42,42,.45); } 70% { box-shadow:0 0 0 7px rgba(154,42,42,0); } 100% { box-shadow:0 0 0 0 rgba(154,42,42,0); } }
.visually-hidden, .segmented span.visually-hidden { position:absolute !important; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }

/* ---------- Phase 96: the phone layout ----------
   Only below 700px wide, and only on pages that render the shared nav
   (includes/nav.php adds html.m-ui and the markup; mobile_ui.js builds the
   Menu sheet). The desktop header -- the pill nav, the page's row(s) of
   action pills and "Signed in as" -- was stacking into five or six wrapped
   rows on a phone. Here it becomes:
     - a slim top bar: the logo, and a Menu button at the right;
     - a bottom tab bar for the four main destinations;
     - a Menu sheet holding the page's other actions, the tour and Log out;
     - one floating button for the page's main action (where it has one).
   The page itself goes edge to edge instead of sitting inside a card with
   a wide margin, so content gets the whole width of the screen. */
.m-menu-btn, .m-tabbar, .m-sheet, .m-sheet-scrim, .m-fab { display:none; }
/* Phase 130: the bottom tab bar (Tree / Timeline / Calendar / Mailbox) is
   the main navigation on every screen size now -- the old row of pills
   (My tree, My timeline, Family calendar, Mailbox) is gone. */
html.m-ui .nav-primary { display:none !important; }
.m-corner-group { position:absolute; top:20px; right:12px; z-index:8; display:flex; align-items:center; gap:8px; }
.m-corner-group .fm-kin-btn--corner { position:static; }
/* Phase 129: this compact layout now switches on whenever a page's rows of
   buttons can't each fit on one line (html.m-narrow, set by nav.php's
   inline script and mobile_ui.js) -- not only under 700px. On a phone the
   page goes edge to edge; on a wider (split-screen, small laptop) window it
   keeps its card, with the tab bar and Menu sheet centred under it. */
@media (max-width: 700px) {
  html.m-ui.m-narrow body { display:block !important; padding:0 !important; min-height:0; }
  html.m-ui.m-narrow body > .card { max-width:none !important; width:100% !important; margin:0 !important; border:none !important; border-radius:0 !important; box-shadow:none !important;
    padding:14px 16px calc(86px + env(safe-area-inset-bottom, 0px)) !important; position:relative; min-height:100vh; }
  html.m-ui.m-narrow body { background:var(--card, #FBF8F1); }
  html.m-ui.m-narrow.m-has-fab body > .card { padding-bottom:calc(146px + env(safe-area-inset-bottom, 0px)) !important; }
}
html.m-ui.m-narrow body > .card { position:relative; }
@media (min-width: 701px) {
  html.m-ui body > .card { padding-bottom:96px !important; }
  html.m-ui.m-narrow.m-has-fab body > .card { padding-bottom:150px !important; }
  html.m-ui .m-tabbar { left:50% !important; right:auto !important; width:min(560px, calc(100% - 32px)); transform:translateX(-50%); border:1px solid rgba(154,42,42,.26) !important; border-bottom:none !important; border-radius:18px 18px 0 0; }
  html.m-ui.m-narrow .m-sheet { left:50% !important; right:auto !important; width:min(520px, calc(100% - 32px)); }
  html.m-ui.m-narrow .m-sheet:not(.open) { transform:translate(-50%, 100%) !important; }
  html.m-ui.m-narrow .m-sheet.open { transform:translateX(-50%) !important; }
}

  /* top bar */
  html.m-ui.m-narrow .brand { margin:0 0 14px !important; padding-right:96px; gap:10px !important; }
  html.m-ui.m-narrow .brand .brand-mark { width:34px !important; height:34px !important; }
  html.m-ui.m-narrow .brand .wordmark { font-size:21px; }
  html.m-ui.m-narrow .brand .subtitle { display:none; }
  html.m-ui.m-narrow .nav { margin:0 !important; gap:0 !important; }
  html.m-ui.m-narrow .nav-links > .segmented, html.m-ui.m-narrow .nav .whoami, html.m-ui.m-narrow .nav-links > .whoami { display:none !important; }
  html.m-ui.m-narrow .m-menu-btn { display:inline-flex; align-items:center; gap:6px; position:absolute; top:14px; right:16px; height:36px; padding:0 14px 0 11px; border-radius:999px;
    border:1px solid var(--line); background:var(--paper-2); color:var(--ink); font:700 14px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; cursor:pointer; box-shadow:var(--shadow); }
  html.m-ui.m-narrow .m-menu-btn[hidden] { display:none; }
  html.m-ui.m-narrow body > .card > .page-head { position:static; }
  html.m-ui.m-narrow .m-menu-btn svg { width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; }

  /* bottom tab bar */
  html.m-ui .m-tabbar { display:flex; position:fixed; left:0; right:0; bottom:0; z-index:40; background:rgba(251,248,241,.97); border-top:1px solid var(--line);
    padding:6px 6px calc(6px + env(safe-area-inset-bottom, 0px)); box-shadow:0 -6px 18px -12px rgba(26,23,20,.35); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px); }
  /* Phase 131: a fine brand-tinted line around the tab bar so it sits apart from the page */
  html.m-ui .m-tabbar { border-top:1px solid rgba(154,42,42,.26); box-shadow:0 -1px 0 rgba(255,255,255,.7) inset, 0 -8px 22px -14px rgba(26,23,20,.45);
    background:rgba(251,248,241,.7); -webkit-backdrop-filter:blur(12px) saturate(1.3); backdrop-filter:blur(12px) saturate(1.3); } /* semi-transparent, frosted */
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))) { html.m-ui .m-tabbar { background:rgba(251,248,241,.9); } }
  html.m-ui .m-tabbar a { flex:1 1 0; display:flex; flex-direction:column; align-items:center; gap:3px; padding:6px 0 4px; border-radius:12px; color:var(--ink-soft); text-decoration:none;
    font:600 11.5px/1.1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; min-height:48px; -webkit-tap-highlight-color:transparent; }
  /* several pages style every .nav a as a bordered white pill -- not these */
  html.m-ui .nav .m-tabbar a { border:none; background:transparent; padding:6px 0 4px; font-size:11.5px; }
  html.m-ui .nav .m-tabbar a.active { background:var(--accent-bg, #F1DCDC); color:var(--accent); }
  html.m-ui .m-tabbar a.active { color:var(--accent); background:var(--accent-bg, #F1DCDC); }
  html.m-ui .m-tab-icon { position:relative; width:24px; height:24px; }
  html.m-ui .m-tab-icon svg { width:24px; height:24px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
  html.m-ui .m-badge { position:absolute; top:-5px; right:-10px; min-width:18px; height:18px; padding:0 5px; border-radius:999px; background:var(--accent); color:#fff; font:800 11px/18px system-ui, sans-serif; text-align:center; border:2px solid #FBF8F1; }
  html.m-ui .m-tabbar a.has-pending { color:var(--accent); font-weight:800; } /* Phase 106 */
  html.m-ui .m-badge { animation:ourthologyMailPulse 2.4s ease-out infinite; }

  /* Menu sheet */
  html.m-ui.m-narrow .m-sheet-scrim { display:block; position:fixed; inset:0; z-index:44; background:rgba(26,23,20,.4); opacity:0; transition:opacity .2s ease; }
  html.m-ui.m-narrow .m-sheet-scrim.open { opacity:1; }
  html.m-ui.m-narrow .m-sheet-scrim[hidden], html.m-ui.m-narrow .m-sheet[hidden] { display:none; }
  html.m-ui.m-narrow .m-sheet { display:flex; flex-direction:column; position:fixed; left:0; right:0; bottom:0; z-index:45; max-height:82vh; background:var(--card, #FBF8F1);
    border-radius:20px 20px 0 0; box-shadow:0 -10px 30px rgba(26,23,20,.25); padding:8px 16px calc(12px + env(safe-area-inset-bottom, 0px)); transform:translateY(100%); transition:transform .2s ease; }
  html.m-ui.m-narrow .m-sheet.open { transform:none; }
  html.m-ui.m-narrow .m-sheet-grip { width:40px; height:5px; border-radius:3px; background:var(--line); margin:2px auto 10px; flex:none; }
  html.m-ui.m-narrow .m-sheet-body { overflow-y:auto; -webkit-overflow-scrolling:touch; }
  html.m-ui.m-narrow .m-sheet-h { font:600 12px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; color:var(--ink-faint); margin:14px 4px 6px; text-transform:none; letter-spacing:0; }
  html.m-ui.m-narrow .m-sheet-item { display:block; width:100%; text-align:left; min-height:48px; padding:12px 14px; margin:0 0 6px; border:1px solid var(--line); border-radius:12px; background:#fff;
    color:var(--ink); font:600 16px/1.25 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; cursor:pointer; }
  html.m-ui.m-narrow .m-sheet-item:active { background:var(--paper-2); }
  html.m-ui.m-narrow .m-sheet-item.accent { background:var(--accent); border-color:var(--accent); color:var(--on-accent); }
  html.m-ui.m-narrow .m-sheet-close { flex:none; margin-top:6px; min-height:46px; border:none; background:transparent; color:var(--ink-soft); font:700 15px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; cursor:pointer; }

  /* floating main action */
  html.m-ui.m-narrow .m-fab { display:inline-flex; align-items:center; gap:6px; position:fixed; right:16px; bottom:calc(76px + env(safe-area-inset-bottom, 0px)); z-index:39; height:50px; padding:0 20px 0 16px;
    border:none; border-radius:999px; background:var(--accent); color:var(--on-accent); font:700 15.5px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    box-shadow:0 8px 20px -6px rgba(154,42,42,.6); cursor:pointer; }
  html.m-ui.m-narrow .m-fab span { font-size:24px; font-weight:500; line-height:1; margin-top:-2px; }
  /* Phase 130: pinned to the top-right corner of the page's main window
     (timeline, tree) -- clear, but a modest size */
  html.m-ui.m-narrow .m-corner-group { position:absolute; top:12px; right:12px; z-index:8; display:flex; align-items:center; gap:8px; }
  html.m-ui.m-narrow .m-corner-group .fm-kin-btn--corner { position:static; }
  /* Phase 131: a quieter "soft chip" -- cream glass with a thin brand-red
     outline and a small solid red "+" disc: easy to find, doesn't shout */
  html.m-ui.m-narrow .m-fab.m-fab--corner { position:static; height:28px; padding:0 11px 0 4px; gap:6px; border:1px solid rgba(154,42,42,.38);
    background:rgba(251,248,241,.9); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px); color:var(--accent);
    font:600 12.5px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; box-shadow:0 2px 8px -4px rgba(26,23,20,.35); transition:background .15s, transform .15s; }
  html.m-ui.m-narrow .m-fab.m-fab--corner:active { transform:scale(.96); background:#fff; }
  html.m-ui.m-narrow .m-fab.m-fab--corner span { width:20px; height:20px; border-radius:50%; background:var(--accent); color:var(--on-accent);
    display:inline-flex; align-items:center; justify-content:center; font-size:16px; font-weight:600; line-height:1; margin:0; }
  html.m-ui.m-narrow .m-corner-group .fm-kin-btn--corner { height:28px; padding:0 11px 0 9px; font-size:12.5px; }
  /* Phase 132: label text (long or short), and the in-row version on a phone */
  .m-fab em { font-style:normal; }
  .m-fab .m-fab-short { display:none; }
  html.m-ui.m-narrow .m-fab.m-fab--inline { flex:none; height:30px; padding:0 10px 0 4px; }
  html.m-ui.m-narrow .m-fab.m-fab--inline .m-fab-label { display:none; }
  html.m-ui.m-narrow .m-fab.m-fab--inline .m-fab-short { display:inline; }
  /* never over a pop-up, or the print layout */
  html.m-ui.m-narrow.m-modal-open .m-fab, html.m-ui.m-modal-open .m-tabbar { display:none; }

  /* touch-sized pill groups everywhere else on the page */
  html.m-ui.m-narrow .segmented button, html.m-ui.m-narrow .segmented a, html.m-ui.m-narrow .segmented span { padding:9px 14px; }
  /* maps keep their own layers to themselves, so their controls can't
     float over the tab bar */
  html.m-ui.m-narrow .leaflet-container { isolation:isolate; z-index:0; }
@media print { .m-menu-btn, .m-tabbar, .m-sheet, .m-sheet-scrim, .m-fab { display:none !important; } }

/* ---------- Phase 99: drag to reorder photos/documents in an upload box ----------
   (sortable_tiles.js). The dragged tile's slot stays as a faded placeholder
   while a lifted copy follows the pointer. Long-pressing a photo on iOS
   would otherwise pop up "Save Image" and select text instead. */
.pick-tile:not(.pick-tile--add), .pk-tile { cursor:grab; -webkit-user-select:none; user-select:none; -webkit-touch-callout:none; }
.pick-tile img, .pk-tile img { -webkit-user-drag:none; }
.pick-tile:focus-visible, .pk-tile:focus-visible { outline:3px solid var(--accent); outline-offset:2px; }
.sorting, .sorting * { cursor:grabbing !important; }
.sort-placeholder { opacity:.3; outline:2px dashed var(--accent); outline-offset:-2px; }
.sort-drag-ghost { box-shadow:0 14px 30px -8px rgba(26,23,20,.55); transform:scale(1.06) rotate(-2deg); border-radius:10px; overflow:hidden; opacity:.95; }
.sort-hint { font-size:12px; color:var(--ink-faint); margin:6px 0 0; }
.sort-hint[hidden] { display:none; }

/* ---------- Phase 100: maps in English, and the country counter ----------
   geo.js addBaseLayers(): a label-free Esri background, warmed slightly to
   sit with the site's paper tones, with our own English country names on
   top (Natural Earth borders). */
.og-base-tiles { filter:sepia(.22) saturate(.95) brightness(1.02); }
.og-country-label { pointer-events:none; }
.og-country-label span { display:block; text-align:center; white-space:nowrap; font:600 11px/16px Georgia, "Times New Roman", serif; letter-spacing:.06em; text-transform:uppercase;
  color:#6B5E52; text-shadow:0 0 3px #FBF8F1, 0 0 3px #FBF8F1, 0 0 2px #FBF8F1; }
.og-country-label.big span { font-size:12.5px; color:#5A4E44; }

/* The country counter, top right of the life maps (timeline.php). Held
   16px in from the map's edges (Leaflet's own control margin is 10px). */
.leaflet-top.leaflet-right .lm-counter { margin:16px 16px 0 0; }
.lm-counter { min-width:196px; max-width:240px; background:rgba(251,248,241,.97); border:2px solid var(--accent, #9A2A2A); border-radius:14px;
  box-shadow:0 8px 22px -10px rgba(26,23,20,.45); padding:12px 14px 12px; color:var(--ink, #1A1714); font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
.lmc-title { font:700 11.5px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; letter-spacing:.08em; text-transform:uppercase; color:var(--accent, #9A2A2A);
  padding-bottom:8px; margin-bottom:6px; border-bottom:1px solid var(--line, #E4DCCF); }
.lmc-wait, .lmc-none { font-size:12.5px; color:var(--ink-faint, #8A8076); margin:4px 0 0; }
.lmc-table { width:100%; border-collapse:collapse; }
.lmc-table th { text-align:left; font-weight:500; font-size:13px; color:var(--ink-soft, #4A443D); padding:5px 10px 5px 0; vertical-align:baseline; }
.lmc-table td { text-align:right; font-family:Georgia, "Times New Roman", serif; font-weight:700; color:var(--ink, #1A1714); padding:3px 0; vertical-align:baseline; white-space:nowrap; }
.lmc-table tr + tr th, .lmc-table tr + tr td { border-top:1px dashed var(--line, #E4DCCF); }
.lmc-n { font-size:28px; line-height:1.05; color:var(--accent, #9A2A2A) !important; }
.lmc-p { font-size:19px; }
.lmc-toggle { display:block; width:100%; margin-top:8px; padding:6px 0 0; border:none; border-top:1px solid var(--line, #E4DCCF); background:none; color:var(--accent, #9A2A2A);
  font:700 12.5px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; text-align:left; cursor:pointer; }
.lmc-list { list-style:none; margin:6px 0 0; padding:0; max-height:160px; overflow-y:auto; font-size:13px; color:var(--ink-soft, #4A443D); }
.lmc-list[hidden] { display:none; }
.lmc-list li { padding:3px 0; border-bottom:1px solid rgba(228,220,207,.6); }
.lmc-list li:last-child { border-bottom:none; }
@media (max-width: 700px) {
  .leaflet-top.leaflet-right .lm-counter { margin:12px 12px 0 0; }
  .lm-counter { min-width:150px; max-width:176px; padding:9px 11px; }
  .lmc-n { font-size:22px; }
  .lmc-p { font-size:16px; }
  .lmc-table th { font-size:12px; }
}

/* ---------- Phase 101: the "Where it happened" place box, shared ----------
   Used by the memory composer (add_entry.php) and, for a tagged person,
   the memory viewer on timeline.php. Moved here from add_entry.php. */
.loc-row { display:flex; gap:8px; }
.loc-row input { flex:1 1 auto; min-width:0; }
.loc-btn { flex:none; padding:0 14px; border:1px solid var(--line); border-radius:8px; background:#fff; font:inherit; font-size:14px; font-weight:600; color:var(--ink-soft); cursor:pointer; }
.loc-btn:hover { border-color:var(--accent); color:var(--ink); }
.loc-btn:disabled { opacity:.6; cursor:default; }
.loc-homes { display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin-top:8px; font-size:12.5px; color:var(--ink-faint); }
.loc-homes button { font:inherit; font-size:12.5px; padding:4px 10px; border:1px solid var(--line); border-radius:999px; background:#fff; color:var(--ink-soft); cursor:pointer; }
.loc-homes button:hover, .loc-homes button.on { border-color:var(--accent); background:#F1DCDC; color:var(--ink); }
.loc-status { display:flex; flex-wrap:wrap; gap:4px 12px; align-items:center; margin-top:6px; font-size:12.5px; color:var(--ink-soft); }
.loc-status #locMsg:empty { display:none; }
.loc-link { font:inherit; font-size:12.5px; background:none; border:none; padding:0; color:var(--accent); text-decoration:underline; cursor:pointer; }
.loc-link[hidden] { display:none; }
.loc-choices { display:flex; flex-direction:column; gap:4px; margin-top:6px; }
.loc-choices[hidden] { display:none; }
.loc-choices span { font-size:12px; color:var(--ink-faint); }
.loc-choices button { text-align:left; font:inherit; font-size:12.5px; line-height:1.35; padding:6px 9px; border:1px solid var(--line); border-radius:8px; background:#fff; color:var(--ink-soft); cursor:pointer; }
.loc-choices button:hover { border-color:var(--accent); }
.loc-choices button.on { border-color:var(--accent); background:#F1DCDC; color:var(--ink); }
#locMap { height:220px; border-radius:10px; border:1px solid var(--line); margin-top:8px; }
#locMap[hidden] { display:none; }
.viewer-place-form .loc-row input { font-size:15px; padding:9px 11px; border:1px solid var(--line); border-radius:8px; background:#fff; }
.viewer-place-form .btn-ghost { margin-top:10px; }

/* ---------- Phase 102: maps never draw over pop-ups ----------
   Leaflet gives its panes and controls z-indexes up to 1000 (popups 700,
   zoom buttons/the country counter 800-1000), which competed with the
   whole page -- so a memory opened from the map's popup (z-index 50) came
   up UNDER the map's popup and buttons. Each map now keeps its layers to
   itself (its own stacking context at the page's level 0), on every
   screen size -- this used to apply on phones only (Phase 96). */
.leaflet-container { isolation:isolate; z-index:0; }

/* Phase 106: no pulsing for anyone who has asked for less motion */
@media (prefers-reduced-motion: reduce) { .nav-badge, .segmented span.nav-badge, html.m-ui .m-badge { animation:none; } }

/* Phase 114: "please confirm your email" reminder under the main nav */
.verify-banner { flex-basis:100%; order:99; display:flex; flex-wrap:wrap; align-items:center; gap:8px 14px; margin-top:6px;
  background:#fbf1e6; border:1px solid #e8c9a4; color:#6b3a0e; border-radius:10px; padding:8px 12px; font-size:13px; line-height:1.4; }
.verify-banner form { display:inline; margin:0; }
.verify-banner button { background:none; border:none; color:var(--accent); text-decoration:underline; cursor:pointer; font:inherit; padding:0; }
.verify-banner a, .nav-links .verify-banner a { color:var(--ink-faint); font-size:12.5px; background:none !important; border:none !important; padding:0 !important; box-shadow:none !important; border-radius:0 !important; text-decoration:underline; font-weight:400; }
html.m-ui .verify-banner { margin:0 0 10px; }
.verify-banner.nudge { background:#f3f0e8; border-color:var(--line); color:var(--ink-soft); }
.verify-banner a.go, .nav-links .verify-banner a.go { color:var(--accent); font-size:13px; font-weight:600; }
