/* Shared theme for the static pages (board, builds, admin*, error). The planner
   (src/styles.css) stays self-contained on purpose, since planner-standalone.html
   has to work with no server behind it to link this file from. Keep the token
   names in sync with src/styles.css so the whole site reads as one system. */

:root {
  --void: #0a0a0d;
  --deep: #111114;
  --panel: #16161a;
  --edge: #27272e;
  --glow: #6e8bff;
  --hot: #8aa2ff;
  --lume: #e0b34a;
  --ink: #eaeaef;
  --dim: #8a8a94;
  --ok: #4fd68a;
  --bad: #ff5c5c;

  /* The seven damage types, the same hex values src/styles.css carries. The
     palette is duplicated on purpose, because planner-standalone.html has to
     render with no server to link a stylesheet from, and csscheck holds the two
     copies together. These were missing here, so every element name on /bosses
     drew in plain text and the .dt classes did nothing at all. */
  --dt-physical: #b9b9c4;
  --dt-fire: #ff9a4d;
  --dt-frost: #6fd0ff;
  --dt-electric: #ffd84d;
  --dt-luminous: #fff0b0;
  --dt-shadow: #c99aff;
  --dt-poison: #ff7ad1;

  /* How wide the content column gets, and there are two answers because the
     pages hold two different things. A grid of cards or a table wants room; a
     column of prose wants a line you can get back to the start of.

     Written down as tokens because the six pages that use .wrap had drifted to
     four different widths: the planner ran to 2040px, Builds to 1600, the two
     admin pages to 1200, and Feedback and Bosses inherited 900 from this file
     by simply never setting one. Bosses is a grid of 32 cards and was the one
     that suffered, at three columns where it had room for seven. Nothing said
     so, because the width a page ends up at is invisible unless you go looking
     for the rule that is missing. (The error page is the exception and needs
     neither token: it centres one 520px box.) */
  --w-page: min(2040px, 94vw);
  --w-read: min(1180px, 94vw);
}

* { box-sizing: border-box; }
html, body { margin: 0; background: var(--void); }
body { color: var(--ink); font-family: "Inter", system-ui, sans-serif; line-height: 1.5;
  padding: 16px 16px 60px; }
/* Every page picks one of the two deliberately. There is no default worth
   having: a page that forgets is exactly how this drifted the first time. */
.wrap { max-width: var(--w-page); margin: 0 auto; }
.wrap.read { max-width: var(--w-read); }
a { color: var(--glow); }

/* ---- top nav, the same on every page ---- */
.nav { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
.nav a, .nav span.here { font-size: 12.5px; font-weight: 600; text-decoration: none; padding: 8px 13px;
  border-radius: 9px; border: 1px solid var(--edge); background: var(--panel); color: var(--dim); }
.nav a:hover { color: var(--ink); border-color: var(--glow); }
.nav span.here { background: var(--deep); color: var(--ink); border-color: var(--glow); }
.nav .sp { flex: 1; }

h1 { font-size: clamp(22px, 5vw, 30px); margin: 0 0 4px; letter-spacing: -.02em; font-weight: 700; }
h1 em { font-style: normal; color: var(--glow); }
.sub { color: var(--dim); font-size: 13.5px; margin: 0 0 18px; }
.sub a { color: var(--glow); }

/* ---- cards, the base surface everything else sits on ---- */
.card { background: var(--panel); border: 1px solid var(--edge); border-radius: 12px;
  padding: 14px 15px; margin-bottom: 10px; }
.row { display: flex; gap: 12px; align-items: flex-start; }
.cards { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 20px; }
.cards .card, .card.stat { padding: 12px 16px; margin-bottom: 0; }
.card .k { font-family: ui-monospace, monospace; font-size: 9px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--dim); }
.card .v { font-family: ui-monospace, monospace; font-size: 20px; font-weight: 700; }

/* ---- buttons ---- */
button, .btn { font-family: inherit; cursor: pointer; border-radius: 8px; font-size: 12.5px; }
.primary { background: var(--glow); color: #0a0a0d; border: none; padding: 9px 15px; font-weight: 600; }
.primary:hover { background: var(--hot); }
.ghost { background: transparent; color: var(--dim); border: 1px solid var(--edge); padding: 8px 12px; }
.ghost:hover { color: var(--ink); border-color: var(--glow); }
.ghost.on { border-color: var(--glow); color: var(--ink); background: var(--deep); }
.danger { background: transparent; color: var(--bad); border: 1px solid #3a2226; padding: 8px 13px; }
.danger:hover { background: #3a2226; color: #fff; }
.mini { width: 24px; height: 24px; padding: 0; background: var(--deep); color: var(--ink);
  border: 1px solid var(--edge); font-size: 13px; line-height: 1; border-radius: 7px; }
.mini:hover { border-color: var(--glow); color: var(--glow); }

/* ---- pills, tags, statuses ---- */
.pill { font-family: ui-monospace, monospace; font-size: 9.5px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; padding: 3px 8px; border-radius: 4px; background: #232c42; color: #9fc0ff; }
.tag { font-size: 10.5px; font-family: ui-monospace, monospace; letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 20px; border: 1px solid var(--edge); color: var(--dim); }
.kind { font-family: ui-monospace, monospace; font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 4px; background: #232c42; color: #9fc0ff; }
.kind.bug { background: #3a2226; color: #ffb4b4; }
.kind.idea { background: #223026; color: #a8e6c4; }
.st { font-size: 10.5px; font-family: ui-monospace, monospace; letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 20px; font-weight: 700; }
.st.open { background: rgba(138, 138, 148, .16); color: var(--dim); }
.st.lookingatit { background: rgba(110, 139, 255, .16); color: #a9b8ff; }
.st.planned { background: rgba(224, 179, 74, .16); color: var(--lume); }
.st.done { background: rgba(79, 214, 138, .16); color: var(--ok); }
.st.declined { background: rgba(255, 92, 92, .14); color: #ffb4b4; }

.muted { color: var(--dim); font-size: 12px; }
.empty { color: var(--dim); text-align: center; padding: 34px 0; }

/* ---- forms ---- */
/* Native controls follow this: the select popup, the scrollbars, the date and
   file pickers. Without it Windows draws a white list with a blue highlight over
   a black page, and no amount of styling the closed control changes that, since
   the open list is the OS drawing it rather than us. */
:root { color-scheme: dark; }

input.txt, textarea, select { font-family: inherit; font-size: 13.5px; background: var(--deep);
  color: var(--ink); border: 1px solid var(--edge); border-radius: 9px; padding: 9px 11px; width: 100%; }
textarea { min-height: 90px; }
label.fl { display: block; font-family: ui-monospace, monospace; font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--dim); margin: 12px 0 5px; }
select:hover { border-color: var(--glow); }

/* ---- asking a question ----
   Drawn to match the planner's, which carries its own copy in src/styles.css for
   the same reason the palette is duplicated there. public/dialog.js is what puts
   this on the page; the two are a pair and neither is any use alone. */
.modal { position: fixed; inset: 0; background: rgba(0, 0, 0, .7); display: grid;
  place-items: center; padding: 18px; z-index: 60; overflow-y: auto; }
.sheet { background: var(--panel); border: 1px solid var(--edge); border-radius: 14px;
  padding: 18px; width: 100%; max-height: calc(100vh - 36px); overflow-y: auto; }
.sheet.dlg { max-width: 430px; }
.sheet.dlg h3 { margin: 0 0 7px; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.dlgbody { color: var(--dim); font-size: 13.5px; line-height: 1.5; margin: 0; }

/* What is about to be deleted, shown rather than described. The admin page used
   to paste an excerpt into the confirm() message with blank lines around it,
   because that was the only place a native dialog had to put it. */
.dlgquote { margin: 12px 0 0; padding: 9px 12px; border-left: 2px solid var(--edge);
  background: var(--deep); border-radius: 0 8px 8px 0; color: var(--dim);
  font-size: 12.5px; line-height: 1.5; overflow-wrap: break-word; }

.dlgfoot { display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px; }
.dlgfoot button { padding: 9px 15px; font-size: 13px; }

/* ---- toast ---- */
.toast { position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); background: var(--glow);
  color: #0a0a0d; font-weight: 700; font-size: 13px; padding: 11px 20px; border-radius: 22px; z-index: 50; }

/* ---- micro-heading, used above a block of controls ---- */
h2 { font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
  font-family: ui-monospace, monospace; margin: 22px 0 10px; padding-bottom: 7px;
  border-bottom: 1px solid var(--edge); }

.warnbar { border: 1px solid var(--lume); color: var(--lume); border-radius: 10px; padding: 10px 14px;
  font-size: 13px; margin-bottom: 18px; background: rgba(224, 179, 74, .08); }

.hint { color: var(--dim); font-size: 11.5px; margin: 9px 0 0; }

.spacer { flex: 1; }

/* ---- site footer ----
   Carries the wiki credit, which is a licence obligation rather than a courtesy:
   the upgrade text and every icon came from there under CC BY-SA 4.0, and until
   now that was only recorded in the README, which nobody visiting the site can
   see. The "not affiliated" line is here for the same reason, so nobody reads a
   tier list as something the game's authors published. */
.sitefoot { margin-top: 36px; padding-top: 18px; border-top: 1px solid var(--edge);
  color: var(--dim); font-size: 12.5px; }
.sitefoot .fnav { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
.sitefoot .fnav a { color: var(--dim); text-decoration: none; font-weight: 600; }
.sitefoot .fnav a:hover { color: var(--ink); }
.sitefoot p { margin: 0 0 7px; max-width: 92ch; }
.sitefoot b { color: var(--ink); font-weight: 600; }
.sitefoot a { color: var(--glow); }
.sitefoot .fine { font-size: 11.5px; line-height: 1.6; }

/* ---- scrollbars ----
   The default Windows scrollbar is a light grey slab that sits next to a near
   black page and reads as a rendering fault. These are the same graphite and
   indigo as everything else, sized so they are still easy to grab.

   Firefox only takes the two-keyword form, so it is set alongside rather than
   instead of the WebKit rules. */
* { scrollbar-width: thin; scrollbar-color: var(--edge) transparent; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--edge); border-radius: 7px;
  border: 3px solid var(--void); }
::-webkit-scrollbar-thumb:hover { background: #3a3a45; }
::-webkit-scrollbar-thumb:active { background: var(--glow); }
::-webkit-scrollbar-corner { background: transparent; }

/* Anchor links and back-to-top land softly, unless the reader has asked for no
   motion, in which case they jump as before. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* A scroll box that has hit its end should not start scrolling the page behind
   it: on a trackpad that reads as the page lurching for no reason. */
.fnlist, textarea, .nav { overscroll-behavior: contain; }

/* ---- long strings must not widen the page ----
   A pasted URL in a feedback message, or a very long build title, used to push
   the whole layout sideways. None of these pages scroll horizontally by design,
   so break inside a word rather than let one word decide the page width. */
body { overflow-wrap: break-word; }

/* Centred on the viewport, so on a narrow screen a long message ran off both
   edges at once and neither end could be read. */
.toast { max-width: calc(100vw - 32px); text-align: center; }

/* ---- phones ----
   Two of these are bug fixes rather than taste. Inputs go to 16px because iOS
   Safari zooms the page in when you focus a field smaller than that, and does
   not zoom back out. Controls grow because a 24px target is not something a
   thumb hits reliably. */
@media (max-width: 640px) {
  /* Six nav pills wrapped onto three lines and ate the top of the screen. They
     scroll sideways instead now, the way the planner's class tabs already do. */
  .nav { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: thin; padding-bottom: 3px; }
  .nav::-webkit-scrollbar { height: 4px; }
  .nav::-webkit-scrollbar-thumb { background: var(--edge); border-radius: 2px; }
  .nav a, .nav span.here { flex: none; white-space: nowrap; }
  .nav .sp { display: none; }

  input.txt, textarea, select { font-size: 16px; padding: 10px 12px; }

  button, .btn { font-size: 13px; }
  .primary, .ghost, .danger { padding: 11px 15px; }
  .mini { width: 34px; height: 34px; font-size: 15px; }

  .card { padding: 13px 14px; }
  .cards { gap: 8px; }

  /* The same shape the planner's dialog takes on a phone: two full-width rows
     with the safe one nearest the thumb. */
  .sheet { padding: 15px; max-height: calc(100vh - 24px); }
  .modal { padding: 12px; }
  .dlgfoot { flex-direction: column-reverse; }
  .dlgfoot button { width: 100%; padding: 12px 15px; font-size: 14px; }
}

@media (max-width: 400px) {
  body { padding: 11px 11px 54px; }
  .card { padding: 12px; border-radius: 10px; }
  /* two stat cards per row beats one wide card and an orphan */
  .cards .card, .card.stat { flex: 1 1 calc(50% - 4px); padding: 10px 12px; }
  h2 { margin: 18px 0 9px; }
}

/* ---- damage types ---- */
.dt { font-style: normal; font-family: ui-monospace, monospace; letter-spacing: .1em; }
.dt.PHYSICAL { color: var(--dt-physical); } .dt.FIRE { color: var(--dt-fire); }
.dt.FROST { color: var(--dt-frost); } .dt.ELECTRIC { color: var(--dt-electric); }
.dt.LUMINOUS { color: var(--dt-luminous); } .dt.SHADOW { color: var(--dt-shadow); }
.dt.POISON { color: var(--dt-poison); }

/* ---- tooltips ----
   Drawn by src/tip.js, which upgrades whatever already carries a `title`. Fixed
   rather than absolute so it is placed against the window and not against
   whichever ancestor happens to be positioned; the script flips it below when
   there is no room above. The same rule as everywhere else applies to the
   arrow: it is one element, so it cannot drift from the box it points out of. */
.tip { position: fixed; z-index: 200; max-width: 300px; pointer-events: none;
  opacity: 0; visibility: hidden; transform: translateY(2px);
  transition: opacity .12s ease, transform .12s ease, visibility .12s;
  background: var(--panel); color: var(--ink); border: 1px solid var(--edge);
  border-radius: 9px; padding: 7px 10px;
  /* Monospace, like the chips and the stat rows. Most of what carries a title
     here is label-shaped — "Sorcerer's Mastery x11", "PHYSICAL 1.25x", "Past the
     soft cap at 250%" — and those line up in it rather than reading as prose
     that happens to contain a number.

     11.5 rather than 12.5: a monospace face sets larger at the same size. The
     box widens to 300 for the same reason, since it fits fewer characters per
     pixel than the sans it replaced and 280 would have wrapped a line more. */
  font-family: ui-monospace, monospace;
  font-size: 11.5px; line-height: 1.55; letter-spacing: .01em;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
  border-color: color-mix(in srgb, var(--glow) 26%, var(--edge)); }
.tip.on { opacity: 1; visibility: visible; transform: none; }
/* The point, drawn as a rotated corner of the same box so it takes the same
   border and background without either being restated. */
.tip::after { content: ''; position: absolute; width: 8px; height: 8px;
  left: 50%; margin-left: -4px; bottom: -5px; background: var(--panel);
  border-right: 1px solid var(--edge); border-bottom: 1px solid var(--edge);
  border-color: color-mix(in srgb, var(--glow) 26%, var(--edge));
  transform: rotate(45deg); }
.tip.below::after { bottom: auto; top: -5px;
  border: none; border-left: 1px solid var(--edge); border-top: 1px solid var(--edge);
  border-color: color-mix(in srgb, var(--glow) 26%, var(--edge)); }
/* Anyone who asked for less movement gets it without the slide. */
@media (prefers-reduced-motion: reduce) {
  .tip { transition: opacity .12s ease, visibility .12s; transform: none; }
}
