/* =============================================================
   Trip site — hanabi palette (night sky, gold bursts, festival red)

   THEMES. The light and dark palettes are both built around fireworks:
   light is the festival on paper — warm lantern cream, festival crimson,
   gold — and dark is the sky it happens in, near-black indigo with the
   burst colours turned up. Lavender is a third, separate theme.

   All three set the SAME variable names, so no rule below needs to know
   which theme is active. --accent is the primary; --lav/--lav-deep are
   kept as aliases of it because a great deal of existing CSS refers to
   them by that name, from back when the accent actually was lavender.
   ============================================================= */
@import url('https://fonts.googleapis.com/css2?family=Zen+Kaku+Gothic+New:wght@400;500;700;900&family=Inter:wght@400;500;600;700&display=swap');

:root {
  /* Light — the festival on paper: lantern-warm cream, festival crimson,
     the gold off the fireworks themselves. */
  --ink:        #241d33;
  --ink-soft:   #63597a;
  --cream:      #fdf8f2;
  --paper:      #ffffff;
  --tint:       #fdeee1;
  --accent:     #c8305c;
  --accent-deep:#9b1f45;
  --lav:        var(--accent);        /* historical names, kept so the rest */
  --lav-deep:   var(--accent-deep);   /* of this file needs no rewrite */
  --green:      #2c8f79;
  --green-dp:   #1d6f5d;
  --gold:       #d99213;
  --coral:      #e0603f;
  --line:       #f0e2d3;
  --amber:      #8f5f10;
  --amber-tint: #fbeed8;
  --shadow:     0 12px 34px -16px rgba(90, 35, 65, .28);
  --radius:     18px;
  --wrap:       1080px;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; font-family: 'Inter', system-ui, -apple-system, sans-serif;
  color: var(--ink); background: var(--cream); line-height: 1.6; -webkit-font-smoothing: antialiased;
}
h1, h2, h3, .nav__brand { font-family: 'Zen Kaku Gothic New', 'Inter', sans-serif; }
a { color: var(--lav-deep); }
img { max-width: 100%; display: block; }
/* No form control may force layout wider than its container — datetime-local
   and selects have big fixed intrinsic widths that otherwise stretch the page
   past the phone screen; Android then lets the site "zoom out" and snaps the
   zoom back on every reflow.

   font-size is NOT optional here: a control smaller than 16px makes mobile
   Safari zoom the page in when it takes focus, and it does NOT zoom back out
   on blur. You're then left pinching to zoom out on every later page load,
   and — because .bnav is position:fixed, i.e. pinned to the LAYOUT viewport —
   the bottom nav sits off-screen until you scroll. Controls inherit nothing
   from body by default; unstyled ones land on the UA's 13.33px. 16px floor
   here, so a new control can never reintroduce that. */
input, select, textarea { max-width: 100%; min-width: 0; font-size: max(16px, 1rem); }

/* ---------- Nav ---------- */
.nav {
  position: sticky; top: 0; z-index: 50; display: flex; align-items: center; flex-wrap: wrap;
  justify-content: space-between; gap: 1rem; padding: .8rem clamp(1rem, 4vw, 2.5rem);
  background: rgba(251, 249, 244, .85); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line);
}
.nav__brand { font-weight: 900; font-size: 1.15rem; text-decoration: none; color: var(--ink); }
.nav__brand span { color: var(--lav); font-weight: 700; font-size: .8rem; letter-spacing: .18em; text-transform: uppercase; }
.nav__links { display: flex; align-items: center; gap: clamp(.6rem, 2vw, 1.5rem); flex-wrap: wrap; }
.nav__links a { text-decoration: none; font-weight: 500; font-size: .92rem; color: var(--ink-soft); border-bottom: 2px solid transparent; transition: .15s; }
.nav__links a:hover { color: var(--lav-deep); border-color: var(--lav); }
.nav__cta { background: var(--lav); color: #fff !important; padding: .4rem .9rem; border-radius: 999px; border: none !important;
            font: inherit; font-weight: 600; font-size: .92rem; cursor: pointer; }
.nav__cta:hover { background: var(--lav-deep); }
.nav__links form { display: inline; margin: 0; }
/* Trip clock: countdown/day chip in the top bar; click for world times & distance */
.tclock { position: relative; }
.tclock summary { list-style: none; }
.tclock summary::-webkit-details-marker { display: none; }
.tclock__chip {
  display: inline-block; cursor: pointer; white-space: nowrap;
  background: var(--tint); color: var(--lav-deep);
  font-weight: 800; font-size: .85rem; padding: .35rem .85rem; border-radius: 999px;
  border: 1px solid var(--line);
}
.tclock[open] .tclock__chip { background: var(--lav); color: #fff; border-color: var(--lav); }
.tclock__panel {
  position: absolute; top: calc(100% + .55rem); left: 50%; transform: translateX(-50%);
  min-width: 15.5rem; z-index: 70;
  background: var(--paper); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow); padding: .75rem .95rem; display: grid; gap: .45rem;
}
.tclock__row { display: flex; justify-content: space-between; gap: 1.2rem; font-size: .9rem; white-space: nowrap; }
.tclock__row span { color: var(--ink-soft); }
.nav__badge { font-size: .8rem; background: var(--tint); color: var(--lav-deep); padding: .3rem .7rem; border-radius: 999px; font-weight: 600; }

/* ---------- Flash ---------- */
.flash { max-width: var(--wrap); margin: .8rem auto -1rem; padding: .8rem 1.1rem; background: #eafaf2;
  border: 1px solid #bce8d3; color: var(--green-dp); border-radius: 12px; font-weight: 500; }

/* ---------- Hero ---------- */
.hero { position: relative; overflow: hidden; color: #fff; }
.hero--slim .hero__inner { padding-top: clamp(3rem, 8vw, 5rem); padding-bottom: clamp(3rem, 8vw, 5rem); }
.hero__bg { position: absolute; inset: 0;
  /* A cat watching hanabi over the water — hand-built SVG (tools/gen_hero.py),
     so it is pin-sharp on a 4K display and still ~38KB. The scrim over it is
     light and top-weighted: it darkens where the title sits without greying
     out the bursts. Fallback is the same night sky for the instant before
     the image lands. */
  background:
    linear-gradient(180deg, rgba(6,8,22,.55) 0%, rgba(8,10,28,.14) 42%, rgba(6,8,22,.30) 100%),
    url('../img/hero.svg') center / cover no-repeat,
    linear-gradient(170deg, #10142e 0%, #0a0c1e 55%, #05060f 100%); }
.hero__inner { position: relative; max-width: var(--wrap); margin: 0 auto;
  padding: clamp(3.5rem, 11vw, 7rem) clamp(1.2rem, 5vw, 2.5rem) clamp(3rem, 8vw, 5rem); text-align: center; }
.hero__eyebrow { text-transform: uppercase; letter-spacing: .3em; font-size: .8rem; font-weight: 600; color: #f6e6c9; margin: 0 0 1rem; }
.hero__title { font-size: clamp(3rem, 13vw, 7rem); font-weight: 900; line-height: .95; margin: 0; letter-spacing: -.02em; }
.hero__dates { font-size: clamp(1rem, 3vw, 1.35rem); color: #f7e7c4; margin: 1rem 0 1.8rem; font-weight: 500; }
/* keep hero text readable over the photo background */
.hero__eyebrow, .hero__title, .hero__dates, .hero .countdown, .hero .livechip {
  text-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 2px 20px rgba(0, 0, 0, .75); }

.livechip { display: inline-flex; align-items: center; gap: .55rem; background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.28); padding: .6rem 1.1rem; border-radius: 999px; margin-bottom: 1.8rem; font-size: 1.02rem; }
.livechip strong { font-weight: 700; }
.livechip__dot { width: 10px; height: 10px; border-radius: 50%; background: #7dffb0; box-shadow: 0 0 0 0 rgba(125,255,176,.7); animation: pulse 2s infinite; }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(125,255,176,.6);} 70% { box-shadow: 0 0 0 10px rgba(125,255,176,0);} 100%{box-shadow:0 0 0 0 rgba(125,255,176,0);} }

.countdown { display: inline-flex; gap: clamp(.5rem, 2.5vw, 1.4rem); margin-bottom: 2rem; }
.countdown__cell { min-width: clamp(58px, 16vw, 92px); padding: .8rem .4rem; border-radius: 14px;
  background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.2); }
.countdown__num { display: block; font-size: clamp(1.6rem, 6vw, 2.6rem); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1; }
.countdown__label { display: block; margin-top: .4rem; font-size: .72rem; letter-spacing: .16em; text-transform: uppercase; color: #f6e6c9; }

.btn { display: inline-block; text-decoration: none; font-weight: 600; cursor: pointer; font-size: 1rem;
  padding: .8rem 1.7rem; border-radius: 999px; background: #fff; color: var(--lav-deep); border: none;
  box-shadow: var(--shadow); transition: transform .15s, box-shadow .15s; }
.btn:hover { transform: translateY(-2px); }
.btn--ghost { background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.5); box-shadow: none; }
.btn--sm { padding: .35rem .7rem; font-size: .82rem; box-shadow: none; background: var(--tint); }
.btn--danger { background: #fbe6e2; color: var(--coral); }

/* ---------- Sections ---------- */
.section { max-width: var(--wrap); margin: 0 auto; padding: clamp(3rem, 8vw, 5.5rem) clamp(1.2rem, 5vw, 2.5rem); }
.section--bare { padding-top: clamp(1rem, 3vw, 1.8rem); } /* working screens: no hero/heading above */
.section--tint { max-width: none; background: var(--tint); }
.section--tint > * { max-width: var(--wrap); margin-left: auto; margin-right: auto; }
.section__head { margin-bottom: 2.2rem; }
.section__head h2 { font-size: clamp(1.7rem, 5vw, 2.5rem); margin: 0 0 .4rem; letter-spacing: -.01em; }
.section__sub { color: var(--ink-soft); margin: 0; font-size: 1.05rem; }
.sub-h { margin: 2.2rem 0 1rem; font-size: 1.2rem; }
.empty { color: var(--ink-soft); font-size: 1.1rem; }

/* ---------- Weather: horizontal day strip (each day once, grouped by city)
   + current-location "now + next 8 hours". Refreshes on load. ---------- */
.wx-strip { display: flex; gap: .9rem; overflow-x: auto; padding: .2rem .1rem 1rem;
  -webkit-overflow-scrolling: touch; }
.wx-city { flex: 0 0 auto; }
.wx-city__name { font-weight: 700; font-size: .9rem; margin: 0 0 .5rem .15rem; white-space: nowrap; }
.wx-city__here { font-size: .58rem; text-transform: uppercase; letter-spacing: .08em; background: var(--green);
  color: #fff; padding: .1rem .45rem; border-radius: 999px; margin-left: .25rem; }
.wx-city__days { display: flex; gap: .4rem; }
.wx-day { flex: 0 0 auto; width: 3.7rem; background: var(--paper); border: 1px solid var(--line); border-radius: 14px;
  padding: .55rem .3rem; display: flex; flex-direction: column; align-items: center; gap: .18rem; text-align: center; }
.wx-day--today { border-color: var(--lav); box-shadow: 0 0 0 2px rgba(124,92,219,.3); background: var(--tint); }
.wx-day__dow { font-size: .62rem; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft); font-weight: 700; }
.wx-day__dom { font-size: 1.05rem; font-weight: 800; line-height: 1; color: var(--ink); }
.wx-day__icon { font-size: 1.3rem; line-height: 1.2; }
.wx-day__temps { font-size: .7rem; font-variant-numeric: tabular-nums; display: flex; gap: .3rem; }
.wx-day__hi { color: var(--coral); font-weight: 700; }
.wx-day__lo { color: var(--lav-deep); }

.wx-now { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 1rem 1.1rem; margin-top: .2rem; }
.wx-now__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: .5rem; }
.wx-now__place { font-weight: 700; font-size: 1rem; }
.wx-now__temp { font-size: 2rem; font-weight: 800; line-height: 1; }
.wx-now__cond { font-size: .9rem; color: var(--ink-soft); }
.wx-now__obs { font-size: .72rem; color: var(--ink-soft); margin-left: auto; }
.wx-hours { display: flex; gap: .5rem; overflow-x: auto; margin-top: .9rem; padding-bottom: .3rem; -webkit-overflow-scrolling: touch; }
.wx-hour { flex: 0 0 auto; width: 3rem; display: flex; flex-direction: column; align-items: center; gap: .2rem; text-align: center; }
.wx-hour__t { font-size: .68rem; color: var(--ink-soft); font-weight: 600; }
.wx-hour__i { font-size: 1.15rem; line-height: 1.1; }
.wx-hour__d { font-size: .8rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* There is no multi-city strip — the "now" panel always stands alone, so it
   gets the breathing room such a strip would have occupied above it. */
.wx--solo .wx-now { margin-top: 1rem; }
.wx-now__range { display: flex; align-items: baseline; gap: .4rem; margin: .55rem 0 0;
  font-size: .82rem; font-variant-numeric: tabular-nums; }

.wx-status { display: flex; align-items: center; justify-content: center; gap: .6rem; margin-top: 1rem;
  font-size: .8rem; color: var(--ink-soft); }

/* ---------- Cards (events) ---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1.2rem; }
.card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem; box-shadow: var(--shadow); }
.card__kicker { font-size: .72rem; text-transform: uppercase; letter-spacing: .12em; color: var(--lav); font-weight: 700; }
.card h3 { margin: .3rem 0 .3rem; font-size: 1.2rem; }
.card__when { font-weight: 600; color: var(--green-dp); margin: 0 0 .5rem; font-size: .92rem; }
.card p { margin: 0; color: var(--ink-soft); }
.card__link { display: inline-block; margin-top: .6rem; font-weight: 600; text-decoration: none; }

/* ---------- Timeline ---------- */
.timeline { list-style: none; margin: 0; padding: 0; position: relative; }
.timeline::before { content: ""; position: absolute; left: 11px; top: 6px; bottom: 6px; width: 2px; background: linear-gradient(var(--gold), var(--lav)); }
.timeline li { position: relative; padding: 0 0 1.8rem 2.6rem; }
.timeline li::before { content: ""; position: absolute; left: 4px; top: 5px; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 3px solid var(--lav); }
.timeline li.is-current::before { border-color: var(--green); background: var(--green); box-shadow: 0 0 0 4px rgba(47,158,111,.2); }
.t-day { font-size: .78rem; text-transform: uppercase; letter-spacing: .14em; color: var(--lav); font-weight: 700; }
.t-place { font-size: 1.25rem; font-weight: 700; margin: .1rem 0 .2rem; }
.t-region { font-size: .8rem; color: var(--ink-soft); font-weight: 500; margin-left: .4rem; }
.t-note { color: var(--ink-soft); margin: 0 0 .4rem; }
.t-hotel { margin: .2rem 0; font-size: .92rem; }
.t-ideas { margin-top: .4rem; }
.t-ideas summary { cursor: pointer; color: var(--lav-deep); font-weight: 600; font-size: .9rem; }
.t-ideas p { color: var(--ink-soft); font-size: .92rem; margin: .5rem 0 0; }

/* ---------- Food ---------- */
.food-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.6rem; }
.food-col-title { margin: 0 0 .9rem; font-size: 1.15rem; }
.food { list-style: none; margin: 0; padding: 0; display: grid; gap: .8rem; }
.food li { background: var(--paper); border: 1px solid var(--line); border-left: 4px solid var(--green); border-radius: 12px; padding: .9rem 1.1rem; }
.food--tourist li { border-left-color: var(--gold); }
.food b { display: block; font-size: 1.02rem; }
.food span { color: var(--ink-soft); font-size: .92rem; }
.food em { display: block; color: var(--lav); font-style: normal; font-size: .78rem; margin-top: .3rem; text-transform: uppercase; letter-spacing: .06em; }

/* ---------- Posts / gallery / arrivals ---------- */
.post { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem 1.6rem; margin-bottom: 1.2rem; box-shadow: var(--shadow); }
.post__meta { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; font-size: .82rem; color: var(--ink-soft); margin-bottom: .4rem; }
.post__place { background: var(--tint); color: var(--lav-deep); padding: .15rem .6rem; border-radius: 999px; font-weight: 600; }
.post h3 { margin: .1rem 0 .5rem; }
.post__body { margin: 0; }
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: .8rem; margin: 1rem 0; }
.gallery__item { margin: 0; border-radius: 14px; overflow: hidden; background: var(--paper); border: 1px solid var(--line); }
.gallery__item img { width: 100%; height: 180px; object-fit: cover; }
.gallery__item figcaption { padding: .5rem .7rem; font-size: .82rem; color: var(--ink-soft); }
.arrivals { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.arrivals li { display: flex; flex-wrap: wrap; gap: .6rem; align-items: baseline; background: var(--paper); border: 1px solid var(--line); border-radius: 10px; padding: .6rem .9rem; }
.arrivals__when { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--lav-deep); font-size: .9rem; }
.arrivals__place { font-weight: 600; }
.arrivals__note { color: var(--ink-soft); font-style: italic; }
.arrivals__who { margin-left: auto; color: var(--ink-soft); font-size: .85rem; }

/* ---------- Crew ---------- */
.crew { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1rem; }
.crew__member { text-align: center; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.5rem 1rem; }
.crew__avatar { width: 60px; height: 60px; margin: 0 auto .7rem; border-radius: 50%; display: grid; place-items: center; font-size: 1.6rem; color: #fff; background: linear-gradient(150deg, var(--gold), var(--lav)); font-weight: 800; }
.crew__name { font-weight: 700; }
.rsvp { font-size: .85rem; margin-top: .2rem; }
.rsvp--yes { color: var(--green-dp); } .rsvp--no { color: var(--coral); } .rsvp--maybe { color: var(--ink-soft); }

/* ---------- Login ---------- */
.login { display: grid; gap: .9rem; max-width: 340px; margin: 1.5rem auto 1rem; text-align: left; }
.login label { display: grid; gap: .3rem; font-size: .85rem; color: #efe8ff; font-weight: 600; }
.login input { padding: .7rem .9rem; border-radius: 10px; border: 1px solid rgba(255,255,255,.3); background: rgba(255,255,255,.95); font-size: 1rem; }
.login .btn { justify-self: start; }
.login__note { font-size: .85rem; color: #e6ddfa; max-width: 380px; margin: 1rem auto 0; }
.login__note code, .panel__hint code { background: rgba(124,92,219,.14); padding: .1rem .35rem; border-radius: 6px; }

/* ---------- Dashboard ---------- */
.dash { max-width: var(--wrap); margin: 0 auto; padding: clamp(2rem, 6vw, 3.5rem) clamp(1.2rem, 5vw, 2.5rem); }
.dash__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.8rem; }
.dash__head h1 { margin: 0 0 .2rem; }
.dash__head .btn { color: var(--lav-deep); background: var(--tint); box-shadow: none; }
.tag { background: var(--lav); color: #fff; font-size: .7rem; padding: .12rem .5rem; border-radius: 999px; text-transform: uppercase; letter-spacing: .08em; vertical-align: middle; }
.tag--user { background: var(--green); }
.dash__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 1.2rem; }
/* Grid items default to min-width:auto and refuse to shrink below their
   content — which lets a wide child push the whole column past the viewport.
   Letting them shrink keeps every panel inside the screen on mobile. */
.dash__grid > * { min-width: 0; }
.panel { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem 1.5rem; box-shadow: var(--shadow); }
.panel--wide { grid-column: 1 / -1; }
.panel h2 { margin: 0 0 .3rem; font-size: 1.15rem; }
.panel__hint { color: var(--ink-soft); font-size: .85rem; margin: 0 0 .9rem; }
.panel form { display: grid; gap: .7rem; }
.panel label { display: grid; gap: .3rem; font-size: .82rem; font-weight: 600; color: var(--ink-soft); }
.panel input, .panel select, .panel textarea { padding: .6rem .75rem; border: 1px solid var(--line); border-radius: 10px; font-size: 1rem; font-family: inherit; background: var(--cream); }
.panel .btn { justify-self: start; box-shadow: none; background: var(--lav); color: #fff; }
.muted { font-weight: 400; color: #9a92ad; }
/* display:block + own scrollbar: a wide table scrolls inside itself instead
   of stretching the page past narrow phone screens. */
.tbl { width: 100%; border-collapse: collapse; font-size: .9rem; display: block; overflow-x: auto; }
.tbl th, .tbl td { text-align: left; padding: .5rem .5rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tbl th { font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); }
.inline { display: flex; gap: .4rem; align-items: center; }
.inline input { padding: .35rem .5rem; border: 1px solid var(--line); border-radius: 8px; }
.row-form { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.row-form input, .row-form select { padding: .55rem .7rem; border: 1px solid var(--line); border-radius: 10px; font: inherit; }

/* Form controls never inherit page color — set it, or dark mode goes dark-on-dark. */
input, select, textarea { color: var(--ink); caret-color: var(--ink); }
.login input { color: #241f2e; caret-color: #241f2e; } /* white box in both themes */

/* ---------- Responsive ---------- */
@media (max-width: 640px) {
  .food-cols { grid-template-columns: 1fr; }
  .dash__grid { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .livechip__dot { animation: none; } }


/* ---------- Section tabs (top banner + bottom of page) ---------- */
.tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: .45rem; }
.tab { display: inline-block; background: var(--paper); border: 1px solid var(--line); color: var(--lav-deep);
       text-decoration: none; font-weight: 600; font-size: .9rem; padding: .45rem 1.05rem; border-radius: 999px;
       transition: border-color .15s, background .15s; }
a.tab:hover { border-color: var(--lav); }
.tab.is-active { background: var(--lav); border-color: var(--lav); color: #fff; }

/* ---------- Map (trip route / day check-ins) ---------- */
.map-toggle { display: flex; justify-content: center; gap: .5rem; margin-bottom: 1.1rem; }
.map-toggle__btn { font: inherit; font-weight: 600; font-size: .9rem; padding: .45rem 1.3rem; border-radius: 999px;
                   border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); cursor: pointer; }
.map-toggle__btn.is-active { background: var(--lav); border-color: var(--lav); color: #fff; }
.map-days { display: none; justify-content: center; flex-wrap: wrap; gap: .4rem; margin-bottom: 1.1rem; }
.map-days.is-open { display: flex; }
.map-day-btn { font: inherit; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: .05rem;
               background: var(--paper); border: 1px solid var(--line); border-radius: 10px; padding: .35rem .6rem; min-width: 3.2rem; }
.map-day-btn__d { font-weight: 700; font-size: .95rem; color: var(--ink); }
.map-day-btn__p { font-size: .62rem; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-soft); font-weight: 600; }
.map-day-btn.is-active { border-color: var(--lav); background: var(--tint); box-shadow: 0 0 0 1px var(--lav); }
a.map-day-btn { text-decoration: none; }
.map-day-btn--edge .map-day-btn__d { font-size: .82rem; }

/* ---------- Entry feed (trip diary + personal diaries) ---------- */
.feed { display: grid; gap: 1rem; }
.feed-item { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
             padding: 1rem 1.2rem; box-shadow: var(--shadow); }
.feed-item--summary { background: var(--tint); border-color: var(--lav); box-shadow: none; }
/* Arrived here from a map dot / "Where we've been" link — make it obvious
   which post was meant. */
.feed-item:target { border-color: var(--lav); box-shadow: 0 0 0 3px rgba(124, 92, 219, .28); scroll-margin-top: 5rem; }
.feed-item__meta { font-size: .78rem; color: var(--ink-soft); margin: 0 0 .35rem; text-transform: none; }
.feed-item__title { margin: 0 0 .3rem; font-size: 1.1rem; }
.feed-item__body { margin: 0; white-space: normal; }
/* Post text sitting above its photo/album — needs a gap the plain body doesn't. */
.feed-item__body--above { margin-bottom: .55rem; }
.feed-item__caption { margin: .4rem 0 0; font-size: .82rem; color: var(--ink-soft); }
.feed-item img, .feed-item video { max-width: 100%; border-radius: 10px; display: block; }
/* Multi-photo album (one post, several photos, tap to open the full set) */
.album { display: grid; gap: 4px; border-radius: 12px; overflow: hidden; margin-top: .2rem; }
.album__cell { position: relative; margin: 0; padding: 0; border: none; cursor: pointer; overflow: hidden; background: var(--tint); }
.album__cell img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; }
.album--n2 { grid-template-columns: 1fr 1fr; aspect-ratio: 2 / 1; }
.album--n3 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; aspect-ratio: 3 / 2; }
.album--n3 .album__cell:first-child { grid-row: span 2; }
.album--grid { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; aspect-ratio: 1 / 1; }
.album__more { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.5); color: #fff; font-weight: 800; font-size: 1.5rem; }
/* Fullscreen lightbox */
.lightbox { position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,.92);
  display: flex; align-items: center; justify-content: center; }
.lightbox[hidden] { display: none; }
.lightbox img { max-width: 94vw; max-height: 86vh; object-fit: contain; border-radius: 6px;
  touch-action: none; transform-origin: center center; cursor: grab; }
.album__cell { cursor: zoom-in; }
img.feed-photo { cursor: zoom-in; }
.lightbox__btn { position: absolute; background: rgba(255,255,255,.16); color: #fff; border: none; cursor: pointer;
  width: 3rem; height: 3rem; border-radius: 999px; display: flex; align-items: center; justify-content: center; font-size: 2rem; line-height: 1; }
.lightbox__btn:hover { background: rgba(255,255,255,.28); }
.lightbox__prev { left: 1rem; top: 50%; transform: translateY(-50%); }
.lightbox__next { right: 1rem; top: 50%; transform: translateY(-50%); }
.lightbox__close { top: 1rem; right: 1rem; font-size: 1.4rem; }
.lightbox__save { top: 1rem; left: 1rem; font-size: 1.5rem; text-decoration: none; }
.lightbox__save[hidden] { display: none; }   /* class sets display:flex — [hidden] must win */
/* Reads as a control, not a stray number, so "there is more than one photo
   here" lands before you go hunting for arrows. */
.lightbox__count { position: absolute; bottom: 1rem; left: 50%; transform: translateX(-50%);
  color: #fff; font-size: .82rem; font-weight: 600; letter-spacing: .04em;
  background: rgba(255,255,255,.16); padding: .25rem .7rem; border-radius: 999px;
  backdrop-filter: blur(6px); }
/* 💬 caption toggle — a small semitransparent disc, deliberately quieter than
   the ✕ / ⤓ controls: it's an option, not an exit. */
.lightbox__cc { position: absolute; bottom: 1rem; right: 1rem; width: 2.4rem; height: 2.4rem;
  border: none; border-radius: 999px; cursor: pointer; font-size: 1.05rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.16); color: #fff; backdrop-filter: blur(6px); }
.lightbox__cc[hidden] { display: none; }      /* class sets display:flex — [hidden] must win */
.lightbox__cc.is-on { background: rgba(124,92,219,.85); }
.lightbox__cap { position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 4.2rem; max-width: min(90vw, 44rem); margin: 0; padding: .55rem .9rem;
  border-radius: 12px; background: rgba(0,0,0,.62); color: #fff;
  font-size: .92rem; line-height: 1.45; text-align: center; backdrop-filter: blur(6px); }
.lightbox__cap[hidden] { display: none; }
/* Shown while the next photo decodes. Dead centre, because the frame behind
   it is deliberately blank — see setImg() in app.js for why a blank frame
   beats leaving the previous photo up. [hidden] must win over the display
   here, as everywhere else in this file. */
.lightbox__wait { position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%); margin: 0; padding: .55rem .9rem;
  border-radius: 12px; background: rgba(0,0,0,.62); color: #fff;
  font-size: .95rem; text-align: center; backdrop-filter: blur(6px); }
.lightbox__wait[hidden] { display: none; }
/* Idle on a mouse-driven screen: the chrome steps out of the picture's way.
   Never applied on touch (no mousemove to bring it back — see app.js), and
   never to the caption itself, which is the thing you asked to read. */
.lightbox.is-idle .lightbox__btn,
.lightbox.is-idle .lightbox__cc,
.lightbox.is-idle .lightbox__count { opacity: 0; pointer-events: none; }
.lightbox__btn, .lightbox__cc, .lightbox__count { transition: opacity .35s ease; }
/* One photo: nothing to page through. */
.lightbox--solo .lightbox__prev,
.lightbox--solo .lightbox__next,
.lightbox--solo .lightbox__count { display: none; }
/* On touch, swiping is the primary gesture — the arrows step back to being a
   fallback rather than the thing you have to hunt for. */
@media (hover: none) {
  .lightbox__prev, .lightbox__next { width: 2.5rem; height: 2.5rem; font-size: 1.6rem;
    background: rgba(255,255,255,.10); }
  .lightbox__prev { left: .35rem; }
  .lightbox__next { right: .35rem; }
}
/* ---------- Reactions + comments under diary posts ----------
   The kaomoji row sits on its own line; the thread and the comment box break
   onto a full-width row underneath. Nothing is hidden behind a badge. */
.cmts { margin-top: .6rem; display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }
.cmts__box { flex: 0 0 100%; margin-top: .5rem; display: grid; gap: .5rem; }

/* Kaomoji chips (顔文字) — tap to toggle. Faces are CJK glyphs, so they get the
   Japanese face stack; nothing here goes below 12px on a real phone. */
.rxn { display: flex; flex-wrap: wrap; gap: .3rem; margin: 0; }
.rxn__chip { display: inline-flex; align-items: center; gap: .3rem; cursor: pointer;
  background: var(--paper); border: 1px solid var(--line); border-radius: 999px;
  padding: .2rem .55rem; color: var(--ink); font: inherit; line-height: 1.4;
  white-space: nowrap; transition: background .15s, border-color .15s; }
.rxn__chip:disabled { cursor: default; opacity: .55; }
.rxn__chip.is-on { background: var(--tint); border-color: var(--lav); }
.rxn__face { font-family: 'Zen Kaku Gothic New', 'Hiragino Sans', 'Noto Sans JP', sans-serif;
  font-size: .82rem; letter-spacing: -.02em; }
/* The plain emoji beside the face — same meaning, read instantly. Pinned to
   the colour-emoji stack so it never falls back to a mono outline glyph. */
.rxn__icon { font-size: .9rem; line-height: 1;
  font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif; }
/* Nobody has tapped this one yet: emoji only, so an untouched post reads as a
   quiet row of four offers rather than four empty scoreboards. The kaomoji and
   the count arrive together the moment the count does. */
.rxn__chip--bare { padding: .25rem .55rem; }
.rxn__chip--bare .rxn__face { display: none; }
.rxn__chip--bare .rxn__icon { font-size: 1.05rem; }
/* A collapsed chip is small — on a thumb it still needs a real target. */
@media (hover: none) {
  .rxn__chip { min-height: 2.1rem; padding-left: .65rem; padding-right: .65rem; }
  .rxn__chip--bare .rxn__icon { font-size: 1.15rem; }
}
.rxn__n { font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--lav-deep); }
.rxn__n:empty { display: none; }
/* A tap should feel like something happened — and a failed one should not
   look like "your tap just didn't count". */
.rxn__chip--pop { animation: rxn-pop .3s ease; }
.rxn__chip--err { border-color: var(--coral); animation: rxn-shake .3s ease; }
@keyframes rxn-shake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-3px); }
  75%      { transform: translateX(3px); }
}
@keyframes rxn-pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.16); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .rxn__chip--pop, .rxn__chip--err { animation: none; }
}
.cmt { border-top: 1px solid var(--line); padding-top: .5rem; }
.cmt:target { background: var(--tint); border-radius: 8px; padding: .5rem; scroll-margin-top: 5rem; }
/* One flowing line per comment — everything inline, soft-wrapping only. */
.cmt__line { margin: 0; font-size: .92rem; overflow-wrap: anywhere; }
.cmt__when { color: var(--ink-soft); font-size: .75rem; }
.cmt__tag { font-size: .62rem; text-transform: uppercase; letter-spacing: .06em;
  background: var(--lav); color: #fff; padding: .05rem .4rem; border-radius: 999px; }
.cmt__del { display: inline; }
.cmt__del button { background: none; border: none; color: var(--ink-soft); cursor: pointer;
  font-size: .72rem; padding: 0 .15rem; vertical-align: baseline; }
/* Comments listed under a post on the Write page (where deleting lives). */
.wcmts { margin-top: .5rem; padding: .45rem .65rem; background: var(--tint); border-radius: 10px; display: grid; gap: .3rem; }
.wcmts .cmt__line { font-size: .85rem; }
/* Collapsed the form is one line — just the textarea. Tapping it opens the
   rest (app.js adds .is-open); it also opens on load when the browser has
   restored text into it, so a back-navigation never hides half a comment. */
.cmt-form { display: grid; gap: .4rem; margin-top: .2rem; }
/* font: inherit keeps these at 16px — anything smaller makes Android zoom
   the page in on focus (and the zoom sticks after the post reload). */
.cmt-form textarea { height: 2.5rem; min-height: 2.5rem; resize: none; overflow: hidden;
  font: inherit; line-height: 1.4;
  padding: .5rem .65rem; border: 1px solid var(--line); border-radius: 999px;
  background: var(--cream); color: var(--ink); transition: border-radius .15s; }
.cmt-form.is-open textarea { min-height: 4.2rem; resize: vertical; border-radius: 12px; }
.cmt-form__more { display: none; gap: .4rem; align-items: center; justify-content: flex-end; }
.cmt-form.is-open .cmt-form__more { display: flex; }
.cmt-form__name { flex: 1 1 auto; max-width: 14rem; font: inherit;
  padding: .5rem .65rem; border: 1px solid var(--line); border-radius: 10px; background: var(--cream); color: var(--ink); }
.cmt-form__off { font-size: .8rem; color: var(--ink-soft); margin: 0; }

/* The composer's batch-preview cards (.tw-batch*) are gone: a pick is one
   post now, so there are no per-batch caption boxes to style. The split is
   a single opt-in toggle inside .tw-meta__panel below. */
.trip-map { height: clamp(320px, 55vh, 540px); border-radius: var(--radius); border: 1px solid var(--line);
            box-shadow: var(--shadow); position: relative; z-index: 0; }
.map-dot { display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%;
           background: #c62828; color: #fff; font-weight: 700; font-size: .8rem; border: 2px solid #fff;
           box-shadow: 0 1px 5px rgba(0,0,0,.45); }
.map-dot--current { background: var(--green); }
.map-dot--future { background: #fff; color: #c62828; border-color: #c62828; }
.map-hint { display: none; font-size: .8rem; color: var(--ink-soft); text-align: center; margin: .5rem 0 0; }
@media (pointer: coarse) { .map-hint { display: block; } }
/* Recorded-track legend (companion-app drives/walks) */
.map-tracklegend { font-size: .8rem; color: var(--ink-soft); text-align: center; margin: .5rem 0 0; }
.map-tracklegend__drive, .map-tracklegend__walk { display: inline-block; width: 26px; height: 0; vertical-align: middle; border-top: 3px solid #4f46a0; opacity: .75; }
.map-tracklegend__walk { border-top-style: dashed; border-top-color: #2e7d4f; }
.map-legend { margin-top: 1.2rem; }
.map-legend__list { margin: 0 0 .9rem; padding-left: 1.5rem; }
.map-legend__list li { margin: .3rem 0; }
/* "Where we've been" — chronological pin log under the map (all modes) */
.map-visits { margin-top: 1.4rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.map-visits__h { font-size: .95rem; margin: 0 0 .7rem; }
.map-visits__list { list-style: none; margin: 0; padding: 0; display: grid; gap: .1rem; }
.map-visits__item { display: flex; align-items: baseline; gap: .6rem; padding: .45rem 0; border-bottom: 1px dashed var(--line); }
.map-visits__item[hidden] { display: none; } /* .map-visits__item's own display:flex would otherwise beat the UA [hidden] rule */
.map-visits__when { flex: 0 0 auto; width: 5.2rem; font-size: .78rem; font-weight: 700; color: var(--lav-deep); }
.map-visits__what { flex: 1 1 auto; min-width: 0; font-size: .9rem; }
.map-visits__go { flex: 0 0 auto; text-decoration: none; font-weight: 700; color: var(--lav-deep); }
/* Popup on a geo dot: tap through to the post it came from. */
.map-pop { font-size: .85rem; font-weight: 600; color: var(--lav-deep); }
/* Diary mode switch: two compact buttons — Blog / By date (date opens a picker) */
.diary-modes { display: flex; gap: .5rem; justify-content: center; margin-bottom: 1.3rem; }
.diary-mode { display: inline-flex; align-items: center; gap: .35rem; font: inherit; font-weight: 700; font-size: .9rem;
  padding: .5rem 1.1rem; border-radius: 999px; border: 1px solid var(--line); background: var(--paper);
  color: var(--ink-soft); cursor: pointer; text-decoration: none; white-space: nowrap; }
.diary-mode.is-active { background: var(--lav); border-color: var(--lav); color: #fff; }
.diary-picker { position: relative; }
.diary-picker > summary { list-style: none; }
.diary-picker > summary::-webkit-details-marker { display: none; }
.diary-picker__panel { position: absolute; z-index: 20; top: calc(100% + .4rem); left: 50%; transform: translateX(-50%);
  background: var(--paper); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow);
  padding: .4rem; width: max-content; max-width: 82vw; max-height: 58vh; overflow-y: auto; display: grid; gap: .1rem; }
.diary-picker__day { display: block; text-decoration: none; color: var(--ink); font-size: .88rem; font-weight: 600;
  padding: .5rem .8rem; border-radius: 8px; white-space: nowrap; }
.diary-picker__day:hover { background: var(--tint); }
.diary-picker__day.is-active { background: var(--lav); color: #fff; }

/* ---------- Ask (chat interface) ---------- */
.chat { display: flex; flex-direction: column; min-height: calc(100dvh - 12rem); }
.chat__notice { background: var(--amber-tint); color: var(--amber); border-radius: 12px;
                padding: .6rem .9rem; margin: 0 0 .6rem; font-size: .9rem; }
.chat-feed { flex: 1 1 auto; display: flex; flex-direction: column; gap: .55rem;
             padding: .4rem 0 1rem; justify-content: flex-end; }
.chat-empty { margin: auto; text-align: center; color: var(--ink-soft); max-width: 22rem; }
.chat-empty__big { font-size: 2.6rem; margin: 0 0 .4rem; }
.msg { display: flex; flex-direction: column; max-width: 82%; }
.msg--you { align-self: flex-end; align-items: flex-end; }
.msg--guide { align-self: flex-start; align-items: flex-start; }
.msg__bubble { padding: .6rem .85rem; border-radius: 16px; line-height: 1.5; word-wrap: break-word; }
.msg--guide .msg__bubble { background: var(--paper); border: 1px solid var(--line); border-bottom-left-radius: 5px; }
.msg--you .msg__bubble { background: var(--lav); color: #fff; border-bottom-right-radius: 5px; }
.msg__img { max-width: min(260px, 80%); border-radius: 14px; display: block; margin-bottom: .35rem; }
.msg__meta { font-size: .7rem; color: var(--ink-soft); margin: .18rem .2rem 0; }

.askbar { position: sticky; bottom: calc(4.2rem + env(safe-area-inset-bottom));
          margin-top: .3rem; background: var(--cream); padding-top: .5rem; }
.askbar__tray { display: flex; gap: .5rem; margin-bottom: .5rem; }
.askbar__opt { font: inherit; font-weight: 600; font-size: .88rem; cursor: pointer;
               background: var(--paper); border: 1px solid var(--line); color: var(--ink);
               border-radius: 999px; padding: .45rem .9rem; }
.askbar__opt:hover { border-color: var(--lav); color: var(--lav-deep); }
.askbar__chips { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .5rem; }
.askbar__chip { display: inline-flex; align-items: center; gap: .4rem; font-size: .8rem; font-weight: 600;
                background: var(--tint); color: var(--lav-deep); border-radius: 999px; padding: .3rem .35rem .3rem .7rem; }
.askbar__chip button { border: none; background: rgba(0,0,0,.08); color: inherit; cursor: pointer;
                       width: 1.2rem; height: 1.2rem; border-radius: 999px; line-height: 1; font-size: .85rem; }
.askbar__bar { display: flex; align-items: flex-end; gap: .4rem;
               background: var(--paper); border: 1px solid var(--line); border-radius: 24px;
               padding: .35rem .4rem; box-shadow: var(--shadow); }
.askbar__plus { flex: 0 0 auto; width: 2.3rem; height: 2.3rem; border-radius: 999px; cursor: pointer;
                border: none; background: var(--tint); color: var(--lav-deep); font-size: 1.3rem; line-height: 1;
                display: flex; align-items: center; justify-content: center; transition: transform .15s; }
.askbar__plus[aria-expanded="true"] { transform: rotate(45deg); background: var(--lav); color: #fff; }
.askbar__input { flex: 1 1 auto; border: none; background: transparent; font: inherit; color: var(--ink);
                 resize: none; max-height: 40vh; padding: .5rem .2rem; line-height: 1.4; }
.askbar__input:focus { outline: none; }
.askbar__reset { flex: 0 0 auto; width: 2.3rem; height: 2.3rem; border-radius: 999px; cursor: pointer;
                 border: none; background: transparent; color: var(--ink-soft); font-size: 1.2rem; line-height: 1; }
.askbar__reset:hover { background: var(--tint); color: var(--coral); }
.askbar__send { flex: 0 0 auto; border: none; cursor: pointer; font: inherit; font-weight: 700;
                background: var(--lav); color: #fff; border-radius: 999px; padding: .6rem 1.2rem; }
.askbar__send:hover { background: var(--lav-deep); }
.askbar__send:disabled { opacity: .5; cursor: not-allowed; }

/* ---------- Write page — Twitter-style composer ---------- */
.dash--write { max-width: 640px; }
.tw { background: var(--paper); border: 1px solid var(--line); border-radius: 18px;
  padding: 1rem 1.1rem; box-shadow: var(--shadow); margin-bottom: 1.6rem; }
.tw__top { display: flex; gap: .8rem; align-items: flex-start; }
.tw__avatar { flex: 0 0 auto; width: 2.6rem; height: 2.6rem; border-radius: 999px;
  background: linear-gradient(135deg, var(--lav), var(--lav-deep)); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 1.1rem; }
.tw__text { flex: 1 1 auto; min-width: 0; border: none; background: transparent; resize: none;
  font: inherit; font-size: 1.25rem; line-height: 1.45; color: var(--ink); padding: .35rem 0; max-height: 50vh; }
.tw__text::placeholder { color: var(--ink-soft); opacity: .7; }
.tw__text:focus { outline: none; }
.tw__indent { margin-left: 3.4rem; }
.tw__previews { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
  gap: .5rem; margin: .6rem 0 0 3.4rem; }
.tw__thumb { position: relative; }
.tw__thumb img, .tw__thumb video { width: 100%; height: 88px; object-fit: cover; border-radius: 12px; display: block; }

/* A LONE attachment gets the whole width. There's no grid to keep tidy with
   one photo, and you're looking at it to decide whether it's the right shot —
   an 88px crop can't answer that. `contain` not `cover`: this is a preview of
   what you're posting, so it must not crop the frame. max-height keeps a tall
   portrait shot from pushing Post off the screen. */
.tw__previews.is-one { grid-template-columns: 1fr; }
.tw__previews.is-one .tw__thumb img,
.tw__previews.is-one .tw__thumb video {
  height: auto; max-height: 62vh; object-fit: contain; background: var(--tint); }
/* The badges get a size to match — at 88px they had to be tiny; here they
   were left looking like specks in a corner. */
.tw__previews.is-one .tw__thumb button { width: 2rem; height: 2rem; font-size: 1rem; }
.tw__previews.is-one .tw__thumb .tw__exif { font-size: .85rem; padding: .2rem .45rem; }
.tw__previews.is-one .tw__thumb .tw__cc,
.tw__previews.is-one .tw__thumb .tw__ai { font-size: .95rem; padding: .3rem .5rem; width: auto; height: auto; }
.tw__thumb button { position: absolute; top: .25rem; right: .25rem; width: 1.5rem; height: 1.5rem;
  border-radius: 999px; border: none; background: rgba(0,0,0,.6); color: #fff; cursor: pointer; font-size: .8rem; line-height: 1; }
/* Per-photo EXIF badge + the batch summary under the previews. A photo with
   no location of its own can never get one back downstream, so the composer
   says which ones are carrying it while there's still time to re-pick. */
.tw__thumb .tw__exif { position: absolute; left: .25rem; bottom: .25rem;
  min-width: 1.15rem; padding: .1rem .25rem; border-radius: 999px;
  font-size: .7rem; line-height: 1.25; text-align: center;
  background: rgba(0,0,0,.55); color: #fff; }
.tw__thumb .tw__exif.is-on { background: rgba(23,110,60,.82); }
/* Whether these photos know where they were, in one line, with the fix beside
   it. Amber when something is unlocated — it's a warning, not an error: a post
   with no pin is allowed, it just won't appear on the map. */
.tw__loc { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
  margin: .25rem 0 0; font-size: .8rem; font-weight: 600; color: #8a5a12; }
.tw__loc.is-ok { color: var(--ink-soft); font-weight: 400; }
/* The fix is pointed at, not duplicated: when a pick has no location the
   EXISTING 📍/🗺 buttons pulse once and stay outlined (.is-wanted). Growing a
   second pair beside the warning cost a row of screen and implied there were
   two different location controls. */
.tw__opt.is-wanted { border-color: var(--amber, #b8860b); color: #8a5a12; background: var(--amber-tint, #fdf3dd); }
html[data-theme="dark"] .tw__opt.is-wanted { color: #e0b25f; background: rgba(224,178,95,.12); }
.tw__opt.just-asked { animation: locpulse .55s ease-out 2; }
@keyframes locpulse {
  0%   { box-shadow: 0 0 0 0 rgba(184,134,11,.55); }
  70%  { box-shadow: 0 0 0 .45rem rgba(184,134,11,0); }
  100% { box-shadow: 0 0 0 0 rgba(184,134,11,0); }
}
/* A pulsing control is exactly what motion sensitivity flags; the outline
   still carries the whole message without it. */
@media (prefers-reduced-motion: reduce) { .tw__opt.just-asked { animation: none; } }
html[data-theme="dark"] .tw__loc { color: #e0b25f; }

/* 💬 per-photo caption button. Shares the ✕ button rule above, so it only
   needs to move itself out of the top-right corner; is-on marks a photo that
   already has a caption, so you can see at a glance which ones you've done. */
.tw__thumb .tw__cc { top: auto; right: .25rem; bottom: .25rem; font-size: .72rem; }
.tw__thumb .tw__cc.is-on { background: var(--lav); }
/* ✨ sits beside 💬 — same affordance, writes the caption instead of asking
   you to. Shares .tw__cc's geometry so the two read as a pair. */
.tw__thumb .tw__ai { position: absolute; top: auto; left: .25rem; bottom: .25rem; font-size: .72rem;
  border: none; border-radius: 999px; cursor: pointer; line-height: 1; padding: .2rem .35rem;
  background: rgba(255,255,255,.85); color: var(--lav-deep); }

/* Offered when nothing in the pick knows where it was. An offer: a post with
   no pin is fine, and a location invented to fill the gap would be worse. */

/* The caption strip: one editor reused for every photo, rather than an input
   per thumbnail (unusable at 88px on a phone). */
.tw-cap { display: flex; gap: .6rem; align-items: flex-start; margin: .5rem 0;
  padding: .6rem; border: 1px solid var(--line); border-radius: 14px; background: var(--cream); }
/* The strip opens on demand (💬 / ✨) and is `hidden` the rest of the time —
   but the rule above sets its own display, which beats the UA [hidden] rule.
   Without this line the empty strip renders on every page load whether or
   not a photo is attached, which is exactly how it was reported. */
.tw-cap[hidden] { display: none; }
.tw-cap__thumb { width: 68px; height: 68px; object-fit: cover; border-radius: 10px; flex: 0 0 auto; }
.tw-cap__main { flex: 1 1 auto; min-width: 0; }
.tw-cap__who { display: flex; justify-content: space-between; align-items: center; gap: .5rem;
  margin: 0 0 .3rem; font-size: .78rem; font-weight: 600; color: var(--ink-soft); }
.tw-cap__x { border: none; background: none; color: var(--ink-soft); cursor: pointer; font-size: 1rem; line-height: 1; padding: .1rem .2rem; }
.tw-cap__in { width: 100%; }
.tw-cap__nav { display: flex; gap: 1rem; margin: .35rem 0 0; }

/* ✨ describe + the tone chips, inside the caption strip. */
.tw-cap__ai { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: .45rem 0 0; }
.tw-cap__ai-go { font: inherit; font-size: .82rem; font-weight: 700; cursor: pointer;
  background: var(--tint); color: var(--lav-deep); border: none; border-radius: 999px; padding: .35rem .8rem; }
.tw-cap__ai-go:disabled { opacity: .5; cursor: progress; }
.tw-tones { display: flex; flex-wrap: wrap; gap: .25rem; }
.tw-tones button { font: inherit; font-size: .74rem; font-weight: 600; cursor: pointer;
  background: none; color: var(--ink-soft); border: 1px solid var(--line);
  border-radius: 999px; padding: .22rem .55rem; }
.tw-tones button.is-on { background: var(--lav); border-color: var(--lav); color: #fff; }

/* ✨ Describe the album / caption each photo — sits under the thumbnails. */
.tw-aiall { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem;
  margin: .5rem 0 0 3.4rem; font-size: .85rem; }
.tw-aiall[hidden] { display: none; }   /* class display must not beat [hidden] */
.tw-aiall button[hidden] { display: none; }

/* The post's own line: when it's dated, how many files, one post or several.
   A summary that opens a panel — both controls in it are corrections, not
   decisions you have to make before posting. */
.tw-meta { margin: .5rem 0 0 3.4rem; }
.tw-meta[hidden] { display: none; }
.tw-meta__row { display: flex; flex-wrap: wrap; gap: .4rem; }
/* Small pills, not a status bar. Same shape as the location line's fixes so
   every optional control in the composer reads the same way. */
.tw-meta__btn { display: inline-flex; align-items: center; gap: .3rem; cursor: pointer;
  font: inherit; font-size: .95rem; line-height: 1; color: var(--ink-soft);
  background: var(--cream); border: 1px solid var(--line); border-radius: 999px;
  padding: .28rem .6rem; }
.tw-meta__btn span { font-size: .75rem; font-weight: 600; }
.tw-meta__btn:hover { border-color: var(--lav); color: var(--lav-deep); }
.tw-meta__btn[hidden] { display: none; }   /* inline-flex must not beat [hidden] */
.tw-meta__btn.is-on { background: var(--tint); border-color: var(--lav); color: var(--lav-deep); }
.tw-meta__panel { display: grid; gap: .6rem; margin-top: .5rem; padding: .7rem .8rem;
  border: 1px solid var(--line); border-radius: 14px; background: var(--cream); }
.tw-meta__panel[hidden] { display: none; }   /* class display must not beat [hidden] */
.tw-meta__panel > label { display: block; font-size: .8rem; font-weight: 600; color: var(--ink-soft); }
.tw-meta__panel > label input[type="datetime-local"] { width: 100%; margin-top: .2rem; font-weight: 400; }
.tw-meta__split { display: flex; align-items: flex-start; gap: .5rem; cursor: pointer; }
.tw-meta__split[hidden] { display: none; }   /* class display must not beat [hidden] */
.tw-meta__split input { width: 1.1rem; height: 1.1rem; flex: 0 0 auto; margin-top: .15rem; }
.tw-meta__split em { display: block; font-style: normal; font-weight: 400; font-size: .76rem; }

/* "12 photos" next to an album's date — says it's a set before you tap in. */
.feed-item__n { color: var(--ink-soft); font-weight: 600; }

.tw__chips { margin: .6rem 0 0 3.4rem; }
.tw__chip { display: inline-flex; align-items: center; gap: .4rem; background: var(--tint); color: var(--lav-deep);
  border-radius: 999px; padding: .3rem .35rem .3rem .8rem; font-size: .82rem; font-weight: 600; }
.tw__chip button { border: none; background: rgba(0,0,0,.08); color: inherit; cursor: pointer;
  width: 1.2rem; height: 1.2rem; border-radius: 999px; line-height: 1; font-size: .85rem; }

/* Video upload hint. A panel that hardcodes a near-white background MUST also
   own its text colour and carry a dark-theme override — otherwise dark mode
   leaves it painting the theme's near-white ink onto its own near-white panel,
   and the whole hint (tips included) reads as white on white. */
.vid-hint { font-size: .85rem; background: #f4f1fa; color: var(--ink); border: 1px solid #d9d2ec; border-radius: 10px; padding: .6rem .8rem; margin: .5rem 0; }
.vid-hint summary { cursor: pointer; color: #4f46a0; }
html[data-theme="dark"] .vid-hint { background: var(--tint); border-color: var(--line); }
html[data-theme="dark"] .vid-hint summary { color: #b9a6f5; }

/* Location picker (composer + edit forms) */
.locpick { margin-top: .5rem; }
.locpick__q { width: 100%; }
.locpick__results { display: flex; flex-direction: column; gap: 4px; margin-top: .35rem; }
.locpick__row { display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding: .5rem .65rem; border: 1px solid var(--line); border-radius: 10px;
  background: var(--paper); cursor: pointer; text-align: left; font: inherit; color: inherit; }
.locpick__row:hover, .locpick__row:focus-visible { border-color: var(--lav); }
.locpick__name { font-weight: 600; }
.locpick__addr, .locpick__note { font-size: .85em; color: var(--ink-soft); }
.locpick__cur { font-size: .9em; color: var(--ink-soft); display: flex; align-items: center; gap: .5rem; }

/* Admin's ✎ edit disclosure under a diary post (mirrors .entry details) */
.feed-edit { margin-top: .5rem; }
.feed-edit summary { cursor: pointer; font-size: .85rem; color: var(--ink-soft); }
.feed-edit form { display: grid; gap: .6rem; margin-top: .6rem; }
.feed-edit label { display: grid; gap: .25rem; font-size: .8rem; font-weight: 600; color: var(--ink-soft); }
/* The four attach buttons, always on screen (they used to hide behind a ＋,
   which cost two taps per attach).

   ICON-ONLY IS THE DEFAULT, not the fallback. Four labelled buttons do not
   fit across a phone — forcing them made every one ellipsize to "Phot…",
   which is worse than no label at all. So the icon carries the button until
   there is genuine room, and .tw__opt keeps an aria-label in the markup so
   hiding the span never hides the accessible name. */
.tw__tray { display: grid; grid-template-columns: repeat(4, 1fr); gap: .4rem; margin: .7rem 0 0 3.4rem; }
.tw__previews[hidden] { display: none; }   /* class display must not beat [hidden] */
.tw__opt { display: flex; align-items: center; justify-content: center; gap: .35rem;
  font: inherit; font-weight: 600; font-size: 1.15rem; line-height: 1; cursor: pointer;
  background: var(--paper); border: 1px solid var(--line); color: var(--ink);
  border-radius: 999px; padding: .6rem .3rem; white-space: nowrap; }
.tw__opt span { display: none; }
.tw__opt:hover { border-color: var(--lav); color: var(--lav-deep); }
/* Lit while that source is what's attached — the row says what the post
   carries, so the chip below is confirmation rather than the only signal. */
.tw__opt.is-on { background: var(--tint); border-color: var(--lav); color: var(--lav-deep); }
/* Room for words: above every phone in portrait (360–430 CSS px), so those
   stay icon-only as asked.

   The equal-width grid is dropped here on purpose. Forcing four labelled
   buttons into four equal columns is what truncated them in the first
   place, and any fixed breakpoint is a guess about font metrics I can't
   measure. Flex-wrap instead: each button takes exactly the width its own
   label needs, and if they ever don't fit — bigger text, a longer label, a
   narrow window — they wrap to a second row instead of clipping. */
@media (min-width: 500px) {
  .tw__tray { display: flex; flex-wrap: wrap; }
  .tw__opt { font-size: .88rem; padding: .5rem .95rem; }
  .tw__opt span { display: inline; }
  /* The 📍/🗺 fixes on the location line follow the same rule — one
     breakpoint for the whole composer, so the two rows never disagree
     about whether this is a phone. */
  .tw__loc-fix { font-size: .78rem; padding: .22rem .7rem; }
  .tw__loc-fix span { display: inline; }
}
@media (max-width: 380px) { .tw__tray { margin-left: 0; } }
.tw__bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .9rem; padding-top: .8rem; border-top: 1px solid var(--line); }
/* Twitter's send: a filled pill, right-aligned, dead until there's something
   to post. Font stays ≥16px — anything smaller makes mobile Safari zoom on
   focus and never zoom back, which strands the fixed .bnav off-screen. */
.tw__post { flex: 0 0 auto; margin-left: auto; border: none; cursor: pointer; font: inherit; font-weight: 800;
  background: var(--lav); color: #fff; border-radius: 999px; padding: .6rem 1.6rem;
  transition: opacity .15s, background .15s; }
.tw__post:hover:not(:disabled) { background: var(--lav-deep); }
.tw__post:disabled { background: var(--line); color: var(--ink-soft); opacity: .7; cursor: not-allowed; }
.upstate { margin: .5rem 0 0; }
.upstate:empty { display: none; }
#up-status.ok { color: var(--green-dp); font-weight: 700; }
/* Destination segmented control (composer + edit forms) */
.tw-dest { position: relative; display: inline-flex; background: var(--tint); border-radius: 999px; padding: .2rem; }
.tw__bar .tw-dest { margin-left: auto; }
.tw-dest input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.tw-dest label { padding: .35rem .7rem; border-radius: 999px; font-size: .78rem; font-weight: 700;
  color: var(--ink-soft); cursor: pointer; white-space: nowrap; }
.tw-dest input:checked + label { background: var(--paper); color: var(--lav-deep); box-shadow: 0 1px 4px -1px rgba(60,40,110,.3); }
.tw-dest input:focus-visible + label { outline: 2px solid var(--lav-deep); outline-offset: 1px; }
.tw-recent { max-width: 640px; }
.tw-recent__h { font-size: 1.05rem; margin: 0 0 .8rem; }
/* Admin day-banner manager (Write page) */
.banner-admin { max-width: 640px; margin-bottom: 1.6rem; padding: 1rem 1.1rem; background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.banner-form { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.banner-form select, .banner-form input { padding: .5rem .65rem; border: 1px solid var(--line);
  border-radius: 10px; font: inherit; background: var(--cream); color: var(--ink); }
.banner-form input[name="banner_title"] { flex: 1 1 16rem; min-width: 0; }
.banner-list { list-style: none; margin: .9rem 0 0; padding: 0; display: grid; gap: .35rem; }
.banner-list__item { display: flex; align-items: baseline; gap: .6rem; font-size: .85rem;
  border-top: 1px dashed var(--line); padding-top: .35rem; }
.banner-list__day { flex: 0 0 auto; font-weight: 700; color: var(--lav-deep); font-variant-numeric: tabular-nums; }
.banner-list__title { flex: 1 1 auto; min-width: 0; color: var(--ink); }
.banner-list__item .inline { display: inline; flex: 0 0 auto; }
/* Day banner in the diary feed — a highlighted day title */
.feed-banner { font-size: 1.15rem; font-weight: 800; line-height: 1.45; color: var(--lav-deep);
  background: var(--tint); border-left: 4px solid var(--lav); border-radius: 12px; padding: .8rem 1.05rem; }

/* ---------- Dashboard panels + entry list (shared) ---------- */
.dash .panel { margin-bottom: 1.2rem; }
.diary-link { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.diary-link code { background: var(--tint); padding: .35rem .6rem; border-radius: 8px; font-size: .78rem; word-break: break-all; }
.entry-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; }
.entry { background: var(--cream); border: 1px solid var(--line); border-radius: 12px; padding: .8rem 1rem; }
.entry__head { display: flex; gap: .55rem; align-items: baseline; flex-wrap: wrap; }
.entry__kind { font-size: 1.05rem; }
.entry__title { font-weight: 700; }
.entry__meta { font-size: .78rem; color: var(--ink-soft); }
.entry__badge { font-size: .66rem; background: var(--tint); color: var(--lav-deep); padding: .12rem .5rem;
                border-radius: 999px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.entry__badge--locked { background: #fbe6e2; color: var(--coral); }
.entry__body { margin: .35rem 0 0; font-size: .92rem; color: var(--ink-soft); }
.entry__thumb { max-height: 110px; max-width: 100%; border-radius: 8px; margin-top: .45rem; display: block; }
.entry__actions { margin-top: .5rem; display: flex; gap: .9rem; align-items: baseline; }
.entry__actions > form { display: inline; }
.entry details { flex: 1; }
.entry details summary { cursor: pointer; }
.entry details form { display: grid; gap: .6rem; margin-top: .6rem; }
.entry details label { display: grid; gap: .25rem; font-size: .8rem; font-weight: 600; color: var(--ink-soft); }
/* font-size pinned to 1rem: font:inherit alone picks up the .8rem list text,
   and any control under 16px makes Android zoom the page in on focus. */
.entry input, .entry select, .entry textarea { padding: .5rem .65rem; border: 1px solid var(--line); border-radius: 8px; font: inherit; font-size: 1rem; background: var(--paper); }
.btn--link { background: none; border: none; color: var(--lav-deep); font: inherit; font-weight: 600; cursor: pointer; padding: 0; }
.btn--danger-link { color: var(--coral); }
progress.upbar { width: 100%; height: 10px; }

/* ---------- Day guide ---------- */
.dg-days { display: flex; gap: .4rem; overflow-x: auto; flex-wrap: nowrap; padding-bottom: .3rem; margin-bottom: 1.1rem; }
.dg-chip { flex: 0 0 auto; }
.dg-chip--today { position: relative; box-shadow: 0 0 0 2px var(--gold); }
.dg-chip--today::after { content: ""; position: absolute; top: -5px; right: -5px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--gold); border: 2px solid var(--paper); }
.dg-filters { margin-bottom: .4rem; }
.dg-filter-clear { color: var(--coral); }
.dg-count { color: var(--ink-soft); font-size: .85rem; margin: 0 0 1.3rem; }
@media (min-width: 700px) { .dg-days { flex-wrap: wrap; overflow-x: visible; justify-content: center; } }

.dg-head { background: var(--tint); border-radius: var(--radius); padding: 1.2rem 1.4rem; margin-bottom: 1.6rem; }
.dg-head__title { margin: 0 0 .5rem; font-size: 1.25rem; }
.dg-head__line { margin: .25rem 0; }
.dg-head__line a { font-weight: 600; }
.dg-head__warn { margin: .35rem 0; color: var(--amber); font-weight: 500; }
.dg-head__note { margin: .5rem 0 0; color: var(--ink-soft); font-style: italic; }

.dg-event { border-left: 4px solid var(--gold); }

.dg-zone { margin: 1.8rem 0; }
.dg-zone__head { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; flex-wrap: wrap; margin-bottom: .9rem; }
.dg-zone__head h3 { margin: 0; font-size: 1.15rem; }
.dg-zone__count { color: var(--ink-soft); font-size: .85rem; }

.dg-pill { display: inline-block; font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: .12rem .55rem; border-radius: 999px; vertical-align: middle; margin-left: .35rem; }
.dg-pill--part { background: var(--amber-tint); color: var(--amber); }
.dg-pill--icon { background: var(--gold); color: #fff; }

/* Food guide (Guide → Things to eat) */
.dg-view { margin-bottom: 1rem; flex-wrap: nowrap; }
.dg-view .tab { font-weight: 700; white-space: nowrap; }
@media (max-width: 480px) {
  .dg-view { gap: .35rem; }
  .dg-view .tab { padding: .45rem .65rem; font-size: .85rem; }
}
.fx-view { padding: 1rem 0 2rem; }
.fx-view .fx-line { justify-content: center; font-size: 1.15rem; }

/* One weather card per point — where we are, where the day started, where it
   ends. Each keeps its own 24 hours, which is the whole reason they're
   separate cards rather than one strip. */
.wx-card + .wx-card { margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.wx-card__role { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem;
  margin: .25rem 0 .5rem; font-size: .8rem; font-weight: 600; color: var(--ink-soft); }
.wx-card__role .muted { font-weight: 400; font-size: .76rem; }

/* ---------- Info page: sub-tabs, FX chart, AI feeds ---------- */

/* General / News / Local. Icon-only on a phone, same rule as the composer's
   attach row — three labels plus icons don't fit 360px without truncating. */
.itabs { display: flex; gap: .4rem; justify-content: center; margin: 0 0 1.2rem; }
.itab { display: inline-flex; align-items: center; gap: .35rem; text-decoration: none;
  font-size: 1.05rem; line-height: 1; font-weight: 600; color: var(--ink-soft);
  background: var(--paper); border: 1px solid var(--line); border-radius: 999px;
  padding: .5rem .9rem; }
.itab span { display: none; font-size: .85rem; }
.itab:hover { border-color: var(--lav); color: var(--lav-deep); }
.itab.is-active { background: var(--lav); border-color: var(--lav); color: #fff; }
@media (min-width: 420px) { .itab span { display: inline; } }

/* CAD→JPY history. Business days, not calendar days — see fx_series(). */
.fx-chart { max-width: 420px; margin: 1rem auto 0; }
.fx-ranges { display: flex; gap: .3rem; justify-content: center; margin-bottom: .5rem; }
.fx-range { text-decoration: none; font-size: .78rem; font-weight: 600; color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 999px; padding: .22rem .6rem; }
.fx-range:hover { border-color: var(--lav); color: var(--lav-deep); }
.fx-range.is-active { background: var(--tint); border-color: var(--lav); color: var(--lav-deep); }
.fx-spark { display: block; width: 100%; height: 72px; }
.fx-chart__foot { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
  gap: .45rem; margin: .3rem 0 0; font-size: .82rem; }
.fx-chart__now { font-weight: 800; font-size: 1rem; }
.fx-chart__delta { font-weight: 700; }
.fx-chart__delta.is-up { color: var(--green-dp); }
.fx-chart__delta.is-dn { color: #b3261e; }
html[data-theme="dark"] .fx-chart__delta.is-dn { color: #ff8a80; }
.fx-chart__foot .muted { font-size: .76rem; }

/* Where the feed is about, plus the ↻ that costs money to press. */
.info-where { display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem;
  margin: 0 0 1rem; font-size: .9rem; }
.info-where .muted { font-size: .8rem; }
.info-refresh { display: inline; }

.info-group { margin: 1.4rem 0 .5rem; font-size: .85rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--lav-deep); }
.info-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; }
.info-item { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .8rem .9rem; }
.info-item__title { font-weight: 700; color: var(--ink); text-decoration: none; line-height: 1.35; }
.info-item__title:hover { color: var(--lav-deep); text-decoration: underline; }
/* Every item links out, so say so once in the corner rather than on each. */
.info-item__title::after { content: " ↗"; color: var(--ink-soft); font-weight: 400; font-size: .85em; }
.info-item__sum { margin: .35rem 0 0; font-size: .88rem; line-height: 1.45; color: var(--ink-soft); }
.info-item__meta { display: flex; flex-wrap: wrap; gap: .5rem; margin: .4rem 0 0; font-size: .76rem; }
.info-item__when { font-weight: 700; color: var(--green-dp); }
/* The provenance line. Deliberately plain — it is a caveat, not a banner. */
.info-caveat { margin: 1.4rem 0 0; font-size: .76rem; color: var(--ink-soft); text-align: center; }

/* Admin: what the AI has cost. Scrolls inside itself on a phone rather than
   making the whole page scroll sideways. */
.ai-usage { overflow-x: auto; }
.ai-usage__t { width: 100%; border-collapse: collapse; font-size: .82rem; }
.ai-usage__t th { text-align: left; font-size: .72rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-soft); border-bottom: 1px solid var(--line); padding: .3rem .5rem; }
.ai-usage__t td { padding: .45rem .5rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.ai-usage__t td:not(:first-child) { text-align: right; white-space: nowrap; }
.ai-usage__t .muted { font-size: .72rem; }
.fd-pill--local { background: #dff5e9; color: var(--green-dp); }
.fd-pill--tourist { background: var(--tint); color: var(--lav-deep); }
.fd-pill--both { background: var(--amber-tint); color: var(--amber); }
.fd-dish { margin: .35rem 0 0; font-weight: 600; font-size: .9rem; }
.fd-intro { background: var(--tint); border-radius: var(--radius); padding: 1rem 1.2rem; margin-bottom: 1rem; }
.fd-intro__title { margin: 0 0 .4rem; font-size: .78rem; text-transform: uppercase; letter-spacing: .08em; color: var(--lav-deep); }
.fd-intro__list { margin: 0; padding-left: 1.1rem; display: grid; gap: .35rem; font-size: .9rem; }
html[data-theme="dark"] .fd-pill--local { background: #16352a; color: #7fd8ab; }

.pcard__badges { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; margin-bottom: .3rem; }
.pcard__badges .dg-pill { margin-left: 0; }
.pcard__stars { color: var(--gold); font-size: .9rem; letter-spacing: .05em; }
.pcard__name { margin: .1rem 0 0; font-size: 1.05rem; }
.pcard__ja { margin: .1rem 0; color: var(--ink-soft); font-size: .82rem; }
.pcard__desc { margin: .4rem 0; color: var(--ink-soft); }
.pcard__meta { display: flex; flex-wrap: wrap; gap: .15rem .8rem; font-size: .82rem; color: var(--ink-soft); margin-bottom: .5rem; }
.pcard__foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: .8rem; }
.pcard__foot details { flex-basis: 100%; }
.pcard__foot summary { cursor: pointer; color: var(--lav-deep); font-weight: 600; font-size: .88rem; }
.pcard__foot details p { margin: .4rem 0 0; color: var(--ink-soft); font-size: .88rem; }
.pcard__vfy { color: var(--amber); }

.dg-more { margin-top: 1rem; }
.dg-more summary { cursor: pointer; color: var(--lav-deep); font-weight: 600; }
.dg-more .cards { margin-top: 1rem; }

.dg-nearmiss { margin-top: 2rem; color: var(--ink-soft); }
.dg-nearmiss summary { cursor: pointer; font-weight: 600; color: var(--ink-soft); }
.dg-nearmiss ul { margin: .8rem 0 0; padding-left: 1.3rem; }
.dg-nearmiss li { margin: .4rem 0; }

/* ---------- FX line + running tab ---------- */
.fx-line { margin: .7rem 0 0; font-size: 1rem; display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; }
.fx-line .muted { font-size: .78rem; }
.fx-line__side { display: inline-flex; align-items: center; gap: .3rem; font-weight: 600; }
.fx-line input { width: 8ch; font: inherit; font-weight: 700; text-align: right; border: 1px solid var(--line);
                 border-radius: 8px; padding: .2rem .45rem; background: var(--paper); color: var(--ink); }
.balances { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .1rem; }
.balances li { display: flex; justify-content: space-between; gap: 1rem; border-bottom: 1px dashed var(--line); padding: .4rem 0; }
.bal--plus { color: var(--green-dp); font-weight: 700; }
.bal--minus { color: var(--coral); font-weight: 700; }
.bal--zero { color: var(--ink-soft); }
.settle { margin: 0; padding-left: 1.3rem; }
.settle li { margin: .25rem 0; }
.people-pick { display: flex; flex-wrap: wrap; gap: .45rem .9rem; border: 1px solid var(--line); border-radius: 10px; padding: .6rem .8rem; }
.people-pick label { display: flex !important; flex-direction: row; gap: .35rem; align-items: center; font-weight: 500 !important; }
.people-pick .kid { color: var(--ink-soft); font-size: .82rem; }
/* Split-between: one row per group, own checks + a "Both" toggle */
.split { border: none; padding: 0; margin: 0; }
.split legend { font-size: .72rem; font-weight: 700; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .06em; padding: 0; margin-bottom: .5rem; }
.split-grid { display: grid; gap: .5rem; }
.split-row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.split-head, .split-group, .split-all { display: flex !important; flex-direction: row; align-items: center; gap: .4rem;
  border: 1px solid var(--line); border-radius: 999px; padding: .4rem .85rem; cursor: pointer;
  font-weight: 600 !important; font-size: .9rem; color: var(--ink); background: var(--paper); }
.split-head input, .split-group input, .split-all input { width: 1.05rem; height: 1.05rem; accent-color: var(--lav); margin: 0; }
.split-head:has(input:checked) { border-color: var(--lav); background: var(--tint); color: var(--lav-deep); }
.split-group, .split-all { margin-left: auto; color: var(--ink-soft); background: transparent; border-style: dashed; }
.split-group:has(input:checked), .split-all:has(input:checked) { border-color: var(--lav); color: var(--lav-deep); border-style: solid; }
/* Settle-up: a button that reveals the plan */
.settleup { margin-top: .4rem; }
.settleup > summary { list-style: none; display: inline-block; }
.settleup > summary::-webkit-details-marker { display: none; }
.settleup > summary { cursor: pointer; }
.settleup[open] > summary { margin-bottom: .8rem; }
.settleup .settle { padding-left: 1.3rem; }

/* Log a purchase — compact filled fields, amount as the hero */
.logform { max-width: 34rem; }
.logform > * { min-width: 0; }               /* rows must shrink to the screen, not their content */
.logform__amount { display: flex; align-items: center; gap: .6rem; background: var(--tint); border-radius: 14px; padding: .45rem .5rem .45rem .95rem; }
.logform .logform__val { flex: 1 1 auto; min-width: 0; border: none; background: transparent; padding: .35rem 0;
  font: inherit; font-size: 1.7rem; font-weight: 800; color: var(--ink); }
.logform .logform__val::placeholder { color: var(--ink-soft); opacity: .55; font-weight: 700; }
.logform .logform__val:focus { outline: none; }
.seg { position: relative; display: flex; flex: 0 0 auto; background: var(--paper); border-radius: 999px; padding: .2rem; box-shadow: inset 0 0 0 1px var(--line); }
.logform .seg input { position: absolute; width: 1px; height: 1px; padding: 0; margin: 0; opacity: 0; border: 0; }
.logform .seg label { display: inline-flex; align-items: center; padding: .4rem .8rem; border-radius: 999px;
  font-size: .82rem; font-weight: 700; color: var(--ink-soft); cursor: pointer; white-space: nowrap; transition: .12s; }
.logform .seg input:checked + label { background: var(--lav); color: #fff; }
.logform .seg input:focus-visible + label { outline: 2px solid var(--lav-deep); outline-offset: 2px; }
.logform__pair { display: flex; flex-wrap: wrap; gap: .55rem; }
.logform__pair > .logform__row { flex: 1 1 9rem; min-width: 0; }   /* shrink below the datetime-local's intrinsic width */
.logform__row { display: flex; align-items: center; gap: .55rem; background: var(--tint); border-radius: 12px; padding: 0 .95rem; }
.logform__lbl { flex: 0 0 auto; font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-soft); }
.logform .logform__row input, .logform .logform__row select { flex: 1 1 auto; min-width: 0; border: none; background: transparent;
  border-radius: 0; padding: .6rem 0; font: inherit; font-size: 1rem; color: var(--ink); }
.logform .logform__row input:focus, .logform .logform__row select:focus { outline: none; }
.logform .split { padding: 0; }
.logform .split legend { margin-bottom: .5rem; }
.logform__add { width: 100%; text-align: center; margin-top: .3rem; }

/* Purchases — one horizontal card each (delete top corner, edit bottom) */
.plist { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; }
.pcard { position: relative; background: var(--paper); border: 1px solid var(--line); border-radius: 14px; padding: .85rem 1.05rem; }
.pcard__top { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding-right: 1.6rem; }
.pcard__desc { font-weight: 700; font-size: 1rem; color: var(--ink); }
.pcard__amt { flex: 0 0 auto; font-weight: 800; font-size: 1.05rem; color: var(--lav-deep); white-space: nowrap; }
.pcard__amt small { font-weight: 600; font-size: .78rem; }
.pcard__meta { margin: .25rem 0 0; font-size: .82rem; color: var(--ink-soft); }
.pcard__del { position: absolute; top: .4rem; right: .5rem; margin: 0; }
.pcard__del button { border: none; background: transparent; color: var(--ink-soft); cursor: pointer;
  font-size: .95rem; line-height: 1; padding: .3rem .4rem; border-radius: 8px; }
.pcard__del button:hover { color: var(--coral); background: var(--tint); }
.pcard__edit { margin-top: .5rem; }
.pcard__edit > summary { list-style: none; display: inline-block; cursor: pointer;
  font-size: .8rem; font-weight: 700; color: var(--lav-deep); }
.pcard__edit > summary::-webkit-details-marker { display: none; }
.pcard__edit[open] > summary { margin-bottom: .7rem; }
html[data-theme="dark"] .pcard__amt, html[data-theme="dark"] .pcard__edit > summary { color: #b9a6f5; }
.theme-pick { border: none; padding: 0; }
.tbl__editrow td { border-bottom: 1px solid var(--line); padding-top: 0; }
.entry-edit { display: grid; gap: .6rem; margin: .5rem 0 .8rem; }
.entry-edit label { display: grid; gap: .25rem; font-size: .8rem; font-weight: 600; color: var(--ink-soft); }
.entry-edit input, .entry-edit select { padding: .45rem .6rem; border: 1px solid var(--line); border-radius: 8px; font: inherit; background: var(--paper); color: var(--ink); }
.entry-edit .btn { justify-self: start; }

/* ---------- Bottom app bar (universal — the site's one navigation) ---------- */
body:has(.bnav) { padding-bottom: calc(4.2rem + env(safe-area-inset-bottom)); }
.bnav {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 60;
  display: flex; align-items: stretch; justify-content: center;
  padding: .3rem .3rem calc(.3rem + env(safe-area-inset-bottom));
  background: rgba(251, 249, 244, .92); backdrop-filter: blur(10px);
  border-top: 1px solid var(--line);
}
.bnav__item {
  flex: 1 1 0; max-width: 8rem;
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
  padding: .3rem 0 .25rem; border-radius: 12px; cursor: pointer; list-style: none;
  text-decoration: none; font-size: .64rem; font-weight: 600; color: var(--ink-soft);
}
.bnav__icon { font-size: 1.3rem; line-height: 1.25; }
.bnav__item.is-active { color: var(--lav-deep); background: var(--tint); }

/* WRITE is the point of the site, so it is the button your thumb finds
   without looking: filled, larger, lifted slightly out of the bar. It keeps
   its is-active treatment underneath so the bar still says where you are. */
.bnav__item--write { background: var(--lav); color: #fff; transform: translateY(-.28rem);
  box-shadow: 0 4px 12px -4px rgba(60,40,110,.5); }
.bnav__item--write .bnav__icon { font-size: 1.6rem; }
.bnav__item--write.is-active { background: var(--lav-deep); color: #fff; }
.bnav__item--write:hover { background: var(--lav-deep); }
/* The fifth slot holds its width so the other four don't re-centre when the
   feature that goes here arrives. Inert: no link, no hover, nothing to tap. */
.bnav__item--soon { flex: 1 1 0; max-width: 8rem; pointer-events: none; }

/* ---------- Dark theme (Settings → Appearance; default follows device) ----------
   The sky the fireworks happen in: near-black indigo, with the burst
   colours turned up rather than muted. Cards lift off the page instead of
   matching it, so a photo-heavy feed still has visible edges at night.

   --accent-deep is a LIGHT pink here. In the light theme it's the darker
   ink used for links; on a night page the same value goes muddy, which
   the old palette worked around case by case. Flipping it at the variable
   fixes every link, chip and active state at once. */
html[data-theme="dark"] {
  color-scheme: dark; /* native selects, pickers, scrollbars follow the theme */
  --ink:        #f4ecf2;
  --ink-soft:   #a99cba;
  --cream:      #0a0912;
  --paper:      #16142a;
  --tint:       #201c3a;
  --accent:     #ff5c8a;
  --accent-deep:#ff9ab6;
  --green:      #3ecfa4;
  --green-dp:   #2fae8a;
  --gold:       #ffc44d;
  --coral:      #ff7f5f;
  --line:       #2e2850;
  --amber:      #ffc44d;
  --amber-tint: #33260f;
  --shadow:     0 12px 34px -16px rgba(0, 0, 0, .72);
}
html[data-theme="dark"] .nav  { background: rgba(10, 9, 18, .86); }
html[data-theme="dark"] .bnav { background: rgba(10, 9, 18, .93); }
html[data-theme="dark"] .muted { color: #8d81a0; }
html[data-theme="dark"] .btn { background: var(--tint); color: #ffd0de; }
html[data-theme="dark"] .btn--danger { background: #4a1d24; color: #ff9d8a; }
html[data-theme="dark"] .wchip__temps { color: var(--ink); }
/* On a near-black page the accent fill needs white on it, not ink. */
html[data-theme="dark"] .nav__cta { color: #1a0d13 !important; }

/* ---------- Lavender theme (Settings → Appearance) ----------
   A light theme, not a purple filter over the dark one. The whole surface
   ramp shifts into violet — page, cards, borders — and the accents move
   with it so nothing is left sitting on a hue it wasn't designed for.

   The two things that make a tinted light theme go wrong are contrast and
   accent collision. So: --ink stays a deep near-black violet (13:1 on the
   page, well past AA), and --green/--gold/--coral are re-picked toward the
   cooler, deeper end — the stock green in particular reads acid against
   lavender. The accent goes DEEPER rather than brighter, because the
   backgrounds came up to meet it and the old value no longer separated
   from them. */
html[data-theme="lavender"] {
  color-scheme: light;
  --ink:        #2a1d47;
  --ink-soft:   #6b5a94;
  --cream:      #f6f1fd;   /* page */
  --paper:      #fffcff;   /* cards lift off the page rather than matching it */
  --tint:       #ece2fb;
  --accent:     #6d47cf;
  --accent-deep:#4b2c9e;
  --green:      #2b8f77;
  --green-dp:   #1d6f5c;
  --gold:       #c98a2e;
  --coral:      #d9556b;
  --line:       #ddd0f2;
  --amber:      #8a5b1a;
  --amber-tint: #f7e7d4;
  --shadow:     0 12px 34px -16px rgba(75, 44, 158, .34);
}
html[data-theme="lavender"] .nav  { background: rgba(246, 241, 253, .88); }
html[data-theme="lavender"] .bnav { background: rgba(246, 241, 253, .94); }
/* .btn's default face is --tint, which on this theme is close enough to the
   page to read as flat; give it the paper face and a border instead. */
html[data-theme="lavender"] .btn { background: var(--paper); color: var(--lav-deep); border: 1px solid var(--line); }
html[data-theme="lavender"] .btn--danger { background: #fbe4e8; color: #a3283f; border-color: #f0c4cd; }
html[data-theme="lavender"] .rxn__chip.is-on { border-color: var(--lav); }

/* ---------- Landing (public front door) ---------- */
.hero--landing .hero__inner { padding-top: clamp(5rem, 16vw, 9rem); padding-bottom: clamp(5rem, 15vw, 8.5rem); }
.hero__jp { font-family: 'Zen Kaku Gothic New', 'Inter', sans-serif; font-size: clamp(1.35rem, 4.5vw, 2.1rem); font-weight: 700; }
.hero__actions { display: flex; gap: .9rem; justify-content: center; flex-wrap: wrap; margin-top: 2.2rem; }
.login__note a { color: #fff; }

/* ---------- Repair truncated captions (admin) ---------- */
.fixup__was { margin: .3rem 0 .8rem; padding: .6rem .9rem; border-left: 3px solid var(--line);
  background: var(--tint); color: var(--ink-soft); font-size: .9rem; border-radius: 0 8px 8px 0; white-space: pre-wrap; }
#repair .btn { text-decoration: none; }

/* ---------- Admin videos page ---------- */
.vidcard video { width: 100%; max-height: 320px; border-radius: 10px; background: #000; }
.vidcard__actions { display: flex; gap: .5rem; margin-top: .4rem; }
.vidcard__badge--failed { color: #a03030; }
.vidcard__badge--done { color: #2e7d4f; }

/* ---------- 🍜 Food log ---------- */
.dash--food { max-width: 680px; }
.food-head h1 { margin: 0 0 .2rem; }
.food-head__sum { margin: 0 0 1.4rem; font-size: .9rem; color: var(--ink-soft); }

.fform { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1rem 1.1rem; margin-bottom: 1.8rem; }
/* Meal or snack, chosen before anything else — it's the one decision that
   changes how much form you're signing up for. */
.fform__kind { display: flex; gap: .5rem; margin-bottom: 1rem; }
.fkind { flex: 1 1 0; }
.fkind input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.fkind span { display: block; text-align: center; cursor: pointer; font-weight: 700;
  padding: .6rem .4rem; border: 1px solid var(--line); border-radius: 999px; background: var(--cream); }
.fkind input:checked + span { background: var(--lav); border-color: var(--lav); color: #fff; }
.fkind input:focus-visible + span { outline: 2px solid var(--lav-deep); outline-offset: 2px; }

/* Two buttons, not six. Big targets: the old .btn--sm override made these
   ~28px tall, well under the 44px a thumb needs. */
.fpick { display: flex; gap: .5rem; margin-bottom: .7rem; }
.fpick__btn { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: .2rem;
  min-height: 4.2rem; cursor: pointer; font: inherit; font-size: 1.5rem; line-height: 1;
  background: var(--cream); border: 1px solid var(--line); border-radius: 14px; color: var(--ink); }
.fpick__btn span { font-size: .8rem; font-weight: 700; color: var(--ink-soft); }
.fpick__btn:hover { border-color: var(--lav); }

/* One strip. The chip on each thumbnail says what the photo IS, and cycles
   🍜 → 📜 → 📍 → 🧾 on tap — classification after you can see the picture,
   rather than a taxonomy question before one exists. */
.fstrip { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .9rem; }
.fstrip:empty { display: none; }
.fshot-cell { position: relative; width: 74px; }
.fshot-cell img { width: 100%; height: 74px; object-fit: cover; border-radius: 10px; display: block; }
.fshot-cell__slot { position: absolute; left: .2rem; bottom: .2rem; min-width: 1.6rem; min-height: 1.6rem;
  border: none; border-radius: 999px; cursor: pointer; font-size: .85rem; line-height: 1;
  background: rgba(255,255,255,.9); }
/* A photo that will NOT go to the diary says so on its face. */
.fshot-cell__slot.is-private { background: var(--amber-tint, #fdf3dd); box-shadow: 0 0 0 2px #b8860b inset; }
.fshot-cell__x { position: absolute; top: -.3rem; right: -.3rem; width: 1.4rem; height: 1.4rem;
  border-radius: 999px; border: none; background: rgba(0,0,0,.65); color: #fff; cursor: pointer;
  font-size: .72rem; line-height: 1; }

.floc { margin: 0 0 .9rem; font-size: .82rem; color: var(--ink-soft); }
.fkinds { display: flex; gap: .5rem; align-items: flex-end; }
.fkinds .fkind { flex: 1 1 0; }
.fyen { font-weight: 700; color: var(--ink-soft); }
.fmore { margin-bottom: .9rem; }
.fmore summary { cursor: pointer; font-size: .85rem; font-weight: 600; color: var(--lav-deep); padding: .4rem 0; }
.fshare { display: inline-flex; align-items: center; gap: .3rem; font-size: .85rem; cursor: pointer; }
.fshare input { width: 1.1rem; height: 1.1rem; }
.fwhy { border: none; background: none; color: var(--ink-soft); cursor: pointer; font-size: 1rem; padding: .2rem; }
.fshare__why { margin: .5rem 0 0; font-size: .78rem; color: var(--ink-soft); }
.fshare__why[hidden] { display: none; }

/* 🍜 Shooting: one job, one button, under the thumb. */
.shoot { text-align: center; padding: 1rem 0 2rem; }
.shoot[hidden] { display: none; }
.shoot__h { font-size: 1.1rem; font-weight: 800; margin: 0 0 1rem; }
.shoot__go { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .4rem;
  width: 100%; min-height: 42vh; cursor: pointer; font: inherit; font-size: 3.4rem; line-height: 1;
  background: var(--lav); color: #fff; border: none; border-radius: 20px; }
.shoot__go span { font-size: 1rem; font-weight: 800; }
.shoot__go:active { background: var(--lav-deep); }
.shoot__strip { display: flex; flex-wrap: wrap; gap: .35rem; justify-content: center; margin: .9rem 0; }
.shoot__foot { display: flex; align-items: center; justify-content: center; gap: 1rem; margin: 0; }
.shoot__note { font-size: .76rem; margin: .6rem 0 0; }
.food-head__shoot { display: flex; align-items: center; gap: .7rem; margin: .2rem 0 1.2rem; }

.fform__row { display: block; margin-bottom: .8rem; font-size: .8rem; font-weight: 600; color: var(--ink-soft); }
.fform__row input, .fform__row textarea { width: 100%; margin-top: .25rem; font-weight: 400; }
.fform__two { display: grid; gap: .8rem; }
@media (min-width: 460px) { .fform__two { grid-template-columns: 1fr 1fr; } }
.fform__loc { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: 0 0 .9rem; font-size: .8rem; }
.fform__rate { margin: .4rem 0 .4rem; font-size: .8rem; font-weight: 600; color: var(--ink-soft); }

/* ✕ △ ○ ◎ — Japan's own four-level scale (batsu / sankaku / maru /
   nijuumaru). Glyphs, not emoji, so they render identically everywhere. */
.fscore { display: flex; gap: .4rem; margin-bottom: 1rem; }
.fscore__opt input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.fscore__opt span { display: flex; align-items: center; justify-content: center;
  width: 2.6rem; height: 2.6rem; cursor: pointer; font-size: 1.35rem; line-height: 1;
  border: 1px solid var(--line); border-radius: 999px; background: var(--cream); color: var(--ink-soft); }
.fscore__opt input:checked + span { background: var(--lav); border-color: var(--lav); color: #fff; }
.fscore__opt input:focus-visible + span { outline: 2px solid var(--lav-deep); outline-offset: 2px; }

.fform__share { display: flex; align-items: flex-start; gap: .5rem; margin-bottom: 1rem; cursor: pointer; font-size: .85rem; }
.fform__share input { width: 1.1rem; height: 1.1rem; flex: 0 0 auto; margin-top: .15rem; }
.fform__share em { display: block; font-style: normal; font-size: .76rem; }
.fform__bar { display: flex; align-items: center; gap: .8rem; }

.flog { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
.fentry { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: .9rem 1rem; }
.fentry__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; }
.fentry__kind { font-size: 1.1rem; }
.fentry__place { font-weight: 800; }
.fentry__when { font-size: .78rem; color: var(--ink-soft); }
.fentry__bill { margin-left: auto; font-weight: 700; font-size: .9rem; }
.fentry__bill .muted { font-weight: 400; font-size: .8rem; }
.fentry__shots { display: flex; flex-wrap: wrap; gap: .4rem; margin: .6rem 0; }
.fshot { margin: 0; width: 96px; }
.fshot img { width: 100%; height: 96px; object-fit: cover; border-radius: 10px; display: block; }
.fshot figcaption { font-size: .68rem; color: var(--ink-soft); text-align: center; margin-top: .15rem; }
.fentry__ordered { margin: .5rem 0 0; font-size: .92rem; }
.fentry__comment { margin: .35rem 0 0; font-size: .85rem; color: var(--ink-soft); font-style: italic; }

/* The table of travellers — literally a table. Every traveller gets a row
   whether or not they've rated, so an empty one reads as an invitation
   rather than a silence. */
.ftable { width: 100%; border-collapse: collapse; margin: .7rem 0 .2rem; }
.ftable th { text-align: left; font-size: .82rem; font-weight: 700; padding: .25rem .5rem .25rem 0; white-space: nowrap; }
.ftable td { padding: .25rem 0; }
.ftable__form { display: flex; gap: .25rem; }
.fmark { width: 2rem; height: 2rem; cursor: pointer; font-size: 1.05rem; line-height: 1;
  border: 1px solid var(--line); border-radius: 999px; background: var(--cream); color: var(--ink-soft); }
.fmark:hover { border-color: var(--lav); color: var(--lav-deep); }
.fmark.is-on { background: var(--lav); border-color: var(--lav); color: #fff; }
.fmark--clear { border-style: dashed; font-size: .8rem; }
.fentry__foot { display: flex; align-items: center; gap: .8rem; margin: .5rem 0 0; font-size: .78rem; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* Converting a diary post into a food entry: one row per photo, slot picked
   by hand. Only the person who was there knows which shot is the menu. */
.fform__conv { margin: 0 0 1rem; font-size: .9rem; }
.fconv { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .4rem; }
.fconv__row { display: flex; align-items: center; gap: .6rem; padding: .35rem;
  border: 1px solid var(--line); border-radius: 12px; background: var(--cream); }
/* Album reorder: a drag handle plus ▲▼ buttons that do the SAME job — the
   buttons are the guaranteed-working path on a phone, so they get a real
   tap target (not .btn--link's zero padding), not just a smaller icon
   version of the drag handle. */
.fconv__drag { cursor: grab; color: var(--ink-soft); font-size: 1.1rem; line-height: 1; flex: 0 0 auto; touch-action: none; }
.fconv__row.is-dragging { opacity: .5; border-color: var(--lav-deep); border-style: dashed; }
.fconv__mv { flex: 0 0 auto; min-width: 2rem; min-height: 2rem; padding: .3rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; font-size: .9rem; line-height: 1; }
.fconv__mv:hover, .fconv__mv:focus-visible { background: var(--paper); }
.fconv__n { width: 1.4rem; text-align: center; font-weight: 800; color: var(--ink-soft); font-size: .8rem; }
.fconv__img { width: 54px; height: 54px; object-fit: cover; border-radius: 8px; flex: 0 0 auto; }
.fconv__when { font-size: .75rem; color: var(--ink-soft); }
.fconv__slots { display: flex; gap: .25rem; margin-left: auto; }
.fconv__slot input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.fconv__slot span { display: block; cursor: pointer; font-size: 1.05rem; line-height: 1;
  padding: .4rem .5rem; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); }
.fconv__slot input:checked + span { background: var(--lav); border-color: var(--lav); }
.fconv__slot input:focus-visible + span { outline: 2px solid var(--lav-deep); outline-offset: 2px; }

.fconv-pick { margin-bottom: 1.6rem; }
.fconv-pick summary { cursor: pointer; font-size: .88rem; font-weight: 600; color: var(--lav-deep); }
.fconv-pick__list { list-style: none; margin: .6rem 0 0; padding: 0; display: grid; gap: .35rem; }
.fconv-pick__list a { display: flex; align-items: center; gap: .6rem; text-decoration: none;
  color: inherit; padding: .3rem; border: 1px solid var(--line); border-radius: 10px; font-size: .82rem; }
.fconv-pick__list a:hover { border-color: var(--lav); }
.fconv-pick__list img { width: 40px; height: 40px; object-fit: cover; border-radius: 6px; }

/* The new-entry form is collapsed: Food is mostly for reading back what
   you've eaten, so the form sits behind one button rather than pushing the
   log below the fold every time. <details>, so it works with no JS. */
.fnew { margin-bottom: 1.4rem; }
.fnew__btn { display: block; cursor: pointer; text-align: center; font-weight: 800;
  background: var(--lav); color: #fff; border-radius: 999px; padding: .7rem 1rem; list-style: none; }
.fnew__btn::-webkit-details-marker { display: none; }
.fnew__btn:hover { background: var(--lav-deep); }
.fnew[open] .fnew__btn { border-radius: 14px 14px 0 0; }
.fnew[open] .fform { border-radius: 0 0 14px 14px; border-top: none; margin-bottom: 0; }

/* Each logged meal is one line until you open it. Six lines is a menu you
   can scan; six expanded entries is a scroll. */
.fentry > details > summary { list-style: none; cursor: pointer; }
.fentry > details > summary::-webkit-details-marker { display: none; }
.fentry__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; }
.fentry > details[open] > summary .fentry__head { margin-bottom: .3rem; }
.fentry > details[open] { }
/* Ratings on the CLOSED row — scanning for "where would we go back to"
   shouldn't mean opening six entries. */
.fentry__marks { font-size: .95rem; letter-spacing: .1em; color: var(--lav-deep); }
.fedit { margin-top: .6rem; }
.fedit summary { cursor: pointer; font-size: .85rem; }
.fedit form { display: block; margin-top: .6rem; padding-top: .6rem; border-top: 1px solid var(--line); }

/* Meals and snacks are colour-coded down the left edge, so scanning the
   collapsed list tells you which is which before you read a word.
   Lavender = a sit-down meal, green = something grabbed on the way past. */
.fentry--meal  { border-left: 4px solid var(--lav); }
.fentry--snack { border-left: 4px solid var(--green-dp); }
.fentry--meal  .fentry__kind { background: var(--tint); }
.fentry--snack .fentry__kind { background: #dff5e9; }
.fentry__kind { border-radius: 999px; padding: .15rem .3rem; line-height: 1; }
html[data-theme="dark"] .fentry--snack .fentry__kind { background: rgba(23,110,60,.28); }

/* "Save the originals to your phone" — the site keeps the shrunk copy, the
   phone keeps the full-size one. Only appears when there's a camera-taken
   photo the phone doesn't already have. */
.fsave-roll { display: block; width: 100%; margin: 0 0 .9rem; }
.fsave-roll[hidden] { display: none; }

/* ---------- 💴 Money ---------- */
.dash--money { max-width: 680px; }
/* Where it went. Bars scale to the BIGGEST category, not the total —
   comparing categories to each other is the question this answers, and
   against the total most bars would be slivers. */
.mcat { display: grid; gap: .3rem; margin-bottom: 1.4rem; }
.mcat__row { display: flex; align-items: center; gap: .5rem; font-size: .82rem; }
.mcat__ico { width: 1.4rem; text-align: center; }
.mcat__bar { flex: 1 1 auto; height: .55rem; background: var(--tint); border-radius: 999px; overflow: hidden; }
.mcat__bar i { display: block; height: 100%; background: var(--lav); border-radius: 999px; }
.mcat__amt { min-width: 5.5rem; text-align: right; font-weight: 700; }

.mtab { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .9rem 1rem; margin-bottom: 1.4rem; }
.mtab__h { margin: 0 0 .4rem; font-size: .9rem; }
.mtab__bal { text-align: right; font-weight: 700; font-size: .85rem; }
.mtab__bal.is-up { color: var(--green-dp); }
.mtab__bal.is-dn { color: #b3261e; }
html[data-theme="dark"] .mtab__bal.is-dn { color: #ff8a80; }
.mtab__plan { margin: .6rem 0 .2rem; font-size: .85rem; }
.mtab__list { margin: 0; padding-left: 1.2rem; font-size: .85rem; }

.mcats { display: grid; grid-template-columns: repeat(auto-fit, minmax(4.6rem, 1fr)); gap: .35rem; margin-bottom: .5rem; }
.mcats__opt input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.mcats__opt span { display: flex; flex-direction: column; align-items: center; gap: .15rem;
  cursor: pointer; font-size: 1.15rem; line-height: 1; padding: .45rem .2rem;
  border: 1px solid var(--line); border-radius: 12px; background: var(--cream); }
.mcats__opt span em { font-style: normal; font-size: .62rem; font-weight: 700; color: var(--ink-soft); }
.mcats__opt input:checked + span { background: var(--lav); border-color: var(--lav); }
.mcats__opt input:checked + span em { color: #fff; }
.mcats__opt input:focus-visible + span { outline: 2px solid var(--lav-deep); outline-offset: 2px; }
.mcats__note { font-size: .74rem; margin: 0 0 .9rem; }

.mamt { display: flex; gap: .35rem; margin-top: .25rem; }
.mamt input { flex: 1 1 auto; font-weight: 700; }
.mamt select { flex: 0 0 auto; }

.mlog { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.mrow { display: flex; align-items: center; gap: .6rem; padding: .55rem .7rem;
  background: var(--paper); border: 1px solid var(--line); border-radius: 12px; }
.mrow__ico { font-size: 1.1rem; flex: 0 0 auto; }
.mrow__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.mrow__label { font-weight: 700; font-size: .88rem; color: inherit; }
a.mrow__label:hover { color: var(--lav-deep); }
.mrow__src, .mrow__meta { font-size: .72rem; }
.mrow__amt { flex: 0 0 auto; text-align: right; display: flex; flex-direction: column; }
.mrow__amt strong { font-size: .92rem; }
.mrow__amt .muted { font-size: .7rem; }
.mrow__del button { border: none; background: none; color: var(--ink-soft); cursor: pointer; font-size: .8rem; padding: .2rem; }
.mrow__del button:hover { color: #b3261e; }

/* ---------- ✎ Crop & rotate ---------- */
/* ✎ sits opposite ✨ on the thumbnail, sharing the same badge geometry so
   the three controls read as one set. */
.tw__thumb .tw__edit { position: absolute; top: .25rem; left: .25rem; font-size: .72rem;
  border: none; border-radius: 999px; cursor: pointer; line-height: 1; padding: .2rem .35rem;
  background: rgba(255,255,255,.85); color: var(--lav-deep); }
.tw__previews.is-one .tw__thumb .tw__edit { font-size: .95rem; padding: .3rem .5rem; }

.crop { position: fixed; inset: 0; z-index: 90; display: flex; align-items: center;
  justify-content: center; background: rgba(0,0,0,.72); padding: 1rem; }
.crop[hidden] { display: none; }   /* flex must not beat [hidden] */
body.is-cropping { overflow: hidden; }
.crop__box { background: var(--paper); border-radius: var(--radius); padding: .8rem;
  max-width: min(94vw, 560px); width: 100%; }
.crop__stage { display: flex; justify-content: center;
  background: repeating-conic-gradient(#0001 0% 25%, transparent 0% 50%) 50%/16px 16px; }
/* The frame is positioned against THIS, not the stage. .crop__fit shrink-wraps
   the canvas, so frame coordinates and canvas pixels share an origin whatever
   the aspect ratio. Positioning against the centring flex container instead
   pushed the box left by the gap on every portrait photo. */
.crop__fit { position: relative; line-height: 0; flex: 0 0 auto; max-width: 100%; }
.crop__stage canvas { display: block; max-width: 100%; touch-action: none; }
/* The frame is the interactive part; touch-action none so a drag crops
   instead of scrolling the page underneath. */
.crop__frame { position: absolute; box-sizing: border-box; cursor: move; touch-action: none;
  border: 2px solid #fff; box-shadow: 0 0 0 9999px rgba(0,0,0,.45); }
.crop__frame i { position: absolute; width: 22px; height: 22px; background: #fff;
  border-radius: 3px; box-shadow: 0 1px 3px rgba(0,0,0,.5); }
.crop__frame i[data-h="nw"] { top: -11px; left: -11px; cursor: nwse-resize; }
.crop__frame i[data-h="ne"] { top: -11px; right: -11px; cursor: nesw-resize; }
.crop__frame i[data-h="sw"] { bottom: -11px; left: -11px; cursor: nesw-resize; }
.crop__frame i[data-h="se"] { bottom: -11px; right: -11px; cursor: nwse-resize; }
.crop__hint { margin: .5rem 0 .4rem; font-size: .75rem; text-align: center; }
.crop__bar { display: flex; align-items: center; gap: .4rem; }
.crop__sp { flex: 1 1 auto; }

/* "That upload never finished" — offered, never resent silently. */
.resume { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
  margin: 0 0 1.2rem; padding: .7rem .9rem; font-size: .85rem;
  background: var(--amber-tint, #fdf3dd); color: #8a5a12;
  border: 1px solid #b8860b; border-radius: var(--radius); }
html[data-theme="dark"] .resume { background: rgba(224,178,95,.12); color: #e0b25f; }

/* ---------- 📍 Right here ---------- */
/* A button row, not a panel: this sits below the weather because the weather
   is what you glance at and this is what you ask for. */
.here { margin: 0 0 1.2rem; }
.here__bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.here__ask { position: relative; }
.here__askbtn { display: inline-block; cursor: pointer; list-style: none;
  background: var(--cream); border: 1px solid var(--line); color: var(--ink-soft);
  border-radius: 999px; padding: .4rem .9rem; font-size: .82rem; font-weight: 600; }
.here__askbtn::-webkit-details-marker { display: none; }
.here__ask[open] .here__askbtn { background: var(--tint); color: var(--lav-deep); border-color: var(--lav); }
.here__askform { display: grid; gap: .5rem; margin-top: .5rem; padding: .7rem;
  background: var(--paper); border: 1px solid var(--line); border-radius: 14px; }
.here__askform input[type="text"] { width: 100%; }
.here__photo { font-size: .8rem; color: var(--ink-soft); display: grid; gap: .25rem; }

.here__q { margin: .8rem 0 0; font-size: .85rem; font-weight: 700; color: var(--lav-deep); }
.here__text { margin: .6rem 0 0; font-size: .95rem; line-height: 1.5;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .8rem .9rem; }
/* One line per kind, led by its icon — scannable instead of a run of names. */
.here__cat { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem;
  margin: .5rem 0 0; font-size: .84rem; }
.here__ico { font-size: 1rem; flex: 0 0 auto; }
.here__cat a { color: inherit; }
.here__cat a:hover { color: var(--lav-deep); }
.here__cat .muted { font-size: .72rem; }
/* The feature rests on a position, and a position is a claim — its radius
   and its age are how you judge it. */
.here__foot { margin: .7rem 0 0; font-size: .72rem; }

/* The conversation, and the follow-up box under it. */
.here__chat .here__text { margin-top: .35rem; }
.here__chat .here__q { margin-top: .9rem; }
.here__chat .here__q:first-child { margin-top: .8rem; }
.here__followup { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; margin: .7rem 0 .3rem; }
.here__followup input[type="text"] { flex: 1 1 12rem; min-width: 0; }
.here__followup .here__photo { display: inline-flex; align-items: center; gap: .2rem; font-size: 1rem; }
.here__followup .here__photo input { width: 0; height: 0; opacity: 0; position: absolute; }
/* A disabled submit must still read as a button mid-request, not as a gap. */
button[disabled] { opacity: .6; cursor: progress; }

/* Admin: the phone's credentials, side by side with a copy button. The input
   must stay >=16px like every other control here, or focusing it zooms mobile
   Safari and strands the fixed .bnav off-screen. */
.apk-cred { display: flex; gap: .5rem; align-items: center; margin: .35rem 0; }
.apk-cred input { flex: 1 1 auto; min-width: 0; font-family: ui-monospace, monospace;
  font-size: 1rem; }
.apk-cred .btn { flex: 0 0 auto; }

/* A video that has been posted but not yet transcoded and shipped to the
   edge. Deliberately plain — it is a status, not a thing to look at. */
.feed-video-wait { margin: .4rem 0; padding: .9rem 1rem; border-radius: 12px;
  background: var(--card-2, rgba(127,127,127,.12)); color: var(--muted, #667);
  font-size: .95rem; text-align: center; }

/* R2 usage. min-width on the fill so a nearly-empty bucket still shows a
   sliver rather than looking like a broken element. */
.r2bar { height: 8px; border-radius: 999px; overflow: hidden; margin: .1rem 0 .4rem;
  background: var(--card-2, rgba(127,127,127,.18)); }
.r2bar > span { display: block; height: 100%; border-radius: 999px;
  background: var(--accent, #7c6cc4); }
