/* Dungeon Atlas — parchment & pen, in three lights.

   The palettes are Far Table's, lifted from its PHB page palette
   (lib/features/rules/presentation/phb_theme.dart) so the two apps read as
   one family: `parchment` is the Homebrewery 5ePHB page (naturalcrit/
   homebrewery, MIT), `dark` relights it as slate paper, `ember` as wine
   vellum by candlelight. Each theme carries its own paper texture, the same
   three JPEGs Far Table tiles under every screen.

   Everything colour-bearing is a token. `--red` is the RUBRIC role — the
   heading/active colour, maroon on parchment and the page's own gold in the
   two dark themes, exactly as Far Table's kPhbMaroon does. `--sel` is the
   selection signal and stays gold in all three (Far Table's D3: colour is
   signal, so it does not move between themes). */

/* ---------- parchment (default) ---------- */
:root {
  --parch:      #EEE5CE;
  --parch-deep: #E2D6B8;
  --parch-dark: #D3C4A0;
  --ink:        #2B2118;
  --ink-soft:   #6B5B47;
  --ink-faint:  #9A8873;
  --red:        #58180D;
  --on-red:     #EEE5CE;
  --danger:     #58180D;
  --gold:       #B8860B;
  --gold-lit:   #E3B45C;
  --gold-ink:   #7a5a06;
  --sel:        #B8860B;

  --tex:        url('/tex/parchment_background.jpg?v=1');
  --glow:       rgba(255,252,240,.55);
  --vig-1:      rgba(90,66,32,.18);
  --vig-2:      rgba(60,40,16,.34);
  --fiber:      .5;
  --fiber-blend: multiply;

  --line:       rgba(43,33,24,.28);
  --line-soft:  rgba(43,33,24,.18);
  --line-hard:  rgba(43,33,24,.45);
  --hover:      rgba(43,33,24,.08);
  --red-line:   rgba(88,24,13,.4);
  --red-veil:   rgba(88,24,13,.86);
  --red-shadow: rgba(88,24,13,.18);

  --panel:      rgba(238,229,206,.93);
  --panel-deep: rgba(240,232,212,.98);
  --field:      rgba(255,252,242,.7);
  --field-soft: rgba(255,252,242,.5);
  --field-lit:  #fffdf5;

  --shadow-1:   rgba(60,44,20,.26);
  --shadow-2:   rgba(60,44,20,.14);
  --scrim:      rgba(40,28,12,.42);
  --flash:      rgba(227,180,92,.36);

  /* canvas ink, read by app.js when it writes the SVG */
  --node-fill:      rgba(255,252,242,.88);
  --node-fill-soft: rgba(255,252,242,.5);
  --lead-fill:      rgba(240,222,175,.75);
  --portal-ink:     #7a5a06;
  --ok-ink:         #1F4C3A;
  --chunk-fill:     rgba(184,134,11,.07);
  --marquee-fill:   rgba(184,134,11,.12);
  --peer-lift:      0;   /* 1 = lighten identity colours for a dark ground */

  --sheet-w:    212px;
  color-scheme: light;
}

/* ---------- dark: the page relit as slate paper ---------- */
:root[data-theme="dark"] {
  --parch:      #18181F;
  --parch-deep: #26262F;
  --parch-dark: #34343F;
  --ink:        #E8E4D9;
  --ink-soft:   #9C937E;
  --ink-faint:  #7A7468;
  --red:        #D8C18A;
  --on-red:     #18181F;
  --danger:     #C94F4F;
  --gold:       #9E8A55;
  --gold-lit:   #E3B45C;
  --gold-ink:   #E3B45C;
  --sel:        #E3B45C;

  --tex:        url('/tex/parchment_dark.jpg?v=1');
  --glow:       rgba(150,150,175,.10);
  --vig-1:      rgba(0,0,0,.22);
  --vig-2:      rgba(0,0,0,.44);
  --fiber:      .16;
  --fiber-blend: screen;

  --line:       rgba(232,228,217,.22);
  --line-soft:  rgba(232,228,217,.13);
  --line-hard:  rgba(232,228,217,.36);
  --hover:      rgba(232,228,217,.09);
  --red-line:   rgba(216,193,138,.38);
  --red-veil:   rgba(20,20,26,.86);
  --red-shadow: rgba(216,193,138,.2);

  --panel:      rgba(30,30,38,.93);
  --panel-deep: rgba(34,34,43,.98);
  --field:      rgba(232,228,217,.07);
  --field-soft: rgba(232,228,217,.05);
  --field-lit:  rgba(232,228,217,.13);

  --shadow-1:   rgba(0,0,0,.55);
  --shadow-2:   rgba(0,0,0,.35);
  --scrim:      rgba(6,6,10,.6);
  --flash:      rgba(227,180,92,.26);

  --node-fill:      rgba(35,35,44,.9);
  --node-fill-soft: rgba(35,35,44,.55);
  --lead-fill:      rgba(72,62,32,.7);
  --portal-ink:     #C9A24B;
  --ok-ink:         #6FBF9A;
  --chunk-fill:     rgba(227,180,92,.09);
  --marquee-fill:   rgba(227,180,92,.14);
  --peer-lift:      1;
  color-scheme: dark;
}

/* ---------- ember: wine vellum by candlelight ---------- */
:root[data-theme="ember"] {
  --parch:      #180818;
  --parch-deep: #2A0A1A;
  --parch-dark: #3A0E20;
  --ink:        #F2E3C8;
  --ink-soft:   #B9968F;
  --ink-faint:  #8A6470;
  --red:        #F8C868;
  --on-red:     #180818;
  --danger:     #E06060;
  --gold:       #C9A24B;
  --gold-lit:   #FFD98A;
  --gold-ink:   #F8C868;
  --sel:        #E8834A;

  --tex:        url('/tex/parchment_ember.jpg?v=1');
  --glow:       rgba(255,200,140,.12);
  --vig-1:      rgba(20,0,10,.3);
  --vig-2:      rgba(10,0,6,.55);
  --fiber:      .2;
  --fiber-blend: screen;

  --line:       rgba(242,227,200,.2);
  --line-soft:  rgba(242,227,200,.12);
  --line-hard:  rgba(242,227,200,.34);
  --hover:      rgba(248,200,104,.1);
  --red-line:   rgba(248,200,104,.36);
  --red-veil:   rgba(26,6,20,.86);
  --red-shadow: rgba(248,200,104,.2);

  --panel:      rgba(42,10,26,.93);
  --panel-deep: rgba(48,12,30,.98);
  --field:      rgba(242,227,200,.07);
  --field-soft: rgba(242,227,200,.05);
  --field-lit:  rgba(242,227,200,.13);

  --shadow-1:   rgba(0,0,0,.6);
  --shadow-2:   rgba(0,0,0,.4);
  --scrim:      rgba(12,2,10,.62);
  --flash:      rgba(232,131,74,.28);

  --node-fill:      rgba(42,10,26,.9);
  --node-fill-soft: rgba(42,10,26,.55);
  --lead-fill:      rgba(74,22,49,.8);
  --portal-ink:     #C9A24B;
  --ok-ink:         #6FBF9A;
  --chunk-fill:     rgba(232,131,74,.09);
  --marquee-fill:   rgba(232,131,74,.14);
  --peer-lift:      1;
  color-scheme: dark;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; overflow: hidden; }
body {
  font-family: 'Crimson Pro', Georgia, serif;
  color: var(--ink);
  background: var(--parch);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; }

/* ---------- parchment ground ---------- */
/* The texture is the same sheet Far Table lays under every screen; the two
   radial gradients are this app's own candle-in-the-middle vignette on top. */
#ground {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 40%, var(--glow), rgba(0,0,0,0) 55%),
    radial-gradient(140% 120% at 50% 50%, rgba(0,0,0,0) 52%, var(--vig-1) 82%, var(--vig-2) 100%),
    var(--tex) center / cover no-repeat,
    var(--parch);
}
#fibers {
  position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0;
  pointer-events: none; opacity: var(--fiber); mix-blend-mode: var(--fiber-blend);
}

/* ---------- stage ---------- */
/* SVG is a replaced element: inset:0 alone leaves it at its intrinsic 300x150. */
#stage { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 1; display: block; touch-action: none; }
#stage.is-panning { cursor: grabbing; }
#stage.pen-ready { cursor: crosshair; }
#stage.grab-ready { cursor: cell; }
#stage.join-ready { cursor: crosshair; }
#stage.erase-ready { cursor: crosshair; }
/* Erase shows you exactly which line you're about to cut, before you cut it. */
#stage.erase-ready .edge-hit { stroke-width: 20; }
#stage.erase-ready .edge-hit:hover { stroke: var(--red-line); }
#stage.join-ready .node, #stage.join-ready .hit { cursor: crosshair; }
#arrow path { fill: var(--ink); }

/* The filtered groups are decoration; #edgebits and #nodes carry the hit targets. */
#edges, #nodeshapes, #route { pointer-events: none; }
.edge-hit { stroke: transparent; stroke-width: 22; fill: none; cursor: pointer; pointer-events: stroke; }
.splice { cursor: pointer; }
.splice:hover { fill: var(--gold-lit); }
.handle:hover { fill: var(--gold-lit); }
.node-label { font-family: 'Cinzel', Georgia, serif; font-size: 13px; font-weight: 600; fill: var(--ink); pointer-events: none; letter-spacing: .01em; }
.node-sub   { font-family: 'Caveat', cursive; font-size: 14px; fill: var(--ink-soft); pointer-events: none; }
.edge-label { font-family: 'Caveat', cursive; font-size: 15px; fill: var(--ink-soft); pointer-events: none; }
.glyph      { font-size: 13px; fill: var(--red); pointer-events: none; text-anchor: middle; }

.node { cursor: pointer; }
/* Two strengths of fade: `dimmed` pushes something right out of the way,
   `faded` keeps the skeleton of the map readable behind a filter. */
.dimmed { opacity: .15; }
.faded  { opacity: .3; }

/* ---------- chrome ---------- */
.bar {
  position: fixed; z-index: 5; display: flex; align-items: center; gap: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 3px;
  box-shadow: 0 3px 14px var(--shadow-1);
  backdrop-filter: blur(3px);
}
/* ---------- the two toolboxes ----------
   The bar stacks: the atlas and its chrome, then "draw" (what a click does to
   the map), then "read" (how you look at it). Rows rather than one long run,
   because a single wrapping row breaks its own grouping — the wrap lands in a
   different place at every window width and splits whichever group it hits. */
#topbar {
  top: 14px; left: 14px; padding: 3px 10px;
  flex-direction: column; align-items: stretch; gap: 0;
  max-width: calc(100vw - var(--sheet-w) - 44px);
}
.barrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 5px 0; }
.barrow + .barrow { border-top: 1px solid var(--line-soft); }
/* Pushes the chrome to the far edge of whatever the widest row below sets. */
.spacer { flex: 1 1 auto; }

/* The four exclusive tools, fused into one dial with a single setting. */
/* `overflow: hidden` rounds the corners over the child buttons, but it also
   lets this shrink below its contents — on the phone's single scrolling row
   that collapsed the whole dial to a 2px sliver. Hence flex: 0 0 auto. */
.seg { display: inline-flex; flex: 0 0 auto; border: 1px solid var(--line); border-radius: 3px; overflow: hidden; }
.seg .tool { border-radius: 0; border: none; border-left: 1px solid var(--line-soft); }
.seg .tool:first-child { border-left: none; }

/* Lenses: independent switches, so a different shape from the dial above. */
.tool.pill { border: 1px solid var(--line); border-radius: 999px; padding: 5px 11px; }
.tool.pill.on { border-color: var(--red); }

/* One-shot actions have no state, so they wear no frame — nothing to look
   stuck on. Undo dims when there is nothing left to un-scribble. */
.tool.flat { color: var(--ink-faint); }
.tool.flat:hover { color: var(--red); }
.tool.flat:disabled { opacity: .38; cursor: default; }
.tool.flat:disabled:hover { color: var(--ink-faint); }
/* The type-scale toggle, beside the theme lamp. Both are one-tap settings for
   how the atlas looks rather than what it says, so they read as a pair. */
.type-step { font-family: 'Cinzel', serif; letter-spacing: .04em; min-width: 42px; }
.type-step.on { color: var(--red); border-color: var(--line); background: var(--hover); }

/* The way back to Far Table. Quieter than the atlas's own name, which is the
   one thing in this row that should read first. */
#topbar .homelink { text-decoration: none; display: inline-block; }
#topbar .homelink:hover { color: var(--red); }

#topbar .title {
  font-family: 'Cinzel', serif; font-weight: 700; font-size: 14px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--red);
  padding-right: 4px; border: none; background: none; width: 190px;
}
#topbar .title:focus { outline: none; border-bottom: 1px dashed var(--ink-soft); }

.tool {
  font-family: 'Cinzel', serif; font-size: 11px; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase;
  padding: 6px 10px; border-radius: 2px; color: var(--ink-soft);
  border: 1px solid transparent; white-space: nowrap;
}
.tool:hover { background: var(--hover); color: var(--ink); }
.tool.on { background: var(--red); color: var(--on-red); border-color: var(--red); }
.tool .k { opacity: .55; font-size: 10px; margin-left: 5px; }
.sep { width: 1px; align-self: stretch; background: var(--line-soft); margin: 2px 3px; }

/* ---------- the theme lamp ---------- */
/* Far Table cycles dark → parchment → ember from one app-bar icon (moon /
   sun / flame) and names where you landed. Same control, same order, same
   three glyphs — drawn here rather than pulled from a Material font. */
.theme-lamp { display: inline-flex; align-items: center; padding: 5px 7px; }
.theme-lamp svg { width: 17px; height: 17px; display: block; fill: none;
  stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.theme-lamp .lamp-moon, .theme-lamp .lamp-sun, .theme-lamp .lamp-flame { display: none; }
:root[data-theme="dark"] .theme-lamp .lamp-moon { display: block; }
:root:not([data-theme="dark"]):not([data-theme="ember"]) .theme-lamp .lamp-sun { display: block; }
:root[data-theme="ember"] .theme-lamp .lamp-flame { display: block; }
.theme-lamp:hover { color: var(--red); }

#peers { position: relative; z-index: 6; width: 100%; }
.peer-toggle {
  width: 100%; display: flex; align-items: center; gap: 7px; padding: 6px 8px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 2px; color: var(--ink-soft); font-size: 12px; text-align: left;
}
.peer-toggle:hover { background: var(--parch-deep); color: var(--ink); }
.peer-toggle > span:nth-child(2) { flex: 1; }
.peer-toggle b { font-size: 12px; transition: transform .15s ease; }
#peers.open .peer-toggle b { transform: rotate(180deg); }
.peer-dots { display: flex; padding-left: 4px; }
.peer-dots i { width: 8px; height: 8px; border-radius: 50%; border: 1px solid var(--parch); margin-left: -4px; }
.peer-menu {
  display: none; flex-direction: column; gap: 4px; padding: 6px; margin-top: 3px;
  background: var(--panel-deep); border: 1px solid var(--line);
  border-radius: 2px; box-shadow: 0 5px 14px var(--shadow-2);
}
#peers.open .peer-menu { display: flex; }
.peer {
  display: flex; align-items: center; gap: 5px; padding: 5px 9px 5px 6px;
  background: var(--field-soft); border: 1px solid var(--line-soft);
  border-radius: 2px; font-size: 12px;
}
.peer i { width: 8px; height: 8px; border-radius: 50%; display: block; }
.peer > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.peer small { color: var(--ink-soft); font-size: 10px; }

/* ---------- level stack ---------- */
#sheets {
  position: fixed; top: 14px; right: 14px; bottom: 14px; width: var(--sheet-w); z-index: 5;
  display: flex; flex-direction: column; gap: 5px; overflow-y: auto; padding-right: 2px;
}
#sheets::-webkit-scrollbar { width: 6px; }
#sheets::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }
.sheets-head {
  font-family: 'Cinzel', serif; font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-soft); padding: 2px 4px 3px;
  display: flex; align-items: center; gap: 2px;
}
/* The two faces of the panel. Underlined rather than boxed: they label what
   is below them, and a second framed control beside the level rows would
   read as another row. */
.sheet-tab {
  font-family: 'Cinzel', serif; font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-faint);
  padding: 3px 6px; border-bottom: 1px solid transparent;
}
.sheet-tab:hover { color: var(--ink-soft); }
.sheet-tab.on { color: var(--red); border-bottom-color: var(--red); }
.sheets-head .tool { margin-left: auto; }
/* Offered once, under the session list, while anything is unattributed. */
.adopt {
  width: 100%; margin-top: 7px; padding: 7px 9px; text-align: left;
  font-family: 'Crimson Pro', serif; font-size: 12px; line-height: 1.35;
  color: var(--ink-soft); background: var(--panel);
  border: 1px dashed var(--line); border-radius: 2px;
}
.adopt:hover { color: var(--red); border-color: var(--red-line); }

/* The signpost's link back to the night that drew it. */
.logref-inline {
  font: inherit; color: var(--red); text-decoration: underline;
  text-underline-offset: 2px; padding: 0;
}
.logref-inline:hover { color: var(--ink); }

/* A session row is a sheet row that happens to list nights instead. */
.sheet.session .n { color: var(--ink-soft); }
.sheet.session.on .n { color: var(--on-red); }
.sheet {
  position: relative; text-align: left; padding: 8px 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line);
  border-radius: 2px; box-shadow: 1px 1px 0 var(--shadow-2);
  display: flex; align-items: baseline; gap: 8px; width: 100%;
}
.sheet-row { display: flex; align-items: stretch; gap: 3px; width: 100%; }
.level-delete {
  flex: 0 0 auto; padding: 4px 5px; border: 1px solid var(--red-line);
  border-radius: 2px; color: var(--danger); font-family: 'Caveat', cursive;
  font-size: 12px; writing-mode: vertical-rl; transform: rotate(180deg);
  opacity: .62;
}
.level-delete:hover { color: var(--on-red); background: var(--danger); opacity: 1; }
.empty-levels {
  width: 100%; padding: 13px 10px; border: 1px dashed var(--red-line);
  border-radius: 2px; color: var(--red); background: var(--panel);
  font-family: 'Cinzel', serif; font-size: 10px; letter-spacing: .08em;
  text-transform: uppercase;
}
.empty-levels:hover { background: var(--parch-deep); border-style: solid; }
.sheet:hover { background: var(--parch-deep); }
.sheet.on { border-left-color: var(--red); background: var(--parch-deep); box-shadow: 2px 2px 0 var(--red-shadow); }
.sheet .n { font-family: 'Cinzel', serif; font-weight: 700; font-size: 15px; color: var(--red); min-width: 22px; }
.sheet .nm { font-size: 14px; line-height: 1.15; flex: 1; }
.sheet .ct { font-size: 11px; color: var(--ink-soft); font-family: 'Caveat', cursive; }

/* ---------- inspector ---------- */
/* A floating, draggable, resizable pane rather than a fixed column: the map is
   the point, and a signpost in the bottom-left should not be read through a
   panel nailed to the right. JS restores left/top/width/height as inline
   styles — these values are only the first-run position. */
#inspector {
  /* Opens clear of the toolbar, not over it. */
  /* Above the fan (8), not below it: the form is the thing being read, and a
     hand of cards drawn over the notes field is unusable. */
  position: fixed; top: 84px; right: calc(var(--sheet-w) + 26px); z-index: 9;
  width: 288px; height: min(560px, calc(100vh - 98px));
  max-width: calc(100vw - 28px); max-height: calc(100vh - 28px);
  min-width: 236px; min-height: 180px;
  background: var(--panel-deep);
  border: 1px solid var(--line);
  border-radius: 3px; box-shadow: 0 8px 30px var(--shadow-1);
  padding: 14px; overflow-y: auto;
  display: none; flex-direction: column; gap: 11px;
  resize: both;
}
#inspector.open { display: flex; }
/* Lifted while dragging so it reads as picked up, and so the pointer cannot
   fall through onto the map mid-drag. */
#inspector.lifted { box-shadow: 0 14px 44px var(--shadow-1); user-select: none; }
#inspector.lifted, #inspector.lifted * { cursor: grabbing !important; }
#inspector h3 {
  font-family: 'Cinzel', serif; font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--red); font-weight: 700;
  border-bottom: 1px solid var(--red-line); padding-bottom: 5px;
  display: flex; justify-content: space-between; align-items: center;
  cursor: grab; touch-action: none;
}
#inspector h3 button { cursor: pointer; }
.fld { display: flex; flex-direction: column; gap: 3px; }
.fld > label { font-family: 'Cinzel', serif; font-size: 9.5px; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-soft); }
.fld input[type=text], .fld select, .fld textarea {
  background: var(--field); border: 1px solid var(--line);
  border-radius: 2px; padding: 6px 7px; font-size: 14px; width: 100%;
}
.fld select option { background: var(--parch-deep); color: var(--ink); }
.fld textarea { font-family: 'Caveat', cursive; font-size: 17px; line-height: 1.32; resize: vertical; min-height: 82px; }
.fld input:focus, .fld select:focus, .fld textarea:focus { outline: none; border-color: var(--red); background: var(--field-lit); }
.chips { display: flex; flex-wrap: wrap; gap: 4px; }
.chip {
  font-size: 11px; padding: 4px 8px; border-radius: 2px;
  border: 1px solid var(--line); background: var(--field-soft); color: var(--ink-soft);
}
.chip.on { background: var(--red); color: var(--on-red); border-color: var(--red); }
.wire {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
  padding: 3px 4px 3px 9px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: var(--field-soft);
}
.wire:hover { background: var(--parch-deep); }
.wire .cut {
  width: 17px; height: 17px; line-height: 15px; text-align: center; font-size: 11px;
  border-radius: 50%; color: var(--ink-soft); background: var(--hover);
}
.wire .cut:hover { background: var(--danger); color: var(--on-red); }
.rowbtns { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.btn {
  flex: 1; min-width: 84px; text-align: center; padding: 7px 8px; font-size: 11px;
  font-family: 'Cinzel', serif; letter-spacing: .07em; text-transform: uppercase;
  border: 1px solid var(--line-hard); border-radius: 2px; background: var(--field-soft);
}
.btn:hover { background: var(--parch-deep); }
.btn.danger { color: var(--danger); border-color: var(--red-line); }
.btn.danger:hover { background: var(--danger); color: var(--on-red); }
.btn.gold { border-color: var(--gold); color: var(--gold-ink); }
.btn.gold:hover { background: var(--gold-lit); color: var(--ink); }
.meta { font-family: 'Caveat', cursive; font-size: 14px; color: var(--ink-soft); }
.hintline { font-size: 12px; color: var(--ink-soft); line-height: 1.4; }

/* ---------- art on the map ---------- */
.seal { cursor: pointer; }
.seal-ring { fill: none; stroke: var(--red); stroke-width: 2; }

/* ---------- the fan: a signpost's art, spread on hover ----------
   Screen-space cards over the map, laid out by app.js — everything here that
   varies per card arrives as a custom property so the hover lift and the
   spread animation can both own a transform without fighting over one rule.
   The layer itself is inert; only the cards take the pointer, so a fan can
   never swallow a click meant for the sheet underneath it. */
#fan { position: fixed; inset: 0; z-index: 8; pointer-events: none; }
#fan[hidden] { display: none; }

.fan-card {
  position: absolute; width: var(--fan-w); height: var(--fan-h); pointer-events: auto;
  transform: rotate(var(--rot)); transform-origin: var(--org);
  animation: fan-spread .17s cubic-bezier(.2,.9,.3,1) both;
}
.fan-card:hover { z-index: 2; }

.fan-shot {
  position: absolute; inset: 0; overflow: hidden; border-radius: 2px;
  border: 1px solid var(--line-hard); background: var(--field-soft);
  box-shadow: 2px 3px 8px var(--shadow-1);
  cursor: pointer; transition: transform .12s ease-out, box-shadow .12s ease-out;
}
.fan-card:hover .fan-shot { transform: translateY(-7px) scale(1.05); box-shadow: 3px 6px 15px var(--shadow-1); }
.fan-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

.fan-cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 14px 9px 6px;
  font-family: 'Caveat', cursive; font-size: 19px; line-height: 1.1;
  color: var(--parch); background: linear-gradient(transparent, rgba(30,20,8,.82) 45%);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* The tail of a long hand: says how much is not being shown. */
.fan-more {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; background: var(--panel-deep); border-style: dashed; color: var(--red);
}
.fan-more b { font-family: 'Cinzel', serif; font-size: 34px; }
.fan-more span { font-family: 'Caveat', cursive; font-size: 19px; color: var(--ink-soft); }

@keyframes fan-spread {
  from { transform: translate(var(--fx), var(--fy)) rotate(0deg) scale(.5); opacity: 0; }
  to   { transform: rotate(var(--rot)) scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .fan-card { animation-duration: .01ms; animation-delay: 0ms !important; }
  .fan-card:hover .fan-shot { transform: none; }
}

/* ---------- art strip in the inspector ---------- */
.art { display: flex; flex-wrap: wrap; gap: 6px; }
.art figure {
  position: relative; width: 62px; height: 62px; border-radius: 2px; overflow: hidden;
  border: 1px solid var(--line-hard); box-shadow: 1px 1px 0 var(--shadow-2);
  background: var(--field-soft); cursor: pointer; flex: 0 0 auto;
}
.art figure img { width: 100%; height: 100%; object-fit: cover; display: block; }
.art figure .x {
  position: absolute; top: 0; right: 0; width: 18px; height: 18px; line-height: 16px;
  text-align: center; font-size: 12px; background: var(--red-veil); color: var(--parch);
  opacity: 0; transition: opacity .12s;
}
:root[data-theme="dark"] .art figure .x,
:root[data-theme="ember"] .art figure .x { color: var(--ink); }
.art figure:hover .x { opacity: 1; }
.art .addart {
  width: 62px; height: 62px; border: 1px dashed var(--line-hard); border-radius: 2px;
  color: var(--ink-soft); font-size: 20px; line-height: 60px; text-align: center; flex: 0 0 auto;
}
.art .addart:hover { border-color: var(--red); color: var(--red); background: var(--field-soft); }
.pastebox { display: flex; gap: 5px; }
.pastebox input { flex: 1; min-width: 0; }

/* ---------- chronicle chips in the inspector ---------- */
.logrefs { display: flex; flex-direction: column; gap: 3px; }
.logref {
  text-align: left; font-size: 13px; padding: 5px 7px; border-radius: 2px;
  border: 1px solid var(--line-soft); background: var(--field-soft); line-height: 1.25;
}
.logref:hover { background: var(--parch-deep); }
.logref b { font-family: 'Cinzel', serif; font-size: 11px; letter-spacing: .05em; display: block; color: var(--red); }
.logref span { font-family: 'Caveat', cursive; font-size: 13px; color: var(--ink-soft); }

/* ---------- the form's type scale ----------
   One multiplier, toggled from the toolbar between 1 and 1.25, so the signpost
   form can be read across a table or on a shared screen.

   These are OVERRIDES rather than edits to the rules above, for two reasons.
   Several of those classes (.btn, .meta, .chip) are shared with the reading
   room, which should keep its own sizes — this is the form's knob, not the
   app's. And every size here equals its original at scale 1, so nothing moves
   until someone presses the button.

   The trick in the first line: --fs is one scaled pixel, so each rule below
   reads as its own old px number times the scale. */
#inspector { --fs: calc(1px * var(--form-scale, 1)); }

#inspector h3                                             { font-size: calc(11 * var(--fs)); }
#inspector .fld > label                                   { font-size: calc(9.5 * var(--fs)); }
#inspector .fld input[type=text],
#inspector .fld select                                    { font-size: calc(14 * var(--fs)); }
#inspector .fld textarea                                  { font-size: calc(17 * var(--fs)); }
#inspector .chip                                          { font-size: calc(11 * var(--fs)); }
#inspector .wire                                          { font-size: calc(12 * var(--fs)); }
#inspector .wire .cut                                     { font-size: calc(11 * var(--fs)); }
#inspector .btn                                           { font-size: calc(11 * var(--fs)); }
#inspector .tool                                          { font-size: calc(11 * var(--fs)); }
#inspector .meta                                          { font-size: calc(14 * var(--fs)); }
#inspector .hintline                                      { font-size: calc(12 * var(--fs)); }
#inspector .art .addart                                   { font-size: calc(20 * var(--fs)); }
#inspector .logref                                        { font-size: calc(13 * var(--fs)); }
#inspector .logref b                                      { font-size: calc(11 * var(--fs)); }
#inspector .logref span                                   { font-size: calc(13 * var(--fs)); }

/* The one control that is not type: the art thumbnails grow with the form, or
   a bigger panel just shows the same postage stamps. */
#inspector .art figure,
#inspector .art .addart { width: calc(62 * var(--fs)); height: calc(62 * var(--fs)); }
#inspector .art .addart { line-height: calc(60 * var(--fs)); }

/* ---------- the reading room ---------- */
#book {
  position: fixed; inset: 0; z-index: 14; display: none; flex-direction: column;
  background:
    radial-gradient(120% 90% at 50% 30%, var(--glow), rgba(0,0,0,0) 60%),
    radial-gradient(140% 120% at 50% 50%, rgba(0,0,0,0) 55%, var(--vig-1) 85%, var(--vig-2) 100%),
    var(--tex) center / cover no-repeat,
    var(--parch);
}
#book.open { display: flex; }
.book-bar {
  display: flex; align-items: center; gap: 8px; padding: 12px 16px;
  border-bottom: 1px solid var(--line); background: var(--panel);
}
.book-bar .spacer { flex: 1; }
.btab {
  font-family: 'Cinzel', serif; font-size: 12px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; padding: 7px 14px; border-radius: 2px; color: var(--ink-soft);
  border: 1px solid transparent;
}
.btab:hover { color: var(--ink); background: var(--hover); }
.btab.on { color: var(--on-red); background: var(--red); border-color: var(--red); }
.book-body { flex: 1; overflow-y: auto; padding: 26px 16px 80px; }
#book-inner { max-width: 680px; margin: 0 auto; }

.entry { margin-bottom: 26px; padding-bottom: 22px; border-bottom: 1px solid var(--line-soft); }
.entry:last-child { border-bottom: none; }
.entry.flash { animation: flash 1.4s ease-out; }
@keyframes flash { from { background: var(--flash); } to { background: transparent; } }
.entry h4 {
  font-family: 'Cinzel', serif; font-size: 19px; color: var(--red); font-weight: 700;
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
}
.entry h4 .no {
  font-size: 11px; letter-spacing: .14em; color: var(--ink-soft); text-transform: uppercase;
  border: 1px solid var(--line); border-radius: 2px; padding: 1px 6px;
}
.entry .byline { font-family: 'Caveat', cursive; font-size: 16px; color: var(--ink-soft); margin: 3px 0 10px; }
.entry .body { font-size: 16.5px; line-height: 1.62; }
.entry .body p { margin-bottom: 11px; }
.entry .body ul { margin: 0 0 11px 20px; }
.entry .body li { margin-bottom: 3px; }
.entry .body em { font-style: italic; }
.entry .body strong { font-weight: 600; color: var(--red); }
.entry .pins { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 11px; align-items: center; }
.entry .pins .lbl {
  font-family: 'Cinzel', serif; font-size: 9.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft); margin-right: 2px;
}
.pinchip {
  font-size: 12px; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--red-line); background: var(--field-soft); color: var(--red);
}
.pinchip:hover { background: var(--red); color: var(--on-red); }
.pinchip.off { border-color: var(--line); color: var(--ink-soft); }
.pinchip.off:hover { background: var(--parch-dark); color: var(--ink); }
.entry .tools { display: flex; gap: 6px; margin-top: 12px; }
.entry .tools .tool { padding: 4px 9px; font-size: 10px; }

.editor { display: flex; flex-direction: column; gap: 9px; margin-bottom: 26px; }
.editor .row { display: flex; gap: 9px; }
.editor input[type=text], .editor input[type=date], .editor textarea {
  background: var(--field); border: 1px solid var(--line);
  border-radius: 2px; padding: 8px 9px; font-size: 15px; width: 100%;
}
.editor textarea { min-height: 210px; line-height: 1.55; resize: vertical; font-family: 'Crimson Pro', Georgia, serif; }
.editor input:focus, .editor textarea:focus { outline: none; border-color: var(--red); background: var(--field-lit); }
.editor .hintline { margin-top: -3px; }
.editor code {
  font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px;
  background: var(--hover); border-radius: 2px; padding: 1px 4px;
}
.datelbl {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: 'Cinzel', serif; font-size: 9.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-soft);
}
.datelbl input { width: 168px; }
.imrow {
  border: 1px solid var(--line-soft); border-left: 3px solid var(--red-line);
  border-radius: 2px; padding: 10px; margin-bottom: 10px;
  display: flex; flex-direction: column; gap: 7px; background: var(--field-soft);
}
.imbody {
  font-size: 14px; line-height: 1.5; color: var(--ink-soft);
  max-height: 88px; overflow: hidden; white-space: pre-wrap;
  border-top: 1px dashed var(--line-soft); padding-top: 7px;
}

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(136px, 1fr)); gap: 12px; }
.gcard { border: 1px solid var(--line); border-radius: 2px; overflow: hidden; background: var(--field-soft); box-shadow: 1px 1px 0 var(--shadow-2); text-align: left; }
.gcard img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; cursor: pointer; }
.gcard .meta { padding: 6px 8px; font-size: 12px; line-height: 1.3; }
.gcard .meta b { display: block; font-family: 'Cinzel', serif; font-size: 10px; letter-spacing: .06em; color: var(--red); }
.gcard .meta span { font-family: 'Caveat', cursive; color: var(--ink-soft); font-size: 13px; }
.empty { text-align: center; color: var(--ink-soft); font-family: 'Caveat', cursive; font-size: 19px; padding: 50px 20px; line-height: 1.5; }

/* ---------- lightbox ---------- */
/* A fixed dark room in every theme: a photograph is judged against black, not
   against whatever the app is wearing. (Far Table holds its photo viewer the
   same way, and its identityInk rule exempts fixed dark rooms for this reason.) */
#lightbox { position: fixed; inset: 0; z-index: 22; display: none; align-items: center; justify-content: center; background: rgba(30,20,8,.86); padding: 32px; }
#lightbox.open { display: flex; }
.lb-inner { max-width: 96vw; max-height: 92vh; display: flex; flex-direction: column; gap: 10px; align-items: center; }
#lb-img { max-width: 96vw; max-height: 80vh; object-fit: contain; border: 2px solid rgba(238,229,206,.75); border-radius: 2px; box-shadow: 0 20px 70px rgba(0,0,0,.6); }
#lb-cap {
  width: min(560px, 90vw); text-align: center; background: rgba(238,229,206,.1);
  border: 1px solid rgba(238,229,206,.3); border-radius: 2px; padding: 7px 11px;
  color: #EEE5CE; font-family: 'Caveat', cursive; font-size: 20px;
}
#lb-cap:focus { outline: none; border-color: #E3B45C; background: rgba(238,229,206,.16); }
#lb-cap::placeholder { color: rgba(238,229,206,.42); }
.lb-tools { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; }
.lb-tools .tool { color: rgba(238,229,206,.75); border-color: rgba(238,229,206,.28); border-style: solid; }
.lb-tools .tool:hover { background: rgba(238,229,206,.15); color: #EEE5CE; }

/* ---------- dropping files ---------- */
body.dropping::after {
  content: 'let go to pin it to the map';
  position: fixed; inset: 12px; z-index: 30; pointer-events: none;
  border: 3px dashed var(--red); border-radius: 5px;
  display: flex; align-items: flex-end; justify-content: center; padding-bottom: 26px;
  font-family: 'Cinzel', serif; font-size: 13px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--red); background: var(--flash);
}

/* ---------- modal ---------- */
#modal, .modal { position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; background: var(--scrim); }
#modal.open, .modal.open { display: flex; }
.card {
  width: 380px; max-width: calc(100vw - 32px); background: var(--parch);
  border: 1px solid var(--line-hard); border-radius: 3px;
  box-shadow: 0 18px 60px var(--shadow-1); padding: 22px;
}
.card h2 { font-family: 'Cinzel', serif; font-size: 15px; letter-spacing: .1em; text-transform: uppercase; color: var(--red); margin-bottom: 5px; }
.card p { font-size: 14px; color: var(--ink-soft); margin-bottom: 14px; line-height: 1.45; }
.card input { width: 100%; background: var(--field); border: 1px solid var(--line); border-radius: 2px; padding: 9px 10px; font-size: 16px; }
.card label { display: block; margin: 11px 0 4px; font-family: 'Cinzel', serif; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); }
.card input:disabled { color: var(--ink-soft); background: var(--hover); }
.form-error { min-height: 18px; margin-top: 7px; color: var(--danger); font-size: 13px; }
.card-actions { display: flex; align-items: stretch; gap: 7px; }
.card-actions .cancel { margin-top: 12px; border-color: var(--line); }
.card .go { margin-top: 12px; width: 100%; padding: 10px; background: var(--red); color: var(--on-red); font-family: 'Cinzel', serif; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; border-radius: 2px; }

/* ---------- the alarm ---------- */
/* Shown when the server tells us it can no longer write the map. Sits above
   everything including the reading room, because it is true everywhere. */
#alarm {
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  background: var(--danger); color: #fff;
  font-family: 'Cinzel', serif; font-size: 12px; letter-spacing: .06em;
  text-align: center; padding: 9px 14px; line-height: 1.45;
  box-shadow: 0 3px 16px rgba(0,0,0,.4);
}
#alarm.near { background: var(--gold); color: #1A120B; }
/* The banner wraps to two or three lines depending on width, so its height is
   measured and published as --alarm-h rather than guessed. Only things
   anchored to the TOP move; on phones the level strip and inspector hang off
   the bottom and must be left alone. */
body.alarmed #topbar { top: calc(var(--alarm-h, 0px) + 14px); }
@media (min-width: 701px) {
  body.alarmed #sheets, body.alarmed #inspector { top: calc(var(--alarm-h, 0px) + 14px); }
}
#alarm b { display: block; font-size: 13px; letter-spacing: .12em; text-transform: uppercase; }
#alarm span { font-family: 'Crimson Pro', Georgia, serif; font-size: 13px; letter-spacing: 0; opacity: .92; }

/* ---------- misc ---------- */
#status {
  position: fixed; left: 14px; bottom: 14px; z-index: 5; font-size: 12px; color: var(--ink-soft);
  background: var(--panel); border: 1px solid var(--line-soft); border-radius: 2px;
  padding: 5px 9px; font-family: 'Caveat', cursive; font-size: 15px;
}
#status.warn { color: var(--danger); border-color: var(--red-line); }
#legend {
  position: fixed; left: 14px; bottom: 46px; z-index: 5; width: 200px;
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: 2px; padding: 9px 11px; font-size: 11.5px; color: var(--ink-soft); line-height: 1.65;
  display: none;
  /* The full card is taller than a laptop window; scroll it rather than let
     it climb over the top bar. */
  max-height: calc(100vh - 128px); overflow-y: auto;
}
#legend.open { display: block; }
#legend b { font-family: 'Cinzel', serif; font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--red); display: block; margin-bottom: 4px; }
#legend .lead-mark { color: var(--gold-lit); }
#legend kbd {
  font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 10px;
  border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 3px;
  padding: 0 4px; background: var(--field); color: var(--ink);
}
@media (max-width: 1180px) {
  #topbar .title { width: 156px; font-size: 12px; }
  .tool .k { display: none; }
}

/* Phones: the level stack becomes a strip along the bottom and the map gets
   the full width. A sidebar at this size leaves nothing to read. */
@media (max-width: 700px) {
  #peers { display: none; }
  .book-body { padding: 18px 12px 70px; }
  .book-bar { padding: 9px 10px; gap: 5px; flex-wrap: wrap; }
  .btab { padding: 6px 10px; font-size: 11px; }
  .gallery { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  /* Back to one scrolling row on a phone. Three rows would eat an eighth of
     the screen, and the grouping does not need them — the segmented dial and
     the pills keep saying which control is which kind wherever they sit. */
  #topbar {
    left: 8px; right: 8px; max-width: none; padding: 5px 7px; gap: 4px;
    flex-direction: row; align-items: center;
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  }
  #topbar::-webkit-scrollbar { display: none; }
  .barrow { display: contents; }
  .spacer { display: none; }
  /* Flattening the rows would otherwise put the chrome first and scroll the
     tools off the end. Keep the reaching order: atlas, tools, then chrome. */
  #topbar .title { order: -1; }
  .barrow-head .tool { order: 3; }
  #topbar .title { width: 142px; flex: 0 0 142px; padding: 2px 3px; }
  .tool { padding: 6px 8px; font-size: 10.5px; }
  #topbar .sep { display: none; }

  #sheets {
    top: auto; left: 8px; right: 8px; bottom: 8px; width: auto;
    flex-direction: row; align-items: stretch; gap: 6px;
    overflow-x: auto; overflow-y: hidden; padding: 0;
  }
  #sheetlist { display: flex; flex-direction: row; gap: 6px; }
  .sheet-row { flex: 0 0 auto; width: auto; }
  .level-delete { writing-mode: horizontal-tb; transform: none; }
  .empty-levels { width: auto; white-space: nowrap; }
  .sheets-head {
    order: 9; padding: 0; flex: 0 0 auto;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: 2px;
  }
  .sheets-head span { display: none; }
  .sheet {
    flex: 0 0 auto; flex-direction: column; gap: 1px; align-items: flex-start;
    min-width: 108px; padding: 7px 10px;
  }
  .sheet .nm { font-size: 13px; line-height: 1.1; }
  .sheet .ct { font-size: 10px; }

  /* On a phone it goes back to a fixed tray — there is nowhere to float it to.
     `!important` because JS writes the desktop geometry inline. */
  #inspector {
    top: auto !important; bottom: 74px !important; left: 8px !important; right: 8px !important;
    width: auto !important; height: 52vh !important; max-height: none; resize: none;
  }
  #inspector h3 { cursor: default; }
  #legend { left: 8px; right: 8px; bottom: 74px; width: auto; }
  #status { left: 8px; right: 8px; bottom: 74px; font-size: 14px; z-index: 7; }
}
