/* ===================================================================
   VISTECTUS — site stylesheet
   One file, used by every page. The wireframe it defines is the same
   everywhere: top bar, hero, rows of cards, footer.

   To give a single world its own flavour, do NOT edit this file.
   Add a world.css next to that world's index.html and override the
   custom properties in the :root block below — see
   dnd/world-one/world.css for a worked example.
   =================================================================== */

/* ---- Design tokens ------------------------------------------------
   Named values reused everywhere. A world.css can override any of
   them; everything downstream follows automatically. */

:root {
  /* Surfaces — indigo-black, warming towards violet as it rises */
  --bg:          #0c0a17;   /* page background                     */
  --bg-raised:   #16132a;   /* cards, bars                         */
  --bg-sunken:   #08070f;   /* footer                              */
  --line:        #2a2545;   /* hairlines and card borders          */

  /* Text */
  --ink:         #f1f0f7;   /* headings and body                   */
  --ink-soft:    #a6a1c2;   /* meta, captions, inactive nav        */
  --ink-dim:     #726d91;   /* fine print                          */

  /* Accent — the one colour a world is most likely to change */
  --accent:      #8b7cf6;   /* violet                              */
  --accent-soft: #6d5fd6;   /* the same hue, pushed back           */
  --accent-ink:  #0c0a17;   /* text printed on top of the accent   */

  /* Logo. Replace art/logo.svg with your own file and every page
     follows. Different filename? Change this one line. Wide wordmark?
     Give --logo-w a bigger value. */
  --logo:        url(art/logo.svg);
  --logo-w:      26px;
  --logo-h:      26px;

  /* Type */
  --font-body:    "Source Sans 3", "Segoe UI", system-ui, sans-serif;
  --font-display: "Source Sans 3", "Segoe UI", system-ui, sans-serif;
  --font-mono:    ui-monospace, Consolas, monospace;

  /* Layout */
  --measure:     72rem;     /* max width of a content row          */
  --prose:       40rem;     /* max width of a paragraph            */
  --radius:      2px;       /* corners. Paradox-flat on purpose.   */
  --bar-h:       60px;      /* height of the fixed top bar         */

  /* Art slots. A world.css or an inline style swaps these for
     url('art/whatever.jpg'). The gradients are what shows until
     you have real artwork, so empty pages still look finished. */
  --hero: url("art/backgrounds/Background 1.png");
  --art:  linear-gradient(145deg, #221c42 0%, #110e22 100%);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

/* Keyboard users must always be able to see what is focused. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Jump link for screen readers; invisible until focused. */
.skip {
  position: absolute; left: -9999px;
  background: var(--accent); color: var(--accent-ink);
  padding: .6rem 1rem; z-index: 100;
}
.skip:focus { left: 1rem; top: 1rem; }

/* ---- Top bar ------------------------------------------------------
   Fixed, so navigation is always one click away. */

.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  height: var(--bar-h);
  display: flex; align-items: center; gap: 2rem;
  padding: 0 1.5rem;
  background: rgba(12, 10, 23, .92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex; align-items: center; gap: .6rem;
  font-family: var(--font-display);
  font-weight: 700; font-size: .95rem;
  text-transform: uppercase; letter-spacing: .14em;
  color: var(--ink); text-decoration: none;
  white-space: nowrap;
}

/* The logo. The picture comes from --logo, and the path there is
   relative to THIS stylesheet, so the same line works on every page
   no matter how deep it sits. Nothing to edit when you swap the file. */
.brand-mark {
  flex: none;
  width: var(--logo-w); height: var(--logo-h);
  background: var(--logo) center / contain no-repeat;
  border-radius: var(--radius);
}

/* If art/logo.svg is ever missing the bar would show a gap, so the
   wordmark beside it carries the name on its own. */

.topnav {
  display: flex; align-items: center; gap: 1.6rem;
  margin-left: auto;
  overflow-x: auto;                 /* scrolls instead of wrapping */
  scrollbar-width: none;
}
.topnav::-webkit-scrollbar { display: none; }

.topnav a {
  font-size: .78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-soft); text-decoration: none;
  white-space: nowrap;
  padding: .35rem 0;
  border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
}
.topnav a:hover,
.topnav a[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

/* ---- Hero ---------------------------------------------------------
   Full-bleed key art with a dark scrim so text stays readable over
   any image. Set the art with --hero. */

.hero {
  position: relative;
  min-height: 78vh;
  margin-top: var(--bar-h);
  display: flex; align-items: flex-end;
  padding: 4rem 1.5rem 4.5rem;
  overflow: hidden;
}

/* The artwork itself, in its own layer so it can move without
   dragging the text along with it. */
.hero::before {
  content: "";
  position: absolute; inset: 0;
  background: var(--hero) center / cover no-repeat;
  transform: scale(1.04);
  animation: drift 32s ease-in-out infinite alternate;
}

/* The scrim: dark at the bottom, clear at the top. */
.hero::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to top, var(--bg) 2%, rgba(12,10,23,.72) 38%, rgba(12,10,23,.15) 100%);
}

@keyframes drift {
  from { transform: scale(1.04) translate3d(0, 0, 0); }
  to   { transform: scale(1.12) translate3d(0, -1.5%, 0); }
}

.hero-inner {
  position: relative; z-index: 1;
  width: 100%; max-width: var(--measure);
  margin: 0 auto;
}

/* Shorter hero for system and world pages. */
.hero--compact { min-height: 48vh; padding-bottom: 3rem; }

.kicker {
  font-family: var(--font-mono);
  font-size: .72rem; letter-spacing: .22em; text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 .9rem;
}

.hero h1 {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 7vw, 5rem);
  font-weight: 700; line-height: .98;
  text-transform: uppercase; letter-spacing: .01em;
  margin: 0 0 1rem;
  text-shadow: 0 2px 30px rgba(0,0,0,.5);
}

.lede {
  max-width: var(--prose);
  font-size: 1.1rem;
  color: #d7dce4;
  margin: 0 0 1.8rem;
}

/* ---- Buttons ------------------------------------------------------ */

.btn {
  display: inline-block;
  font-family: var(--font-display);
  font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .14em;
  text-decoration: none;
  padding: .85rem 1.7rem;
  border-radius: var(--radius);
  background: var(--accent); color: var(--accent-ink);
  border: 1px solid var(--accent);
  transition: filter .15s, transform .15s;
}
.btn:hover { filter: brightness(1.12); transform: translateY(-1px); }

/* Outline variant, for the secondary action in a pair. */
.btn--ghost {
  background: transparent; color: var(--ink);
  border-color: #3a4354;
}
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }

/* ---- Rows ---------------------------------------------------------
   A row is one band of content: a heading, then cards or prose. */

.row {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 4rem 1.5rem;
}

.row + .row { padding-top: 1rem; }

.row-head {
  display: flex; align-items: baseline; gap: 1rem;
  margin-bottom: 1.6rem;
  padding-bottom: .9rem;
  border-bottom: 1px solid var(--line);
}

h2 {
  font-family: var(--font-display);
  font-size: 1rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em;
  margin: 0;
}

/* The small link that sits at the right end of a row heading. */
.row-link {
  margin-left: auto;
  font-size: .75rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-soft); text-decoration: none;
}
.row-link:hover { color: var(--accent); }

/* ---- Cards --------------------------------------------------------
   Art-forward tiles. Set each card's picture with an inline
   style="--art: url('art/name.jpg')". */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 1.25rem;
}

.card {
  display: flex; flex-direction: column;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .18s, border-color .18s;
}
.card:hover { transform: translateY(-3px); border-color: var(--accent); }

.card-art {
  position: relative; display: block;
  aspect-ratio: 16 / 9;
  background: var(--art) center / cover no-repeat;
  transition: transform .35s ease;
}
.card:hover .card-art { transform: scale(1.03); }

/* Small label sitting on the artwork, e.g. "3 worlds". */
.card-badge {
  position: absolute; left: .75rem; bottom: .75rem;
  font-family: var(--font-mono);
  font-size: .65rem; letter-spacing: .12em; text-transform: uppercase;
  background: rgba(10, 12, 17, .82); color: var(--ink);
  border: 1px solid var(--line);
  padding: .25rem .55rem;
  border-radius: var(--radius);
}

.card-body { padding: 1.1rem 1.15rem 1.3rem; }

.card-body h3 {
  font-family: var(--font-display);
  font-size: 1.05rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
  margin: 0 0 .35rem;
}
.card-body h3 a { color: var(--ink); text-decoration: none; }
.card-body h3 a:hover { color: var(--accent); }

.card-body p { margin: 0 0 .6rem; color: #c3cad4; font-size: .95rem; }
.card-body p:last-child { margin-bottom: 0; }

/* ---- Entries ------------------------------------------------------
   The repeating blocks on a world page: regions, factions, people.
   Lighter than a card — no artwork required. */

.entries { display: grid; gap: 1.5rem; }

.entry {
  padding-left: 1.1rem;
  border-left: 2px solid var(--line);
  max-width: var(--prose);
  transition: border-color .18s;
}
.entry:hover { border-left-color: var(--accent); }

.entry h3 {
  font-family: var(--font-display);
  font-size: 1.05rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
  margin: 0 0 .25rem;
}

.meta {
  font-family: var(--font-mono);
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 .5rem;
}

p { margin: 0 0 1rem; }
.prose { max-width: var(--prose); color: #c3cad4; }

/* ---- Links in body copy ------------------------------------------ */

a { color: var(--accent); }
a:hover { color: var(--ink); }

.links a {
  margin-right: 1.4rem;
  font-size: .78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em;
  text-decoration: none;
}

/* ---- Breadcrumb --------------------------------------------------- */

.crumb {
  font-family: var(--font-mono);
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 1.2rem;
}
.crumb a { color: var(--ink-soft); text-decoration: none; }
.crumb a:hover { color: var(--accent); }

/* ---- Full-bleed band ----------------------------------------------
   An optional strip of artwork between rows, for atmosphere.
   Set the picture with style="--art: url('art/name.jpg')". */

.band {
  position: relative;
  height: 42vh;
  background: var(--art) center / cover no-repeat;
  border-block: 1px solid var(--line);
}
.band::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(12,10,23,.55), rgba(12,10,23,.85));
}

/* ---- Footer ------------------------------------------------------- */

footer {
  background: var(--bg-sunken);
  border-top: 1px solid var(--line);
  margin-top: 4rem;
  padding: 3rem 1.5rem;
}

.footer-inner {
  max-width: var(--measure); margin: 0 auto;
  display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center;
  font-size: .82rem; color: var(--ink-dim);
}
.footer-inner p { margin: 0; }
.footer-inner .links { margin-left: auto; }

/* ---- Small screens ------------------------------------------------ */

@media (max-width: 720px) {
  .topbar { gap: 1rem; padding: 0 1rem; }
  .brand { font-size: .8rem; letter-spacing: .1em; }
  .topnav { gap: 1.1rem; }
  .hero { min-height: 62vh; padding: 3rem 1.25rem 3rem; }
  .row { padding: 2.5rem 1.25rem; }
  .cards { grid-template-columns: 1fr; }
  .footer-inner .links { margin-left: 0; }
}

/* ---- Reduced motion -----------------------------------------------
   Respects the visitor's system setting. Some people get motion
   sickness from drifting backgrounds. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero::before { animation: none; }
  * { transition-duration: .01ms !important; }
}

/* ===================================================================
   PAGE BACKGROUND ART
   A picture behind the whole page, on every page that wants one.
   It is fixed, so content scrolls over it, and it sits under a scrim
   so text stays readable.

   Turn it on for one page:      <body style="--page-art: url(art/x.jpg)">
   ...or for a whole world, in that world's world.css:
                                 :root { --page-art: url(art/x.jpg); }
   Left unset, nothing renders and the flat background shows through.

   --page-veil controls how heavily the picture is dimmed: 0 is the
   raw image, 1 hides it completely. 0.82 keeps atmosphere without
   fighting the text.
   =================================================================== */

:root {
  --page-art:  none;
  --page-veil: .82;
}

body::before {
  content: "";
  position: fixed; inset: 0; z-index: -2;
  background: var(--page-art) center / cover no-repeat;
  background-attachment: fixed;
}

body::after {
  content: "";
  position: fixed; inset: 0; z-index: -1;
  background: var(--bg);
  opacity: var(--page-veil);
}

/* ---- Roster -------------------------------------------------------
   Portrait tiles that open a dossier. Used by the players and NPC
   pages; driven from the data files by assets/js/render.js. */

.roster {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 1.1rem;
}

.roster-card {
  position: relative;
  display: block; width: 100%; text-align: left;
  padding: 0; cursor: pointer;
  font: inherit; color: inherit;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .18s, border-color .18s;
}
.roster-card:hover { transform: translateY(-3px); border-color: var(--accent); }

.roster-card__portrait {
  width: 100%; aspect-ratio: 3 / 4;
  object-fit: cover;
  background: var(--art);
  filter: saturate(.85) contrast(1.05);
  transition: filter .25s;
}
.roster-card:hover .roster-card__portrait { filter: none; }

.roster-card__hint {
  position: absolute; top: .6rem; right: .6rem; z-index: 1;
  font-family: var(--font-mono);
  font-size: .62rem; letter-spacing: .12em; text-transform: uppercase;
  background: rgba(10, 8, 18, .82); color: var(--ink);
  border: 1px solid var(--line);
  padding: .2rem .5rem; border-radius: var(--radius);
  opacity: 0; transition: opacity .18s;
}
.roster-card:hover .roster-card__hint,
.roster-card:focus-visible .roster-card__hint { opacity: 1; }

.roster-card__body { display: block; padding: .85rem .9rem 1rem; }

.roster-card__name {
  display: block;
  font-family: var(--font-display);
  font-size: 1rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink);
}

.roster-card__tagline {
  display: block; margin-top: .2rem;
  font-size: .85rem; color: var(--ink-soft);
}

/* ---- Dossier ------------------------------------------------------
   The panel that opens when a roster card is clicked. */

.detail-backdrop {
  position: fixed; inset: 0; z-index: 80;
  display: none; place-items: center;
  padding: 1.5rem;
  background: rgba(6, 5, 12, .78);
  backdrop-filter: blur(3px);
}
.detail-backdrop.open { display: grid; }

.detail {
  position: relative;
  width: min(52rem, 100%);
  max-height: 86vh; overflow-y: auto;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.75rem;
}

.detail__close {
  position: absolute; top: .6rem; right: .75rem;
  background: none; border: 0; cursor: pointer;
  color: var(--ink-soft); font-size: 1.7rem; line-height: 1;
}
.detail__close:hover { color: var(--accent); }

.detail__head {
  display: flex; gap: 1.25rem; align-items: flex-start;
  padding-bottom: 1.1rem; margin-bottom: 1.1rem;
  border-bottom: 1px solid var(--line);
}

.detail__portrait {
  width: 8.5rem; aspect-ratio: 3 / 4; flex: none;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--art);
}

.detail__name {
  font-family: var(--font-display);
  font-size: 1.5rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .02em;
  margin: 0 0 .2rem;
}

.detail__role { color: var(--ink-soft); margin: 0 0 .7rem; }

.detail__meta { display: flex; flex-wrap: wrap; gap: .4rem; }

.tag {
  font-family: var(--font-mono);
  font-size: .68rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .2rem .5rem;
}

.detail__section-label {
  font-family: var(--font-mono);
  font-size: .68rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--accent);
  margin: 1.5rem 0 .6rem;
}
.detail__section-label:first-child { margin-top: 0; }

.detail__prose { color: #c9c4dd; }
.detail__prose p { margin: 0 0 .9rem; }

.detail__downloads { display: flex; flex-wrap: wrap; gap: .6rem; }

/* ---- Stat block ---------------------------------------------------- */

.statblock {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
}

.statline {
  display: flex; gap: 1rem; justify-content: space-between;
  padding: .5rem .8rem;
  border-bottom: 1px solid var(--line);
  font-size: .9rem;
}
.statline:last-child { border-bottom: 0; }
.statline .k {
  font-family: var(--font-mono);
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft);
}

.stat-note {
  padding: .6rem .8rem;
  border-top: 1px solid var(--line);
  font-size: .85rem; color: var(--ink-soft);
}

/* ---- Embedded document --------------------------------------------
   For the compendium: someone else's HTML, kept in its own frame so
   its styling cannot leak into the site. */

.frame-shell {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-raised);
}

.frame-bar {
  display: flex; align-items: center; gap: .7rem;
  padding: .55rem .8rem;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft);
}
.frame-bar .spacer { margin-left: auto; }
.frame-bar .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); flex: none;
}

.frame-shell iframe {
  display: block; width: 100%; height: 72vh; border: 0;
  background: var(--bg);
}

/* ---- Empty state --------------------------------------------------- */

.empty {
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 2rem; text-align: center;
  color: var(--ink-soft);
}
.empty code {
  font-family: var(--font-mono); font-size: .85em;
  color: var(--accent);
}

@media (max-width: 720px) {
  .detail { padding: 1.25rem; }
  .detail__head { flex-direction: column; }
  .detail__portrait { width: 7rem; }
  .frame-shell iframe { height: 60vh; }
}
