/* ── Shared gold/dark theme ──────────────────────────────────────────────
   Variables + the full-height .nav-bar system (left-nav.js / right-nav.js)
   + the .nav-item button look + the .ctx-menu context-menu look (used inline
   by stories.html, codex.html, ideas.html, etc.). Link this
   before a page's own <style> block so page-specific rules can override. */

/* Solid base color behind the body gradients — mobile browsers paint the
   landscape safe-area bands (notch letterbox) and rubber-band overscroll with
   the computed background-COLOR only; gradients don't count, and transparent
   falls back to white. Matches the gradients' outer stop. Pages that don't
   link this file (map.css, admin.css, standalone pages) carry their own copy. */
html { background-color: #080810; }

:root {
  --panel-bg: rgba(29, 33, 39, 0.92);
  /* Tutorial wedge width. 0px unless tutorial.js opens the wedge, so with it closed every page computes exactly what it did before this existed. Every rule that offsets for the left nav bar reads it; check-tutorial.mjs enforces that. */
  --tut-w: 0px;
  --panel-bg-solid: rgba(29, 33, 39, 0.98);
  --panel-border: rgba(255, 255, 255, 0.14);
  --text-main: #f6f2e9;
  --accent: #d8aa5d;
  --accent-soft: rgba(216, 170, 93, 0.18);
  --shadow: 0 18px 45px rgba(0, 0, 0, 0.35);
  --bar-alpha: 0.5;
}

/* ── Native widget theming ───────────────────────────────────────────────
   color-scheme: dark must sit at the DOCUMENT level, not on the <select>:
   Chrome keys the option-popup's own chrome (its base fill and the thick
   border around the list) off the document's color scheme — a select-level
   declaration themed the arrow and rows but left a white frame around the
   open popup. Document-level also renders every other native widget dark
   (scrollbars without custom styling, number-input spinners, textarea
   resize grips), matching the site. Safe here because the app is single-
   theme dark: no prefers-color-scheme conditionals exist anywhere, and
   every page authors its own backgrounds. The option rule colors the list
   rows where the browser honours option CSS (Chromium/Firefox); OS-native
   popups (macOS Safari, iOS picker sheets) ignore background and color
   TOGETHER and theme themselves, so the pair degrades safely. Components
   may layer scoped option rules on top, but never set option color without
   also setting its background (dark-on-dark otherwise).
   map.css and admin/admin.css carry their own copies (self-contained). */
:root { color-scheme: dark; }
select option { background: #1d2127; color: #f6f2e9; }

/* ── Full-height side bars ───────────────────────────────────────────────
   left-nav.js renders .nav-bar-left, right-nav.js renders .nav-bar-right. */
/* z-index 45 sits deliberately ABOVE the pages' #navBarTop (40). The edge bars
   and the top bar never overlap — the top bar always spans left:44px/right:44px,
   between them — so the only thing this ordering decides is whether a bar's
   hover tooltip (.nav-label) can overhang the top bar. It must: the topmost
   button's pill is vertically centred around y≈34px, inside the top bar's 48px
   band, so at equal z-index the pill was painted over. This was previously only
   "fixed" by DOM order (the nav scripts appended after the top-bar markup),
   which left map.html — whose bars are inline markup ABOVE its top bar — broken.
   Stay below 60/90/100 so detail popovers, side panels and every modal overlay
   still cover the bars. */
.nav-bar {
  position: fixed; z-index: 45;
  top: 0; bottom: 0; width: 44px;
  display: flex; flex-direction: column;
  background: rgba(29, 33, 39, var(--bar-alpha));
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  -webkit-user-select: none;
  user-select: none; overflow: visible;
}
.nav-bar-left  { left: var(--tut-w);  border-right: 1px solid var(--panel-border); }
.nav-bar-right { right: 0; border-left:  1px solid var(--panel-border); }
.nb-top, .nb-bottom { display: flex; flex-direction: column; padding: 8px 0; }
.nb-bottom { margin-top: auto; }
.nav-bar .nav-item { border-radius: 4px; }

/* The at-the-table tools belong to tabletop stories only. Hidden by DEFAULT and
   revealed by world-mode.js's body class, so a General story never shows them —
   not even for the moment before the mode resolves. The consequence is that a
   page carrying the nav bars but not world-mode.js shows neither button, which
   check-ttrpg-gate.mjs asserts against. */
.nav-item[data-target="dice"],
.nav-item[data-target="initiative"],
.nav-item[data-target="gm"] { display: none; }
body.mode-ttrpg   .nav-item[data-target="dice"],
body.mode-ttrpg   .nav-item[data-target="initiative"],
body.mode-ttrpg   .nav-item[data-target="gm"],
body.mode-ttrpg5e .nav-item[data-target="dice"],
body.mode-ttrpg5e .nav-item[data-target="initiative"],
body.mode-ttrpg5e .nav-item[data-target="gm"] { display: grid; }

.nav-item {
  position: relative; width: 100%; height: 52px; border: 0; border-radius: 14px;
  background: transparent; color: var(--text-main); cursor: pointer; outline: none;
  display: grid; place-items: center; overflow: visible;
  transition: color 0.18s ease, background 0.18s ease;
}
.nav-item:hover, .nav-item.active {
  color: var(--accent); background: rgba(255,255,255,0.055);
}
/* FA-icon experiment: nav icons are <i class="nav-icon fa-solid fa-...">.
   This project's kit is the CSS/webfont build (kit config method:"css"), so the
   <i> stays an <i> and the glyph is a ::before — it is sized by FONT-SIZE, not
   by the box, and colored by `color` (no stroke/fill). width/height still apply
   because FA sets display:inline-block on the icon classes. */
.nav-icon { width: 24px; height: 17px; display: block; font-size: 15px; line-height: 17px; text-align: center; }

.nav-item .nav-label {
  position: absolute; top: 50%; left: calc(100% + 14px); z-index: 999;
  opacity: 0; pointer-events: none; white-space: nowrap;
  padding: 8px 12px; border-radius: 999px;
  background: linear-gradient(180deg, rgba(255,255,255,0.06), transparent), var(--panel-bg-solid);
  border: 1px solid var(--panel-border);
  color: var(--text-main); font-size: 13px; letter-spacing: 0.02em;
  box-shadow: 0 10px 28px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.08);
  transform: translateY(-50%) translateX(-6px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.nav-item .nav-label::before {
  content: ""; position: absolute; right: 100%; top: 50%; transform: translateY(-50%);
  border-width: 6px; border-style: solid;
  border-color: transparent var(--panel-bg-solid) transparent transparent;
}
.nav-bar-right .nav-item .nav-label {
  left: auto; right: calc(100% + 14px); transform: translateY(-50%) translateX(6px);
}
.nav-bar-right .nav-item .nav-label::before {
  right: auto; left: 100%;
  border-color: transparent transparent transparent var(--panel-bg-solid);
}
/* Split deliberately into two rules, and the :hover half gated to pointer
   devices. Two separate WebKit problems, one line of CSS:
   1. An unknown pseudo-class invalidates its ENTIRE selector list, so below
      Safari 15.4 (no :focus-visible) the combined rule was dropped whole and
      tooltips never appeared at all — even on hover.
   2. On touch, revealing content on :hover makes iOS spend the first tap on
      hover and swallow the click (see the hover-reveal note in CLAUDE.md's
      styling conventions). Nav buttons must stay single-tap. */
@media (hover: hover) {
  .nav-item:hover .nav-label { opacity: 1; transform: translateY(-50%) translateX(0); }
}
.nav-item:focus-visible .nav-label { opacity: 1; transform: translateY(-50%) translateX(0); }

/* ── Context menu (matches the existing inline-SVG-icon convention already
   used by stories.html / codex.html / ideas.html, recolored) ── */
.ctx-menu {
  position: fixed; z-index: 500; display: none;
  background: var(--panel-bg-solid); -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  border: 1px solid var(--panel-border); border-radius: 12px; padding: 5px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.3);
  -webkit-user-select: none;
  user-select: none;
}
.ctx-menu.open { display: block; min-width: 180px; }
.ctx-item {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 10px; border-radius: 7px;
  color: var(--text-main); font-size: 13px;
  cursor: pointer; white-space: nowrap; transition: background 0.12s ease;
}
/* Pointer devices only — menu items are <div>s, so iOS doesn't count them as
   natively clickable and spends the first tap on :hover, withholding the
   click. That made every context-menu action a two-tap affair. See the
   hover-reveal note in CLAUDE.md's styling conventions. */
@media (hover: hover) {
  .ctx-item:hover        { background: var(--accent-soft); }
  .ctx-item.danger:hover { background: rgba(255,60,60,0.18); color: rgba(255,140,140,1); }
}
.ctx-item.danger       { color: rgba(255,110,110,0.9); }
.ctx-item.disabled     { opacity: 0.4; pointer-events: none; }
/* FA-icon experiment: context-menu icons are <i class="fa-...">. The svg half
   of the selector is kept for any menu still using an inline SVG icon; the i
   half is what the FontAwesome webfont icons match. Fixed 15px column so
   labels stay aligned regardless of glyph width. */
.ctx-item svg { width: 15px; height: 14px; flex-shrink: 0; opacity: 0.75; font-size: 13px; }
/* An <i> is sized by font-size; width/height only size the inline-block box,
   so a box wider than the glyph pushes it off-centre unless it is centred. */
.ctx-item i { width: 15px; flex-shrink: 0; opacity: 0.75; font-size: 13px; text-align: center; line-height: 1; }
.ctx-divider { height: 1px; background: rgba(255,255,255,0.08); margin: 4px 5px; }

.ctx-has-sub { position: relative; }
.ctx-has-sub::after { content: '›'; position: absolute; right: 12px; top: 50%; transform: translateY(-50%); opacity: 0.6; }
.ctx-submenu {
  position: absolute; left: 100%; top: -4px; margin-left: 4px;
  background: var(--panel-bg-solid); border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px; padding: 4px; min-width: 160px; z-index: 502;
  box-shadow: 0 8px 32px rgba(0,0,0,0.55);
  display: none; pointer-events: none;
}
/* Hover for pointer devices, .sub-open for touch — see the matching comment
   in map.css. No page loading theme.css currently uses submenus, but keep the
   two copies in step so a future one inherits the touch path. */
@media (hover: hover) {
  .ctx-has-sub:hover > .ctx-submenu { display: block; pointer-events: all; }
}
.ctx-has-sub.sub-open > .ctx-submenu { display: block; pointer-events: all; }
.ctx-has-sub.sub-open { background: rgba(255,255,255,0.06); }
.ctx-section-label {
  padding: 6px 14px 3px; font-size: 10px; font-weight: 700;
  letter-spacing: 1px; text-transform: uppercase; color: rgba(255,255,255,0.35);
}

@media (max-width: 600px) {
  .ctx-menu { min-width: 195px; }
  .ctx-submenu { min-width: 170px; }
}

/* ── What a player is not offered ────────────────────────────────────────
   Ideas is owner + editor read only in the rules, so the button was a link to
   a denied read; Story Settings is owner + editor write; History and Library
   are readable but are GM tools, and the Library is the account's OWN images,
   which has nothing to do with the story they were invited to.

   Hidden on the POSITIVE class, so the failure direction is showing a button
   rather than hiding one: world-role.js resolves 'owner' whenever it cannot
   tell, and a control missing from your own story is a worse, more confusing
   failure than one the rules would reject anyway. Nothing here is a security
   boundary - the rules are, and they are unchanged. */
body.role-player .nav-item[data-target="ideas"],
body.role-player .nav-item[data-target="history"],
body.role-player .nav-item[data-target="settings"],
body.role-player .nav-item[data-target="library"],
/* The Game Master page is owner + co-GM only. It comes AFTER the mode rules
   above, so on a tabletop story a player's button is revealed by the mode and
   then hidden again by this - which is the order that matters, since both are
   single-class selectors of equal specificity. */
body.role-player  .nav-item[data-target="gm"],
body.role-viewer  .nav-item[data-target="gm"] { display: none; }
