/* Nippo Bold — served from the Fontshare CDN, deliberately NOT vendored into
   this repo. The ITF Free Font License permits self-hosting on your own site
   but prohibits distributing the font file through a public repository, and
   this repo is public. Loading from Fontshare's own CDN is the route the
   licence explicitly endorses. The service worker caches it for offline use.

   If Fontshare ever rotates this URL the app degrades to the system font
   rather than breaking — that is what font-display: swap and the fallback
   stack below are for. */
@font-face {
  font-family: 'Nippo';
  src: url('https://cdn.fontshare.com/wf/AFAHDMOVBCROSSGE5GOSMLJMR75FYHZP/MX7VPGBDFGT7ERCST2IAA4LH5KO7BZNK/B3C3BZREKEN22Q6DYVZUXV3W4RJM63VW.woff2') format('woff2'),
       url('https://cdn.fontshare.com/wf/AFAHDMOVBCROSSGE5GOSMLJMR75FYHZP/MX7VPGBDFGT7ERCST2IAA4LH5KO7BZNK/B3C3BZREKEN22Q6DYVZUXV3W4RJM63VW.woff') format('woff');
  font-weight: 700;
  font-display: swap;
  font-style: normal;
}

/* ── Tokens ──────────────────────────────────────────────────────────── */
:root {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #eceef2;
  --text: #12141a;
  --muted: #6b7280;
  --line: #e2e5ea;
  --accent: #ff6b35;
  --accent-ink: #ffffff;
  --gold: #f0a020;
  --danger: #e5484d;
  --shadow: 0 1px 2px rgba(16, 20, 30, .06), 0 6px 16px rgba(16, 20, 30, .06);

  --hm-0: #e6e9ee;
  --hm-1: #ffd2bf;
  --hm-2: #ffab88;
  --hm-3: #ff8552;
  --hm-4: #ff6b35;

  /* Nippo carries the display type; small UI text stays on the system font,
     which is more legible at 11-14px than a geometric display face. */
  --font-display: 'Nippo', -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;

  /* Zero by default. In a browser tab, Safari's own toolbars already reserve
     the unsafe areas, so adding env() insets on top reserves them twice and
     leaves a dead gap above the URL bar. Only a standalone app paints under
     the system UI and genuinely needs them. */
  --safe-t: 0px;
  --safe-b: 0px;
  --tabbar-h: 56px;
}

/* JS sets .is-standalone from navigator.standalone as well as the media query,
   because iOS Safari's support for display-mode has been unreliable. Either
   route turning it on is enough. */
:root.is-standalone,
:root:is(.is-standalone) {
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
}
@media (display-mode: standalone) {
  :root {
    --safe-t: env(safe-area-inset-top, 0px);
    --safe-b: env(safe-area-inset-bottom, 0px);
  }
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0e1014;
    --surface: #181b22;
    --surface-2: #22262f;
    --text: #f2f4f8;
    --muted: #8b93a3;
    --line: #2a2f39;
    --accent: #ff7a45;
    --gold: #ffbe4d;
    --danger: #ff6369;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 16px rgba(0, 0, 0, .3);

    --hm-0: #22262f;
    --hm-1: #5c3324;
    --hm-2: #94492a;
    --hm-3: #cc5f33;
    --hm-4: #ff7a45;
  }
}

/* ── Base ────────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }

html {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  margin: 0;
  overflow: hidden;              /* the page never scrolls; only inner regions do */
  overscroll-behavior: none;

  /* --app-height comes from visualViewport, the only measurement that tracks
     what is ACTUALLY visible. 100dvh is wrong here: it resolves to the largest
     viewport (toolbars hidden), so the layout runs behind Safari's bottom bar
     and Chrome's top bar. It stays as the pre-JS fallback only.

     position:fixed pins the app to the viewport so no amount of iOS toolbar
     animation can scroll the header out of view. */
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--app-height, 100dvh);

  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.45 -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

button, input, textarea { font: inherit; color: inherit; }

button {
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  cursor: pointer;
  border: 0;
  background: none;
}

h1, h2, p, ul { margin: 0; }
ul { list-style: none; padding: 0; }

.muted { color: var(--muted); font-size: 14px; }

/* ── View plumbing ───────────────────────────────────────────────────── */
/* Each view is a fixed header + a flexible body. min-height:0 on the flex
   children is what actually lets the inner scrollers shrink instead of
   pushing the layout past the viewport. */
.views { flex: 1 1 auto; min-height: 0; }

.view { display: none; flex-direction: column; height: 100%; min-height: 0; }
.view.is-active { display: flex; }

.topbar { flex: 0 0 auto; padding: calc(var(--safe-t) + 8px) 20px 4px; }
.topbar h1 { font-family: var(--font-display); font-size: 27px; font-weight: 700; letter-spacing: -.01em; }
.topbar-sub { color: var(--muted); font-size: 13px; margin-top: 1px; }

.body-flex {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 0 20px 8px;
}

.inner-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Settings is the one screen allowed to scroll as a whole. */
.scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px 20px 20px;
}

/* ── Progress ring ───────────────────────────────────────────────────── */
.ring-wrap {
  position: relative;
  flex: 0 1 auto;
  width: min(41vw, 168px);
  height: min(41vw, 168px);
  margin: 0 auto;
}
.ring { width: 100%; height: 100%; transform: rotate(-90deg); }
.ring circle { fill: none; stroke-width: 15; stroke-linecap: round; }
.ring-track { stroke: var(--surface-2); }
.ring-fill, .ring-over {
  stroke-dasharray: 540.35;      /* 2 * pi * 86 */
  stroke-dashoffset: 540.35;
  transition: stroke-dashoffset .45s cubic-bezier(.22, 1, .36, 1);
}
.ring-fill { stroke: var(--accent); }
.ring-over { stroke: var(--gold); }

.ring-label {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1px;
}
.ring-total {
  font-family: var(--font-display);
  font-size: 52px; font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; line-height: 1;
}
.ring-goal { color: var(--muted); font-size: 13px; }

.goal-note {
  flex: 0 0 auto;
  text-align: center; font-size: 13px; color: var(--muted);
  min-height: 16px; margin: 4px 0 6px;
}
.goal-note.is-hit { color: var(--gold); font-weight: 600; }

/* ── Set list ────────────────────────────────────────────────────────── */
.sets { display: flex; flex-direction: column; gap: 6px; }

.set-row {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface);
  border-radius: 12px;
  padding: 9px 12px;
  box-shadow: var(--shadow);
  animation: pop .25s cubic-bezier(.22, 1, .36, 1);
}
@keyframes pop {
  from { opacity: 0; transform: translateY(-6px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

/* The row body is the edit target; the × stays a separate quick action. */
.set-main {
  flex: 1 1 auto; display: flex; align-items: center; gap: 10px;
  background: none; padding: 0; text-align: left; min-width: 0;
}
.set-reps { font-family: var(--font-display); font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.set-time { color: var(--muted); font-size: 13px; margin-left: auto; font-variant-numeric: tabular-nums; }
.set-edit-hint { color: var(--muted); font-size: 13px; opacity: .5; }

.set-del {
  width: 27px; height: 27px; flex: 0 0 auto;
  border-radius: 50%;
  background: var(--surface-2); color: var(--muted);
  font-size: 16px; line-height: 1;
  display: grid; place-items: center;
}
.set-del:active { background: var(--danger); color: #fff; }

.empty { text-align: center; padding: 18px 20px; }
.empty-title { font-family: var(--font-display); font-weight: 700; margin-bottom: 3px; font-size: 15px; }
.empty-sub { color: var(--muted); font-size: 13px; }
.empty[hidden] { display: none; }

/* ── Quick add ───────────────────────────────────────────────────────── */
.quickadd { flex: 0 0 auto; padding: 4px 20px 8px; }

.qa-primary {
  width: 100%;
  background: var(--accent); color: var(--accent-ink);
  border-radius: 16px;
  padding: 17px 0;
  font-family: var(--font-display);
  font-size: 28px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  box-shadow: var(--shadow);
  transition: transform .1s ease;
}
.qa-primary:active { transform: scale(.97); }

.btn-custom {
  width: 100%; margin-top: 6px;
  padding: 10px; border-radius: 13px;
  background: var(--surface); color: var(--text);
  font-weight: 600; font-size: 15px;
  box-shadow: var(--shadow);
}
.btn-custom:active { background: var(--surface-2); }

/* ── Cards, stats ────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border-radius: 15px;
  padding: 14px;
  margin-bottom: 10px;
  box-shadow: var(--shadow);
}
.card-tight { padding: 12px 12px 8px; flex: 0 0 auto; }
.card-fill {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  margin-bottom: 0;
}
.card-title { font-family: var(--font-display); font-size: 15px; font-weight: 700; margin-bottom: 4px; }
.card-fill .card-title { flex: 0 0 auto; margin-bottom: 8px; }

.stats {
  flex: 0 0 auto;
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 7px; margin-bottom: 10px;
}
.stat {
  background: var(--surface); border-radius: 13px;
  padding: 10px 6px; text-align: center;
  box-shadow: var(--shadow);
}
.stat-value {
  display: block; font-family: var(--font-display);
  font-size: 21px; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
.stat-label { display: block; color: var(--muted); font-size: 11px; margin-top: 1px; }

/* ── Heatmap ─────────────────────────────────────────────────────────── */
/* No horizontal scroll: the columns are fractions of the available width, so
   the whole 26 weeks always fits. The 3px padding is what stops the selected
   square's outline being clipped at the edges — an overflow container would
   crop it on every side, which is what a scrolling heatmap used to do. */
.heatmap-scroll { padding: 5px; }
.heatmap {
  display: grid; grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr);
  grid-template-columns: repeat(var(--weeks, 26), 1fr);
  gap: 2px;
}
.sq {
  width: auto; aspect-ratio: 1;
  border-radius: 2px; background: var(--hm-0);
  display: block; padding: 0; min-width: 0;
}
.sq.lvl-1 { background: var(--hm-1); }
.sq.lvl-2 { background: var(--hm-2); }
.sq.lvl-3 { background: var(--hm-3); }
.sq.lvl-4 { background: var(--hm-4); }
.sq.is-future { background: transparent; }
.sq.is-selected { outline: 2px solid var(--text); outline-offset: 1px; border-radius: 3px; }

/* ── Forms ───────────────────────────────────────────────────────────── */
.field-label {
  display: block; font-size: 13px; font-weight: 600;
  color: var(--muted); margin-top: 14px;
}
.sheet .field-label:first-of-type { margin-top: 12px; }

.stepper { display: flex; align-items: center; gap: 9px; margin-top: 10px; }
.stepper input {
  flex: 1 1 auto; min-width: 0; text-align: center;
  font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 12px; padding: 9px;
  -moz-appearance: textfield;
}
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper.big { margin-top: 8px; }
.stepper.big input { font-family: var(--font-display); font-size: 30px; padding: 12px; }

.step {
  width: 46px; height: 46px; flex: 0 0 auto;
  border-radius: 12px; background: var(--surface-2);
  font-size: 24px; font-weight: 600; line-height: 1;
}
.step:active { background: var(--accent); color: var(--accent-ink); }

.when-row { display: flex; gap: 8px; margin-top: 8px; }
.when-row input {
  flex: 1 1 0; min-width: 0;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 12px; padding: 11px 10px;
  font-size: 15px; font-variant-numeric: tabular-nums;
}

.btn-row { display: flex; gap: 8px; margin-top: 12px; }
.btn {
  flex: 1 1 0; padding: 12px 8px; border-radius: 12px;
  background: var(--surface-2); font-weight: 600; font-size: 15px;
}
.btn:active { opacity: .7; }
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-danger { background: transparent; color: var(--danger); }
.btn[hidden] { display: none; }

.note { font-size: 13px; margin-top: 10px; min-height: 18px; color: var(--muted); }
.note.is-ok { color: var(--accent); }
.note.is-err { color: var(--danger); }
.storage-line { font-size: 12px; margin-top: 6px; }
.backup-stale { color: var(--gold); font-weight: 600; }

textarea {
  width: 100%; margin-top: 12px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 12px; padding: 10px;
  font-size: 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  resize: vertical;
}

/* ── Tab bar ─────────────────────────────────────────────────────────── */
/* Part of the body flex column rather than position:fixed, so the views
   above get an exact remaining height to divide up. */
.tabbar {
  flex: 0 0 auto;
  height: calc(var(--tabbar-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  display: grid; grid-template-columns: repeat(3, 1fr);
  background: var(--surface);
  border-top: 1px solid var(--line);
}
.tab {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 3px;
  color: var(--muted); font-size: 11px; font-weight: 600;
}
.tab svg {
  width: 21px; height: 21px; fill: none; stroke: currentColor;
  stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
}
.tab.is-active { color: var(--accent); }

/* ── Sheets & toast ──────────────────────────────────────────────────── */
.sheet-backdrop {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, .45);
  display: flex; align-items: flex-end;
  z-index: 40; animation: fade .18s ease;
}
.sheet-backdrop[hidden] { display: none; }
@keyframes fade { from { opacity: 0 } to { opacity: 1 } }

.sheet {
  width: 100%; background: var(--surface);
  border-radius: 20px 20px 0 0;
  padding: 18px 20px calc(18px + var(--safe-b));
  max-height: 90dvh; overflow-y: auto;
  animation: rise .26s cubic-bezier(.22, 1, .36, 1);
}
@keyframes rise { from { transform: translateY(100%) } to { transform: none } }
.sheet-title { font-family: var(--font-display); font-size: 18px; font-weight: 700; }

.toast {
  position: fixed; left: 16px; right: 16px;
  bottom: calc(var(--tabbar-h) + var(--safe-b) + 12px);
  background: var(--text); color: var(--bg);
  border-radius: 14px; padding: 12px 16px;
  display: flex; align-items: center; gap: 12px;
  font-size: 14px; z-index: 30; box-shadow: var(--shadow);
  animation: rise .22s cubic-bezier(.22, 1, .36, 1);
}
.toast[hidden] { display: none; }
.toast button { margin-left: auto; color: var(--accent); font-weight: 700; font-size: 14px; }

/* Short screens (SE, or Safari with both toolbars showing): shrink the ring
   rather than the list, so five sets stay visible instead of four. The counter
   stays large because it is the thing you actually read. */
@media (max-height: 730px) {
  .ring-wrap { width: min(32vw, 124px); height: min(32vw, 124px); }
  .ring circle { stroke-width: 13; }
  .ring-total { font-size: 40px; }
  .ring-goal { font-size: 12px; }
  .qa-primary { padding: 14px 0; font-size: 25px; }
  .topbar h1 { font-size: 24px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
