/* Happy School Library — Telegram Mini App design system.
   Inter Tight is loaded via next/font in layout.tsx (CSS var --font-ui-loaded).
   Book titles fall back to system serif. Accent: muted sage green. */

:root {
  /* ── Light theme (Sage palette) ── */
  --bg:           #fbfaf8;
  --bg-secondary: #f1f0ec;
  --card:         #ffffff;
  --text:         #1c1f1d;
  --text-soft:    #4d5651;
  --text-muted:   #8a948f;
  --link:         #3f6f5c;   /* darker sage — AA on --bg */
  --accent:       #5d8c78;
  --accent-text:  #ffffff;
  --accent-soft:  #e7eee9;
  --hairline:     #efeeeb;
  --hairline-strong: #dcdbd7;
  --destructive:  #c2453a;
  --destructive-soft: #fbe9e6;

  --status-available:    #2f7a5e;   /* cooler than --accent so pill doesn't merge */
  --status-available-bg: #e3efe9;
  --status-reserved:     #a06a1f;
  --status-reserved-bg:  #f5ecda;
  --status-issued:       #6b6b6b;
  --status-issued-bg:    #ececea;
  --status-overdue:      #b9362e;
  --status-overdue-bg:   #fbe5e2;

  --font-ui: var(--font-ui-loaded, system-ui), -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-book: 'Charter', 'Iowan Old Style', 'Georgia', 'Times New Roman', serif;

  --text-2xs: 11px;
  --text-xs:  12px;
  --text-sm:  13px;
  --text-base:14px;
  --text-md:  15px;
  --text-lg:  17px;
  --text-xl:  20px;
  --text-2xl: 24px;
  --text-3xl: 28px;

  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;

  --r-sm: 6px; --r-md: 10px; --r-lg: 14px; --r-xl: 18px;
  --hit: 44px;

  /* Height of the fixed-bottom LibraryTabs strip (chip 44px + 8+8 padding).
     Used to lift other bottom-fixed controls (search bars, MainButton fallback)
     above the tabs, and to extend .app-shell padding-bottom so content
     scrolls clear of them. */
  --tabs-h: 60px;
}

[data-theme='dark'] {
  --bg:           #181d22;
  --bg-secondary: #232a30;
  --card:         #1f262c;
  --text:         #e9eceb;
  --text-soft:    #aab2b0;
  --text-muted:   #717977;
  --link:         #8ab9a6;
  --accent:       #76a691;   /* warmer & lighter sage for dark */
  --accent-text:  #0f1614;   /* dark ink on lighter accent */
  --accent-soft:  #29332e;
  --hairline:     #2a3036;   /* ΔRGB ≈ 18 — visible on dark */
  --hairline-strong: #3a4148;
  --destructive:  #e07b6f;
  --destructive-soft: #3a2522;

  --status-available:    #7cc1a4;
  --status-available-bg: #1f3329;
  --status-reserved:     #d4a464;
  --status-reserved-bg:  #322618;
  --status-issued:       #9aa1a3;
  --status-issued-bg:    #262c31;
  --status-overdue:      #e87a72;
  --status-overdue-bg:   #3a2120;
}

* { box-sizing: border-box; -webkit-font-smoothing: antialiased; }
html, body { margin: 0; padding: 0; }

body {
  font-family: var(--font-ui);
  font-feature-settings: 'cv11', 'ss01';
  color: var(--text);
  background: var(--bg);
  font-size: var(--text-md);
  line-height: 1.45;
  letter-spacing: -0.005em;
}

a { color: var(--link); text-decoration: none; }

/* App shell — real Mini App: no fake phone chrome; Telegram provides it.
   In fullscreen mode (Bot API 8.0+) Telegram overlays its own close/minimize
   header on top of our content — pad top by --tg-content-safe-area-inset-top
   so the first row of content isn't covered. Bottom padding leaves room for
   MainButton + iOS home indicator. */
.app-shell {
  max-width: 480px;
  margin: 0 auto;
  /* +70px gap below Telegram's fullscreen close/minimize overlay so the first
     row of content isn't visually touching the buttons. */
  padding-top: calc(70px + var(--tg-content-safe-area-inset-top, 0px));
  padding-right: 16px;
  padding-bottom: calc(var(--tabs-h) + 24px + var(--tg-safe-area-inset-bottom, 0px));
  padding-left: 16px;
  min-height: 100dvh;
}

/* MainButton fallback for desktop web (when Telegram.WebApp.MainButton is unavailable).
   Rendered by <MainButtonBridge /> as a fixed bottom bar. */
.mb-fallback {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--tabs-h) + var(--tg-safe-area-inset-bottom, 0px));
  height: 54px;
  background: var(--accent);
  color: var(--accent-text);
  font: inherit;
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: 0.01em;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  cursor: pointer;
  z-index: 50;
}
.mb-fallback:disabled { background: var(--hairline-strong); color: var(--text-muted); cursor: not-allowed; }

/* Typography helpers */
.t-display { font-size: var(--text-2xl); font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
.t-h1      { font-size: var(--text-xl); font-weight: 600; letter-spacing: -0.015em; }
.t-h2      { font-size: var(--text-lg); font-weight: 600; letter-spacing: -0.01em; }
.t-body    { font-size: var(--text-md); font-weight: 400; }
.t-sm      { font-size: var(--text-sm); font-weight: 400; color: var(--text-soft); }
.t-meta    { font-size: var(--text-xs); font-weight: 500; color: var(--text-muted); letter-spacing: 0.01em; }
.t-label   { font-size: var(--text-xs); font-weight: 600; color: var(--text-muted); letter-spacing: 0.04em; text-transform: uppercase; }
.t-book-title { font-family: var(--font-book); font-weight: 600; letter-spacing: -0.005em; }

.tg-section-header {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 20px 4px 6px;
}

/* Cells & grouped list */
.tg-cell {
  background: var(--card);
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--hit);
  position: relative;
  text-decoration: none;
  color: inherit;
}
.tg-cell + .tg-cell { border-top: 0.5px solid var(--hairline); }
.tg-group {
  background: var(--card);
  border-radius: var(--r-md);
  overflow: hidden;
  border: 0.5px solid var(--hairline);
}

/* Inputs */
.tg-input {
  width: 100%;
  background: var(--card);
  border: 0.5px solid var(--hairline);
  color: var(--text);
  font: inherit;
  font-size: var(--text-md);
  padding: 11px 12px;
  border-radius: var(--r-md);
  outline: none;
  transition: border-color 0.1s;
}
.tg-input:focus { border-color: var(--accent); }
.tg-input::placeholder { color: var(--text-muted); }
textarea.tg-input { resize: vertical; min-height: 96px; line-height: 1.45; }
/* Native select with a custom chevron — matches the .tg-input frame so
   form rows stay visually homogenous. */
select.tg-input {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%238E8E93' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
  cursor: pointer;
}

/* Chips */
.tg-chip-group { display: flex; gap: 6px; flex-wrap: wrap; }
.tg-chip {
  height: 32px;
  padding: 0 12px;
  border-radius: 999px;
  border: 0.5px solid var(--hairline-strong);
  background: transparent;
  color: var(--text-soft);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.tg-chip[data-selected="true"] {
  background: var(--accent);
  color: var(--accent-text);
  border-color: var(--accent);
}

/* Status token */
.tg-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.01em;
}
.tg-status::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  display: inline-block;
}
.tg-status[data-status="available"] { color: var(--status-available); }
.tg-status[data-status="reserved"]  { color: var(--status-reserved); }
.tg-status[data-status="issued"]    { color: var(--status-issued); }
.tg-status[data-status="overdue"]   { color: var(--status-overdue); }

/* Book cover placeholder */
.book-cover {
  border-radius: 4px;
  background: var(--accent-soft);
  flex-shrink: 0;
  position: relative;
  overflow: hidden;
  border: 0.5px solid var(--hairline-strong);
  box-shadow: inset -1px 0 0 rgba(0,0,0,0.04);
}
.book-cover::before {
  content: '';
  position: absolute;
  left: 4px; top: 0; bottom: 0;
  width: 1px;
  background: rgba(0,0,0,0.06);
}
.book-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Stat tile (hero matrix on home) — clickable variant gets tap feedback */
.stat-tile {
  -webkit-tap-highlight-color: transparent;
  transition: background 120ms ease;
}
a.stat-tile:hover { background: var(--accent-soft); }
a.stat-tile:active { background: var(--accent-soft); transform: scale(0.98); }

/* Buttons (non-MainButton, e.g. inline destructive in form bottom) */
.btn {
  border: 0;
  background: var(--accent);
  color: var(--accent-text);
  font: inherit;
  font-size: var(--text-md);
  font-weight: 600;
  padding: 11px 14px;
  border-radius: var(--r-md);
  cursor: pointer;
}
.btn.ghost {
  background: transparent;
  color: var(--text-soft);
  border: 0.5px solid var(--hairline-strong);
}
.btn.destructive {
  background: transparent;
  color: var(--destructive);
  border: 0.5px solid var(--destructive-soft);
}

/* Section / spacing helpers */
.stack > * + * { margin-top: var(--space-3); }
.stack-lg > * + * { margin-top: var(--space-5); }
.row { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.between { display: flex; justify-content: space-between; align-items: center; }
.muted { color: var(--text-muted); }
.center { text-align: center; }

/* ── Reader-side motion ──
   Scoped to main[data-reader] (base.html sets it for non-admin pages);
   the admin console stays static. One easing everywhere — a quick settle. */
:root { --ease-settle: cubic-bezier(0.22, 1, 0.36, 1); }

/* Page transitions: hx-boost swaps <body>, so <main> is fresh on every
   navigation and the entrance replays. Fixed-position descendants
   (#lib-search bar, #filter-sheet) must not sit under a transform, so the
   rise runs on main's direct children, not on main itself. */
main[data-reader] { animation: page-fade 180ms ease-out; }
main[data-reader] > :not(#lib-search):not(#filter-sheet) {
  animation: page-rise 280ms var(--ease-settle);
}
@keyframes page-fade { from { opacity: 0; } }
@keyframes page-rise { from { opacity: 0; transform: translateY(8px); } }

/* Search / filter swaps re-fill #list-region; new results fade in.
   (Infinite-scroll pages append inside #book-list and stay instant.) */
#list-region > * { animation: page-fade 160ms ease-out; }
#waitlist-area > .btn { animation: page-fade 160ms ease-out; }

/* Press feedback */
main[data-reader] .btn,
main[data-reader] .tg-chip,
main[data-reader] ~ nav .tg-chip,
#filter-apply, #filter-reset {
  -webkit-tap-highlight-color: transparent;
  transition: transform 120ms ease, opacity 150ms ease,
              background 140ms ease, color 140ms ease, border-color 140ms ease;
}
main[data-reader] .btn:active,
#filter-apply:active, #filter-reset:active { transform: scale(0.97); }
main[data-reader] .tg-chip:active,
main[data-reader] ~ nav .tg-chip:active { transform: scale(0.95); }

main[data-reader] a.tg-cell {
  -webkit-tap-highlight-color: transparent;
  transition: background 120ms ease;
}
main[data-reader] a.tg-cell:active { background: var(--bg-secondary); }

/* Touch: native-app feel. Covers aren't draggable (and no iOS long-press
   save sheet); rows, buttons and tabs aren't text-selectable on long-press.
   Real text (annotation, titles outside links) stays selectable. */
main[data-reader] img,
main[data-reader] .book-cover {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  user-select: none;
}
main[data-reader] a,
main[data-reader] button,
main[data-reader] ~ nav a {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* Filter bottom sheet: backdrop fades, card slides up; lib.html sets
   data-closing and waits 200ms before display:none, so the reversed
   animations play out on close. */
#filter-sheet { animation: overlay-fade 160ms ease-out; }
#filter-sheet-card { animation: sheet-up 300ms var(--ease-settle); }
#filter-sheet[data-closing] { animation: overlay-fade 180ms ease-in reverse forwards; }
#filter-sheet[data-closing] #filter-sheet-card { animation: sheet-up 200ms ease-in reverse forwards; }
@keyframes overlay-fade { from { opacity: 0; } }
@keyframes sheet-up { from { transform: translateY(24px); opacity: 0.5; } }

/* Reservation confirmed — the one deliberate flourish. */
.reserve-pop { animation: reserve-pop 320ms var(--ease-settle); }
@keyframes reserve-pop {
  0%   { opacity: 0; transform: scale(0.96) translateY(6px); }
  60%  { opacity: 1; transform: scale(1.008); }
  100% { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  main[data-reader],
  main[data-reader] > :not(#lib-search):not(#filter-sheet),
  #list-region > *,
  #waitlist-area > .btn,
  #filter-sheet, #filter-sheet-card,
  #filter-sheet[data-closing], #filter-sheet[data-closing] #filter-sheet-card,
  .reserve-pop { animation: none; }
  main[data-reader] .btn:active,
  main[data-reader] .tg-chip:active,
  main[data-reader] ~ nav .tg-chip:active,
  #filter-apply:active, #filter-reset:active { transform: none; }
}

/* Skeleton */
.skel {
  background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--card) 50%, var(--bg-secondary) 75%);
  background-size: 200% 100%;
  border-radius: var(--r-sm);
  animation: skel-pulse 1.4s ease-in-out infinite;
}
@keyframes skel-pulse { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
