/* Win95 "Tàng Thư", remastered — shared primitives for every page.
   One deliberate visual world: grey system chrome on a teal desktop. The world
   is kept exactly; the execution is raised — one type system, a 4px spacing
   grid, pixel-exact bevels, and motion only where it explains something.
   Windows and dialogs: window-chrome.css. Page rules: home.css (/), pages.css
   (/chat /admin /guide), reader.css (/read), shell.css (taskbar, Start menu,
   welcome, loaders — every page). */
:root {
  /* System palette (Win95, unchanged) */
  --face: #c0c0c0; --light: #fff; --hilite: #dfdfdf; --shadow: #808080; --dark: #000;
  --title-a: #000080; --title-b: #1084d0; --desktop: #008080;
  --paper: #fff; --text: #0a0a0a; --sel: #000080; --sel-text: #fff;
  --muted: #464b50;       /* secondary text: 4.8:1 on --face, 8.8:1 on --paper */
  --text-2: #262626;      /* body copy in wells and tips, a step softer than --text */
  --sel-muted: #c8d4ff;   /* secondary text on navy (title bars, a highlighted item) */
  --hint: #6b7075;        /* placeholders: 5:1 on --paper, still lighter than --muted */
  --danger: #a00000; --tip-bg: #ffffe1;   /* tooltip / "Did you know" yellow */
  --cover-shadow: 0 0 0 1px var(--dark), 3px 3px 0 rgba(0,0,0,.3);
  /* Book cloth: shelf spines and the jackets that stand in for missing covers. */
  --cloth-0: #7a3b2e; --cloth-1: #2e5a7a; --cloth-2: #3f6b3a; --cloth-3: #7a6a2e;
  --cloth-4: #5a3f7a; --cloth-5: #7a4f2e; --cloth-6: #2e6b6b; --cloth-7: #6b2e4a;
  --gilt: #e6cf8b;

  /* Type: VT323 is display only; Be Vietnam Pro is what you read and click. */
  --font-display: "VT323", "Courier New", monospace;
  --font-ui: "Be Vietnam Pro", Tahoma, "Segoe UI", system-ui, sans-serif;
  --font-body: var(--font-ui);
  --font-book: "Literata", Georgia, "Times New Roman", serif;
  --t-xs: 12px; --t-sm: 13px; --t-md: 14px; --t-lg: 16px;
  --d-sm: 18px; --d-md: 22px; --d-lg: 28px; --d-xl: 40px;   /* display (VT323) sizes */

  /* Spacing: 4px grid */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px;
  --tap: 28px;   /* min control height; grows on touch */

  /* Bevels */
  --bevel-out: inset -1px -1px var(--dark), inset 1px 1px var(--light), inset -2px -2px var(--shadow), inset 2px 2px var(--hilite);
  --bevel-in: inset -1px -1px var(--light), inset 1px 1px var(--dark), inset -2px -2px var(--hilite), inset 2px 2px var(--shadow);
  --bevel-field: inset -1px -1px var(--light), inset 1px 1px var(--shadow), inset -2px -2px var(--hilite), inset 2px 2px var(--dark);
  --bevel-window: inset -1px -1px var(--dark), inset 1px 1px var(--hilite), inset -2px -2px var(--shadow), inset 2px 2px var(--light);
  --bevel-thin: inset -1px -1px var(--shadow), inset 1px 1px var(--light);
  --bevel-thin-in: inset -1px -1px var(--light), inset 1px 1px var(--shadow);
  --dither: repeating-conic-gradient(var(--light) 0 25%, var(--face) 0 50%) 0 0 / 2px 2px;

  --taskbar-h: 34px;
  --safe-b: env(safe-area-inset-bottom, 0px);

  /* Legacy aliases still referenced by module CSS / the reader stage. */
  --bg: var(--paper); --line: var(--shadow); --chip: var(--face); --accent: var(--sel);
}
/* Touch: 40px targets; a tablet's taskbar grows to hold them (phones get the bottom nav below). */
@media (pointer: coarse) { :root { --tap: 40px; --taskbar-h: 48px; } }
@media (max-width: 640px) { :root { --taskbar-h: 56px; } }
/* A phone on its side (short + touch, wider than a phone upright) also gets the bottom
   nav, one slim row with each word beside its icon: height is what it is short of. */
@media (max-height: 500px) and (pointer: coarse) and (min-width: 641px) { :root { --taskbar-h: 40px; } }

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--desktop); color: var(--text);
  font: 400 var(--t-md)/1.5 var(--font-body);
  -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%;
  padding-bottom: calc(var(--taskbar-h) + var(--safe-b));
}
a { color: var(--sel); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }
button, input, select, textarea { font: inherit; color: inherit; }
::selection { background: var(--sel); color: var(--sel-text); }
h1, h2, h3 { text-wrap: balance; }
/* Read aloud, not shown: a heading the window already shows another way. */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ===== Buttons =====
   --py/--px drive padding so :active can shift the label 1px down-right —
   the authentic Win95 press, not a transform on the whole control. */
.btn, .kind-btn, .pager-btn, .chip.list-chip, .lists-item-btn,
.login-user, .kindle-pick, .kindle-del, .kindle-actions button, .lists-clear-btn,
.toc-close, .tbtn, #login-submit, #login-cancel {
  --py: 5px; --px: 14px;
  background: var(--face); color: var(--text); border: 0; border-radius: 0; cursor: pointer;
  box-shadow: var(--bevel-out);
}
.btn, .kind-btn, .pager-btn, .chip.list-chip, .lists-item-btn, .login-user,
.kindle-pick, .kindle-del, .kindle-actions button, .lists-clear-btn,
#login-submit, #login-cancel {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: var(--tap); padding: var(--py) var(--px);
  font: 500 var(--t-sm)/1.2 var(--font-ui); white-space: nowrap; text-decoration: none;
}
.btn:hover { text-decoration: none; }
.btn:active, .kind-btn:active, .pager-btn:active, .tb:active,
.chip.list-chip:active, .lists-item-btn:active, .login-user:active, .kindle-pick:active,
.kindle-actions button:active, #login-submit:active, #login-cancel:active, .tbtn:active,
.kind-btn.active, .pager-btn.active, .tb[aria-pressed="true"], .lists-item-btn.active,
.shelf-fav-btn.active {
  box-shadow: var(--bevel-in);
}
:is(.btn, .kind-btn, .pager-btn, .chip.list-chip, .lists-item-btn, .login-user,
    .kindle-pick, .kindle-actions button, #login-submit, #login-cancel):active:not(:disabled) {
  padding: calc(var(--py) + 1px) calc(var(--px) - 1px) calc(var(--py) - 1px) calc(var(--px) + 1px);
}
/* Dither = "toggled on" (Win95 toolbar latch). */
.kind-btn.active, .pager-btn.active, .tb[aria-pressed="true"], .lists-item-btn.active, .shelf-fav-btn.active {
  background: var(--dither);
}
/* Default button: the extra black ring Win95 draws around the Enter action. */
.btn-primary, #login-submit {
  box-shadow: 0 0 0 1px var(--dark), var(--bevel-out); font-weight: 600;
}
.btn-primary:active, #login-submit:active { box-shadow: 0 0 0 1px var(--dark), var(--bevel-in); }
:is(.btn, .pager-btn):disabled {
  color: var(--shadow); text-shadow: 1px 1px var(--light); cursor: default;
}
/* Focus: the dotted rectangle inside the control, as Win95 drew it. */
:where(button, a, [tabindex]):focus-visible { outline: 1px dotted var(--dark); outline-offset: -4px; }
:where(input, select, textarea):focus-visible { outline: 2px solid var(--sel); outline-offset: 1px; }

/* ===== Fields ===== */
input[type="text"], input[type="search"], input[type="url"], input[type="password"], input:not([type]), select, textarea {
  background: var(--paper); border: 0; border-radius: 0; box-shadow: var(--bevel-field);
}
input[type="text"], input[type="search"], input[type="url"], input[type="password"], input:not([type]), select, textarea {
  min-height: var(--tap); padding: 4px 8px; font: 400 var(--t-md)/1.3 var(--font-ui);
}
input::placeholder, textarea::placeholder { color: var(--hint); }
input[type="search"]::-webkit-search-cancel-button { cursor: pointer; }
select {
  appearance: none; -webkit-appearance: none; padding-right: 26px; cursor: pointer; font-size: var(--t-sm);
  background: var(--paper) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='18' shape-rendering='crispEdges'%3E%3Crect width='16' height='18' fill='%23c0c0c0'/%3E%3Cpath d='M0 17.5h16M15.5 0v18' stroke='%23000'/%3E%3Cpath d='M1 1.5h14M1.5 1v16' stroke='%23fff'/%3E%3Cpath d='M1 16.5h14M14.5 1v16' stroke='%23808080'/%3E%3Cpath d='M4 7h7v1H4zM5 8h5v1H5zM6 9h3v1H6zM7 10h1v1H7z' fill='%23000'/%3E%3C/svg%3E") no-repeat right 2px center / 16px calc(100% - 4px);
}
/* Touch: under 16px, iOS Safari zooms the page when a field takes focus. */
@media (pointer: coarse) {
  input[type="text"], input[type="search"], input[type="url"], input[type="password"], input:not([type]), select, textarea { font-size: 16px; }
}

/* ===== Book covers: real art, or a cloth jacket stamped in gilt (cover-ui.js) =====
   A jacket is a container: its title scales with the jacket (cqi), and below
   96px wide only a monogram initial is stamped — the title is always printed
   as text right beside the cover, so a tiny jacket need not repeat it. */
div.jacket {
  --cloth: var(--cloth-0);
  container-type: inline-size; position: relative; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0; text-align: center; color: var(--gilt);   /* spacing lives on children in cqi: % here would follow the parent */
  background:
    linear-gradient(90deg, rgba(0,0,0,.28) 0 5%, rgba(255,255,255,.14) 5% 6.5%, transparent 6.5%),
    repeating-linear-gradient(45deg, rgba(255,255,255,.035) 0 1px, transparent 1px 3px),
    var(--cloth);
}
div.jacket::before {   /* gilt rule framing the stamp */
  content: ""; position: absolute; inset: 8% 8% 8% 13%; border: 1px solid rgba(230,207,139,.55); pointer-events: none;
}
.jacket.c1 { --cloth: var(--cloth-1); } .jacket.c2 { --cloth: var(--cloth-2); } .jacket.c3 { --cloth: var(--cloth-3); }
.jacket.c4 { --cloth: var(--cloth-4); } .jacket.c5 { --cloth: var(--cloth-5); } .jacket.c6 { --cloth: var(--cloth-6); }
.jacket.c7 { --cloth: var(--cloth-7); }
.j-title {
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden;
  margin: 0 12cqi 0 16cqi; font: 600 11cqi/1.2 var(--font-book); text-wrap: balance; overflow-wrap: anywhere;
  text-shadow: 0 1px 0 rgba(0,0,0,.45);
}
.j-author {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin: 7cqi 12cqi 0 16cqi; font: 500 7.5cqi/1.25 var(--font-ui); letter-spacing: .04em; text-transform: uppercase; opacity: .8;
}
.j-mono { display: none; margin-left: 4cqi; font: italic 400 46cqi/1 var(--font-book); text-shadow: 0 1px 0 rgba(0,0,0,.45); }
@container (max-width: 95px) {
  .j-mono { display: block; }
  .j-title, .j-author { display: none; }
}

/* ===== Notice (empty result, load failure): icon + message in a sunken well ===== */
.notice95 {
  display: flex; gap: var(--s4); align-items: flex-start; max-width: 560px; margin: var(--s6) auto; padding: var(--s4) var(--s5);
  background: var(--paper); box-shadow: var(--bevel-field); grid-column: 1 / -1;
}
.notice95 > img { width: 32px; height: 32px; flex: none; image-rendering: pixelated; }
.notice95 h3 { margin: 2px 0 var(--s1); font: 600 var(--t-lg)/1.3 var(--font-ui); }
.notice95 p { margin: 0 0 var(--s3); color: var(--text-2); line-height: 1.55; }
.notice95 .notice-actions { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0; }

/* A button that reads as a link (author names, "Đăng nhập" in running text). */
.linkish { background: none; border: 0; padding: 0; color: var(--sel); cursor: pointer; font: inherit; text-align: left; }
.linkish:hover { text-decoration: underline; text-underline-offset: 2px; }
.btn img { width: 16px; height: 16px; flex: none; image-rendering: pixelated; }
.dlg-title img { width: 16px; height: 16px; flex: none; image-rendering: pixelated; }
.dlg-title-text { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* ===== Motion preference ===== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; scroll-behavior: auto !important; }
}
