/* Middle-earth 5e — platform styles.
   Mobile-first. Primary target is the Galaxy Fold 7: the cover screen is
   ~360px wide (single column) and the inner screen ~640-900px (two columns). */

:root {
  --bg: #14110d;
  --bg-2: #1d1913;
  --panel: #241f18;
  --panel-2: #2c261d;
  --line: #3b3226;
  --ink: #e8dfcc;
  --ink-dim: #a89c82;
  --gold: #c8a45c;
  --gold-dim: #8f7538;
  --green: #7c9a63;
  --red: #b4553f;
  --radius: 10px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
}

/* Bound the app column to the VISIBLE viewport, not the taller layout viewport
   behind the URL bar or under an overlapping system bar. Ported from the WWII /
   Liberty or Death platform layer, which had already solved this.
   
   Three declarations, deliberately: each overrides the last where supported, so
   an old browser still gets something sane. `--app-h` is the real answer — it
   comes from `visualViewport.height`, set before first paint by
   platform/viewport.js — because `dvh` on a cold load and under a taskbar is
   larger than what the user can actually see.
   
   Applied at EVERY width, not only under `html.mobile`. Scoping it to the
   mobile class is what made the character builder a dead end on a Fold
   unfolded: past the breakpoint the shell collapsed to content height and the
   wizard footer fell wherever the cards happened to end. */
html, body { height: 100svh; height: 100dvh; height: var(--app-h, 100dvh); overflow: hidden; }

h1, h2, h3 { font-weight: 600; letter-spacing: 0.01em; margin: 0 0 .5rem; }
h1 { font-size: 1.5rem; color: var(--gold); }
h2 { font-size: 1.15rem; color: var(--gold); }
h3 { font-size: 1rem; color: var(--ink); }
a { color: var(--gold); }

button, .btn {
  font: inherit;
  background: var(--panel-2);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .5rem .85rem;
  cursor: pointer;
  min-height: 40px;            /* fat-finger target on the Fold */
}
button:hover { border-color: var(--gold-dim); }
button:disabled { opacity: .5; cursor: default; }
button.primary { background: var(--gold-dim); color: #17130c; border-color: var(--gold); font-weight: 600; }
button.danger { border-color: var(--red); color: #e6b3a6; }

input, select, textarea {
  font: inherit;
  background: var(--bg-2);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .5rem .65rem;
  width: 100%;
  min-height: 40px;
}

label { display: block; margin: .6rem 0 .2rem; color: var(--ink-dim); font-size: .85rem; }

/* ---- Layout -------------------------------------------------------------- */
/* ---- Safe areas ----------------------------------------------------------
   The viewport meta says `viewport-fit=cover`, which is what lets the app fill
   a phone with rounded corners and a notch — and it also means the page runs
   UNDER the system bars. Anything pinned to an edge has to pad itself out of
   the way, or it sits beneath the Samsung navigation bar and simply cannot be
   tapped. That is not a cosmetic issue: it made the character builder's Next
   button unreachable once the app was installed, which is the difference
   between a working wizard and a dead end.

   `env()` is 0 on a desktop browser and on a phone with no inset, so these
   calc()s cost nothing where they are not needed. */
header {
  display: flex; align-items: center; gap: .5rem;
  padding: calc(.6rem + env(safe-area-inset-top)) .8rem .6rem;
  padding-left: calc(.8rem + env(safe-area-inset-left));
  padding-right: calc(.8rem + env(safe-area-inset-right));
  background: var(--bg-2);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
header .spacer { flex: 1; }
header .title {
  color: var(--gold); font-size: 1.05rem; font-weight: 600;
  /* One line, always. A flex item will not shrink below its content unless it
     is allowed to, so without `min-width: 0` the title held its full width and
     "Middle-earth 5e" broke over THREE lines on a folded Fold while the
     buttons ran off the right edge. Truncating is the lesser loss: the app's
     name is the one thing on the bar nobody needs to read. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}

/* On the cover screen the signed-in name is the first thing to go. It is the
   least useful item on the bar — you know who you are — and dropping it keeps
   the title whole and every control on one row at 360px. */
@media (max-width: 420px) {
  header #signed-in { display: none; }
  /* And a little smaller, which is enough for the whole name to fit beside
     four buttons at 360px rather than being cut to "Middle-ear…". The ellipsis
     above still protects every narrower width — this only spends the slack
     that hiding the name freed up. */
  header .title { font-size: .95rem; }
}

#app { display: flex; flex-direction: column; height: 100%; }

/* The lists region is the scroll owner on mobile. `data-scrollable` also marks
   it exempt from board gesture capture (gestures.js). */
main {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;          /* step 2 of the scroll fix */
  padding: .8rem;
  padding-left: calc(.8rem + env(safe-area-inset-left));
  padding-right: calc(.8rem + env(safe-area-inset-right));
  /* The scroll region owns the bottom inset when nothing else is pinned there:
     the last card in a list must be able to clear the navigation bar. `max()`
     because a bar the browser does not report is exactly what --ui-bottom is
     for — see platform/viewport.js. */
  padding-bottom: calc(.8rem + max(env(safe-area-inset-bottom, 0px), var(--ui-bottom, 0px)));
}

.cols { display: grid; grid-template-columns: 1fr; gap: .8rem; }
@media (min-width: 760px) { .cols { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1100px) { .cols { grid-template-columns: 1fr 1fr 1fr; } }

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .8rem;
}

.row { display: flex; align-items: center; gap: .5rem; }
.muted { color: var(--ink-dim); font-size: .85rem; }
.empty { color: var(--ink-dim); font-style: italic; padding: .6rem 0; }

.list { display: flex; flex-direction: column; gap: .5rem; }
.item {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .6rem .7rem;
  display: flex; align-items: center; gap: .6rem;
}
.item .grow { flex: 1; min-width: 0; }
.item .name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.pill {
  font-size: .72rem; padding: .1rem .45rem; border-radius: 999px;
  border: 1px solid var(--line); color: var(--ink-dim); white-space: nowrap;
}
.pill.turn { border-color: var(--gold); color: var(--gold); }
.pill.live { border-color: var(--green); color: var(--green); }

/* ---- Chat ---------------------------------------------------------------- */
.chat-log {
  height: 200px; overflow-y: auto; touch-action: pan-y;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .5rem; font-size: .9rem;
}
.chat-log .who { color: var(--gold-dim); }

/* ---- Modals -------------------------------------------------------------- */
.modal-back {
  position: fixed; inset: 0; background: rgba(0,0,0,.65);
  display: flex; align-items: center; justify-content: center; z-index: 50;
  padding: calc(1rem + env(safe-area-inset-top)) calc(1rem + env(safe-area-inset-right))
           calc(1rem + max(env(safe-area-inset-bottom, 0px), var(--ui-bottom, 0px)))
           calc(1rem + env(safe-area-inset-left));
}
.modal {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1rem; width: 100%; max-width: 480px;
  max-height: 85vh; overflow-y: auto; touch-action: pan-y;
}

/* ---- Toasts + deploy banner ---------------------------------------------- */
#toasts { position: fixed; left: 0; right: 0;
          bottom: calc(1rem + max(env(safe-area-inset-bottom, 0px), var(--ui-bottom, 0px)));
          display: flex; flex-direction: column;
          align-items: center; gap: .4rem; z-index: 100; pointer-events: none; }
.toast {
  background: var(--panel-2); border: 1px solid var(--gold-dim); color: var(--ink);
  padding: .5rem .8rem; border-radius: var(--radius); max-width: 90vw;
  transition: opacity .4s;
}
.toast.out { opacity: 0; }
.toast-error { border-color: var(--red); }

/* A bottom-centred pill, matching the sibling clients. A bar across the top
   reads as an alarm and covers the header; this is an offer the player can
   ignore or dismiss.
   
   (The previous rule also had a live bug: a `padding-top` longhand followed by
   a `padding` shorthand, which silently discarded the safe-area inset.) */
#deploy-banner {
  position: fixed; z-index: 200;
  left: 50%; transform: translateX(-50%);
  bottom: calc(.9rem + max(env(safe-area-inset-bottom, 0px), var(--ui-bottom, 0px)));
  display: flex; align-items: center; gap: .5rem;
  max-width: 92vw;
  padding: .5rem .8rem;
  background: var(--panel-2, #241a10); color: var(--ink);
  border: 1px solid var(--gold-dim); border-radius: var(--radius);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .6);
  font-size: .9rem;
}
#deploy-banner button { min-height: 32px; padding: .2rem .7rem; }
#deploy-banner button.ghost { background: none; border: none; color: var(--ink-dim); padding: .2rem .3rem; }

/* The unread count sits ON its button, not beside it.
 *
 * It was a plain sibling in the header's flex row, pulled back with
 * `margin-left: -.4rem` — which only ever worked because the row had no gap to
 * fight. The header has `gap: .5rem`, so the pull was half a millimetre short
 * of nothing and the badge became its own item in the row: it stood clear of
 * the scroll button, pushed the admin and Leave buttons along, and read as a
 * separate control rather than as a count on that one.
 *
 * Anchored to the button instead, which is what a badge is. Nothing about the
 * header's spacing can move it again. */
.badged { position: relative; display: inline-flex; }

#notif-badge {
  position: absolute; top: -.3rem; right: -.3rem;
  /* Sized from the CONTENT, with a floor: a single digit is a circle and a
     three-digit count stretches into a pill rather than overflowing it. */
  min-width: 1.15rem; height: 1.15rem; padding: 0 .3rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--red); color: #fff; border-radius: 999px;
  font-size: .68rem; font-weight: 700; line-height: 1;
  /* A ring in the header's own colour, so the pill stays legible where it
     overlaps the button's border instead of merging with it. */
  border: 2px solid var(--bg-2);
  /* The button underneath is the target. A badge that swallowed taps would
     make the alerts button dead exactly when there is something to read. */
  pointer-events: none;
}

/* ---- Auth screen --------------------------------------------------------- */
#auth { max-width: 380px; margin: 8vh auto; }
.tabs { display: flex; gap: .4rem; margin-bottom: .8rem; }
.tabs button { flex: 1; }
.tabs button.on { background: var(--gold-dim); color: #17130c; }

/* ---- Stats panel (the ELO replacement) ----------------------------------- */
.stat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .5rem; }
.stat { background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius); padding: .5rem; text-align: center; }
.stat .n { font-size: 1.35rem; color: var(--gold); }
.stat .k { font-size: .72rem; color: var(--ink-dim); }

/* ---- Adventure beats ----------------------------------------------------- */
.beat { margin-bottom: .35rem; }
.beat-narration { color: var(--ink); }
.beat-check, .beat-vote { color: var(--ink-dim); font-size: .9rem; }
.beat-choice { color: var(--gold); }
.beat-xp, .beat-item { color: var(--green); font-size: .9rem; }
.beat-end { color: var(--gold); font-weight: 600; margin-top: .5rem; }

/* A hero's own portrait beside their name. The source is the full-length
   figure the board uses, so the frame crops to the TOP of it — a whole
   standing figure in a 40px circle is a strip with an unreadable face. */
.hero-face {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: 50%;
  object-fit: cover;
  object-position: top center;
  background: #e6dcc4;            /* the parchment the figures are drawn on */
  border: 2px solid #c8a45c;
  margin-right: 10px;
}
