@import url('fonts/fonts.css');

/* =============================================================
   The Brewery
   Palette tokens are split from geometry on purpose: palette is
   Colour vs Greyscale, geometry is Digital vs POD. They combine
   freely, so adding a fourth mode later means adding tokens, not
   a new stylesheet.
   ============================================================= */

/* ---- app chrome (never printed) ---- */
:root{
  --ui-bg:#0a1720; --ui-panel:#12232e; --ui-border:#24404f;
  --ui-text:#eaf5fb; --ui-dim:#8fadbe; --ui-accent:#3d84c4; --ui-accent-dim:#1c3548;
}

/* =============================================================
   Themes.

   A theme is the look of one setting or genre. It owns colour AND
   typography - a recolour alone still reads as 20 Below in a
   different hue, because the typefaces carry most of the genre.

   Two axes, deliberately independent:
     data-theme   = core | backwater      which setting
     data-palette = colour | grey         full colour or print B&W

   Greyscale is a print-cost mode, not a theme. Someone working in
   Backwater Static wants THEIR theme in greyscale, not a rival of
   it - so each theme brings its own grey ramp, tuned against its
   own colours rather than derived from them. A luminance conversion
   would collapse tokens that sit only a step or two apart.

   Adding a theme means adding two blocks below, an <option> in
   index.html, and nothing else.
   ============================================================= */

/* ---- shared: typography roles ----
   Weight and case travel with the face. Anton at 400 is a heavy
   display face; Fraunces at 400 in the same slot looks broken, so
   the weight is part of the theme rather than the rule. */
#preview{
  --font-display:'Anton',"Segoe UI",system-ui,sans-serif;
  --font-display-weight:400;
  --font-display-case:uppercase;
  --font-head:'Bebas Neue',"Segoe UI",system-ui,sans-serif;
  --font-head-weight:400;
  --font-head-case:none;
  --font-body:'Montserrat',"Segoe UI",system-ui,sans-serif;
  --font-mono:'Space Mono',Consolas,monospace;
}

/* ---- 20 BELOW CORE: colour (default) ----
   The site palette, from docs/style-guide.html. Anything a block
   needs should be added here first, then mirrored into every other
   block below. */
#preview,
#preview[data-theme="core"]{
  --page-bg:#0a1720;
  --page-fg:#eaf5fb;
  --page-dim:#8fadbe;
  --panel:#12232e;
  --panel-2:#1c3548;
  --rule:#24404f;
  --accent:#3d84c4;
  --head:#eaf5fb;
  --shadow:rgba(0,0,0,.55);

  /* Variant tints, from docs/style-guide.html. Semantic roles are the
     Battle Tracker set; the Element colours are that guide's Elements
     palette. Keep the two in step. */
  --v-pc:#5ecb6b;
  --v-ally:#c39a5a;
  --v-npc:#e0685c;
  --v-danger:#e0685c;
  --v-text:#eaf5fb;
  --v-accent:#3d84c4;
  --v-earth:#8a6d4e;
  --v-air:#a8c9e0;
  --v-fire:#e0663f;
  --v-water:#078f9b;
  --v-moira:#a06fd1;
}

/* ---- 20 BELOW CORE: greyscale ----
   Not a filter. A luminance conversion collapses bg/panel (10 grey
   steps apart) and panel-2/rule (9 apart), so each token is mapped
   to a chosen grey with real separation instead. */
#preview[data-palette="grey"],
#preview[data-theme="core"][data-palette="grey"]{
  --page-bg:#141414;
  --page-fg:#f5f5f5;
  --page-dim:#c8c8c8;
  --panel:#2d2d2d;
  --panel-2:#464646;
  --rule:#646464;
  --accent:#a8a8a8;
  --head:#ffffff;
  --shadow:rgba(0,0,0,.55);

  /* A B&W print cannot carry eight hues. Rather than let them collapse
     into near-identical greys, every variant falls back to the accent -
     colour-coding is a colour feature, and a greyscale run should say
     in words what the colour would have said. */
  --v-pc:#a8a8a8;
  --v-ally:#a8a8a8;
  --v-npc:#a8a8a8;
  --v-danger:#a8a8a8;
  --v-text:#f5f5f5;
  --v-accent:#a8a8a8;
  --v-earth:#a8a8a8;
  --v-air:#a8a8a8;
  --v-fire:#a8a8a8;
  --v-water:#a8a8a8;
  --v-moira:#a8a8a8;
}

/* ---- BACKWATER STATIC: colour ----
   Lifted from the setting's own hub page rather than invented.
   Roles follow how that page already uses them: brass is links,
   static pink is the signature, cyan is the secondary label, dread
   is the GM/danger colour. Serif throughout - the swamp-gothic
   register the condensed sans of Core cannot reach. */
#preview[data-theme="backwater"]{
  --page-bg:#0e1512;
  --page-fg:#e4ece9;
  --page-dim:#8ea3a0;
  --panel:#121b1c;
  --panel-2:#16211f;
  --rule:#223333;
  --accent:#ef5c93;
  --head:#e4ece9;
  --shadow:rgba(0,0,0,.65);

  --v-pc:#3fe0c9;
  --v-ally:#c39a5a;
  --v-npc:#9c4436;
  --v-danger:#9c4436;
  --v-text:#e4ece9;
  --v-accent:#ef5c93;
  --v-earth:#7a6438;
  --v-air:#8ea3a0;
  --v-fire:#9c4436;
  --v-water:#276a5f;
  --v-moira:#8a3a5c;

  --font-display:'Fraunces',Georgia,serif;
  --font-display-weight:600;
  --font-display-case:none;
  --font-head:'Fraunces',Georgia,serif;
  --font-head-weight:600;
  --font-head-case:none;
  --font-body:'Source Serif 4',Georgia,"Times New Roman",serif;
  --font-mono:'Space Mono',Consolas,monospace;
}

/* ---- BACKWATER STATIC: greyscale ----
   Its own ramp, not Core's. The colour theme sits on a green-black
   ground where Core sits on blue-black, and its panels are much
   closer to the page than Core's are, so lifting Core's greys here
   would flatten the separation the theme relies on. */
#preview[data-theme="backwater"][data-palette="grey"]{
  --page-bg:#121212;
  --page-fg:#f2f2f2;
  --page-dim:#bdbdbd;
  --panel:#242424;
  --panel-2:#3a3a3a;
  --rule:#5c5c5c;
  --accent:#b4b4b4;
  --head:#ffffff;
  --shadow:rgba(0,0,0,.65);

  --v-pc:#b4b4b4;
  --v-ally:#b4b4b4;
  --v-npc:#b4b4b4;
  --v-danger:#b4b4b4;
  --v-text:#f2f2f2;
  --v-accent:#b4b4b4;
  --v-earth:#b4b4b4;
  --v-air:#b4b4b4;
  --v-fire:#b4b4b4;
  --v-water:#b4b4b4;
  --v-moira:#b4b4b4;
}

/* ---- page geometry ----
   --trim-w/h come from the size selector. Digital uses even margins; the
   print profiles add a gutter that alternates by page parity, plus bleed.

   Bleed is NOT symmetric. A printer trims the top, bottom and outside edges
   and cuts nothing at the spine, because that edge is bound. So both KDP and
   DriveThruRPG want a page that is trim + 0.125in WIDE and trim + 0.25in
   TALL - bleed on three edges, not four. Adding it to all four (as this did
   once) makes every page 0.125in too wide, and the printer answers by
   rejecting the file or scaling it, which walks the text off its margins. */
#preview{
  --trim-w:8.5in; --trim-h:11in;
  --margin:0.6in;
  --gutter:0in;        /* extra inside margin, print profiles only */
  --bleed-out:0in;     /* trimmed edges: top, bottom, outside */
  --safe:0in;          /* extra inset for text, print profiles only */
  --cols:1;
  --zoom:1;            /* preview only; print always renders at 1 */
}
#preview[data-layout="kdp"],
#preview[data-layout="drivethru"]{
  --gutter:0.35in;
  --bleed-out:0.125in;
  --safe:0.15in;
}

*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{
  background:var(--ui-bg); color:var(--ui-text);
  font-family:"Segoe UI",system-ui,sans-serif;
  display:flex; flex-direction:column; overflow:hidden;
}

#bar{
  flex:0 0 auto; display:flex; gap:8px; align-items:center; flex-wrap:wrap;
  padding:10px 14px; background:var(--ui-panel); border-bottom:1px solid var(--ui-border);
}
#bar .title{font-weight:600; letter-spacing:.02em; margin-right:12px}
#bar .title span{color:var(--ui-dim); font-weight:400; font-size:13px; margin-left:8px}
#bar .spacer{margin-left:auto}
#bar label{font-size:12px; color:var(--ui-dim); display:flex; align-items:center; gap:6px}
button,select{
  font:inherit; font-size:13px; color:var(--ui-text); background:transparent;
  border:1px solid var(--ui-border); border-radius:6px; padding:6px 11px; cursor:pointer;
}
select{padding:5px 8px}
button:hover,select:hover{background:var(--ui-accent-dim); border-color:var(--ui-accent)}
button:active{transform:scale(.98)}
button[aria-pressed="true"]{background:var(--ui-accent-dim); border-color:var(--ui-accent); color:#fff}
#status{color:var(--ui-dim); font-size:12px; white-space:nowrap}
#status.warn{color:#e0685c}
/* A link styled as a toolbar button - it navigates, so it stays an <a>. */
.btn-link{
  font-size:13px; color:var(--ui-text); text-decoration:none;
  border:1px solid var(--ui-border); border-radius:6px; padding:6px 11px;
}
.btn-link:hover{background:var(--ui-accent-dim); border-color:var(--ui-accent)}

#split{flex:1 1 auto; display:flex; min-height:0}
#editor{
  flex:0 0 40%; min-width:260px; border:0; outline:0; resize:none;
  padding:16px 18px; background:#0d1c26; color:var(--ui-text);
  font-family:ui-monospace,"Cascadia Mono",Consolas,monospace;
  font-size:14px; line-height:1.65; tab-size:2;
}
#drag{flex:0 0 6px; cursor:col-resize; background:var(--ui-border)}
#drag:hover{background:var(--ui-accent)}
#preview{flex:1 1 auto; overflow:auto; padding:26px 20px; background:#060d12}

/* =============================================================
   The page
   ============================================================= */
.page{
  position:relative;
  /* One bleed on the width (the outside edge), two on the height (top and
     bottom). The spine edge is never trimmed, so it gets none. */
  width:calc(var(--trim-w) + var(--bleed-out));
  min-height:calc(var(--trim-h) + (var(--bleed-out) * 2));
  margin:0 auto 26px;
  padding:
    calc(var(--margin) + var(--bleed-out) + var(--safe))
    calc(var(--margin) + var(--bleed-out) + var(--safe));
  background:var(--page-bg);
  color:var(--page-fg);
  font-family:var(--font-body);
  font-size:10.5pt; line-height:1.6;
  box-shadow:0 3px 22px var(--shadow);
  overflow:hidden;
  zoom:var(--zoom);
}

/* Gutter: the inside edge is wider, and which edge is "inside"
   alternates. Driven off page parity rather than @page :left/:right,
   which browsers support poorly.

   Parity comes from data-side, which render.js works out from the page's
   NUMBER rather than its place in the file. A chapter exported on its own
   and opening at page 12 is a verso, and has to be laid out as one. Using
   the element's position instead would mirror every page in that file and
   put the binding margin on the outside edge, which no proof shows you
   until it is printed and bound. */
/* The spine edge carries the gutter and no bleed - nothing is trimmed there. */
#preview:not([data-layout="digital"]) .page[data-side="recto"]{
  padding-left:calc(var(--margin) + var(--safe) + var(--gutter));
}
#preview:not([data-layout="digital"]) .page[data-side="verso"]{
  padding-right:calc(var(--margin) + var(--safe) + var(--gutter));
}

/* Content past the bottom of a page is clipped, and print would lose it
   silently. Mark it in the preview; never in print. */
.page.overflowing{outline:2px solid #e0685c; outline-offset:-2px}
.page.overflowing::after{
  content:'this page is longer than the sheet - split it with a \\page';
  position:absolute; left:0; right:0; top:0;
  background:#e0685c; color:#2e1a17;
  font-family:"Segoe UI",system-ui,sans-serif; font-size:9pt; font-weight:600;
  text-align:center; padding:.25em; z-index:5;
}
@media print{ .page.overflowing{outline:none} .page.overflowing::after{display:none} }

/* =============================================================
   Page backgrounds
   =============================================================
   A page asks for one with: \page bg=hex

   The art is a layer of its own rather than the page's background,
   which is what lets it be tinted and greyscaled without touching the
   text sitting on it. It covers the bleed as well, because a printer
   trims into it.

   Two kinds. The built-in textures in backgrounds/ are used as MASKS:
   the drawing carries only alpha and the ink comes from --accent, so a
   texture follows the theme and goes grey with the greyscale proof
   instead of staying one fixed colour while the page changes around it.
   Anything else is treated as a URL and drawn as an ordinary image.

   Strength is set per page with tint=, a 0-to-1 value. The defaults are
   low: these are grounds, and body copy has to stay readable over them. */
.page::before{
  content:''; position:absolute; inset:0; z-index:0; pointer-events:none;
  print-color-adjust:exact; -webkit-print-color-adjust:exact;
}
.page:not([data-bg])::before,
.page[data-bg="none"]::before{display:none}

.page[data-bg="hex"]::before,
.page[data-bg="hexdrift"]::before,
.page[data-bg="swarm"]::before{
  background-color:var(--accent);
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center;  mask-position:center;
  -webkit-mask-size:cover;       mask-size:cover;
  opacity:var(--bg-tint, .30);
}
/* Each name falls back to the drawing that ships with the tool. A
   document that names a seed has its grounds drawn in the browser
   instead, and render.js sets --page-mask on the page to the result -
   through a custom property rather than a competing rule, so there is no
   specificity race to lose. */
.page[data-bg="hex"]::before{
  -webkit-mask-image:var(--page-mask, url("backgrounds/hex.svg"));
  mask-image:var(--page-mask, url("backgrounds/hex.svg"));
}
.page[data-bg="hexdrift"]::before{
  -webkit-mask-image:var(--page-mask, url("backgrounds/hexdrift.svg"));
  mask-image:var(--page-mask, url("backgrounds/hexdrift.svg"));
}
/* Heavier than the other two by design - a chapter opener or a title
   page, not a page carrying two columns of body copy. */
.page[data-bg="swarm"]::before{
  -webkit-mask-image:var(--page-mask, url("backgrounds/swarm.svg"));
  mask-image:var(--page-mask, url("backgrounds/swarm.svg"));
  opacity:var(--bg-tint, .16);
}

/* An image of your own. The URL arrives as an inline custom property
   from render.js, because a stylesheet cannot know it in advance. */
.page[data-bg="image"]::before{
  background-image:var(--page-art);
  background-repeat:no-repeat; background-position:center; background-size:cover;
  opacity:var(--bg-tint, 1);
}
/* The greyscale proof is a proof of what will be printed, so art has to
   go grey too - otherwise it is the one thing on the page still lying. */
#preview[data-palette="grey"] .page[data-bg="image"]::before{filter:grayscale(1)}

/* =============================================================
   Folios
   =============================================================
   A document asks for page numbers with a \folio line; without one it
   has none, because a saved setting must never silently restyle
   something you wrote.

   The number sits in the bottom margin, measured from the TRIM edge
   rather than the sheet edge - the bleed is cut off, so measuring from
   there would walk the folio up the page every time the output profile
   changed.

   "Outside" alternates on the same parity the gutter runs on, so a
   number can never end up buried in the spine. */
.page > .folio{
  position:absolute;
  bottom:calc(var(--bleed-out) + (var(--margin) + var(--safe)) * 0.38);
  z-index:2;
  font-family:var(--font-mono);
  font-size:8.5pt;
  /* Loose enough to look set rather than typed, tight enough that a
     roman numeral still reads as one word: viii, not v i i i. */
  letter-spacing:.05em;
  color:var(--page-dim);
  print-color-adjust:exact; -webkit-print-color-adjust:exact;
}
.page[data-folio="outside"][data-side="recto"] > .folio{
  right:calc(var(--margin) + var(--bleed-out) + var(--safe));
}
.page[data-folio="outside"][data-side="verso"] > .folio{
  left:calc(var(--margin) + var(--bleed-out) + var(--safe));
}
.page[data-folio="center"] > .folio{left:0; right:0; text-align:center}

/* Two columns, filled rather than balanced.
 *
 * column-fill defaults to balance, which makes both columns the same
 * height. On a page that does not quite fill, the leftover then shows up
 * at the foot of BOTH columns as one band of white across the page,
 * instead of the first column running to the bottom the way a book sets.
 *
 * column-fill:auto only takes effect against a definite height, and
 * height:100% is not one: .page is min-height, so the percentage is
 * indeterminate and resolves to auto. Hence the same arithmetic the page
 * uses, written out - the sheet, less the padding on both sides of it.
 *
 * The catch, and the reason overflow is measured the way it is below:
 * with a definite height, content that does not fit no longer makes the
 * page taller. It spills into a third column, sideways, where the page's
 * own overflow:hidden clips it. Nothing grows and nothing is visible, so
 * "is the page taller than the sheet" stops being able to detect
 * anything. See overflowing() in autopage.js and flagOverflow() in
 * main.js: both ask scrollWidth instead. */
.page > .flow{
  position:relative; z-index:1;
  height:calc(var(--trim-h) + (var(--bleed-out) * 2)
              - (var(--margin) + var(--bleed-out) + var(--safe)) * 2);
  column-count:2; column-gap:0.38in; column-fill:auto;
}
/* Two columns is the default. A page opts out with: \page cols=1 */
.page[data-cols="1"] > .flow{column-count:1}

/* \column in the source. Nothing is drawn - it exists to carry the
   break, which is why it has no height and no margin of its own. Now
   that the columns fill rather than balance, where the first one ends is
   a decision worth being able to make by hand. */
.page .column-break{break-before:column; height:0; margin:0}
/* Whatever follows starts the column, so it opens at the top of it. A
   heading carries a top margin to set it off from the text above, and at
   a column start there is no text above. */
.page .column-break + *{margin-top:0}

/* A page title spans the spread rather than sitting in one column.
   Lower headings stay in-column so sections can start mid-column. */
.page > .flow > h1{column-span:all}

/* ::: wide - break out of the columns. A spanning element splits the
   flow, so content after it resumes in fresh columns below it. */
.page .wide{column-span:all; margin:0 0 .8em}
.page .wide > :last-child{margin-bottom:0}
/* A wide table spans the page, and equal columns there leave a cost column
   as broad as its description - a sixty-row menu then ran eight pages of
   rows wrapped four lines deep. Sized to their content instead. */
.page .wide table{table-layout:auto}
/* Break only between words there, or auto sizing squeezes a column down to
   one letter and "Cost" sets as "Cos / t". */
.page .wide th,.page .wide td{overflow-wrap:break-word}
/* A wide block has no frame, so its title sits straight on the page and
   has to be kept with the table it names - a heading stranded at the foot
   of a sheet is worse than no heading. */
.page .wide .block-title{break-after:avoid; page-break-after:avoid}

/* The Difficulty ladder, hardest to easiest. The tint is decoration:
   the name column says which rung it is, so the chart still reads
   in greyscale, in print, and to anyone the colour does not reach. */
/* Fixed layout splits three columns into equal thirds, and the first
   one holds a single digit. Naming the narrow two lets each example
   set on one line, which is the difference between this sheet being
   three pages and four. */
/* A lookup table carries tighter rows than body copy. This one is read
   a line at a time mid-roll, not left to right, and the extra leading
   only costs page count. */
.page .wide--difficulty td,.page .wide--difficulty th{padding-top:.14em;padding-bottom:.14em}
.page .wide--difficulty td:first-child,.page .wide--difficulty th:first-child{width:11%}
.page .wide--difficulty td:nth-child(2),.page .wide--difficulty th:nth-child(2){width:22%}
.page .wide--difficulty tbody tr:nth-child(1){background:hsla(356,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(1) td:first-child{background:hsla(356,72%,48%,.42);border-left:5px solid hsla(356,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(2){background:hsla(8,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(2) td:first-child{background:hsla(8,72%,48%,.42);border-left:5px solid hsla(8,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(3){background:hsla(20,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(3) td:first-child{background:hsla(20,72%,48%,.42);border-left:5px solid hsla(20,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(4){background:hsla(32,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(4) td:first-child{background:hsla(32,72%,48%,.42);border-left:5px solid hsla(32,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(5){background:hsla(44,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(5) td:first-child{background:hsla(44,72%,48%,.42);border-left:5px solid hsla(44,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(6){background:hsla(56,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(6) td:first-child{background:hsla(56,72%,48%,.42);border-left:5px solid hsla(56,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(7){background:hsla(72,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(7) td:first-child{background:hsla(72,72%,48%,.42);border-left:5px solid hsla(72,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(8){background:hsla(88,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(8) td:first-child{background:hsla(88,72%,48%,.42);border-left:5px solid hsla(88,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(9){background:hsla(104,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(9) td:first-child{background:hsla(104,72%,48%,.42);border-left:5px solid hsla(104,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(10){background:hsla(120,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(10) td:first-child{background:hsla(120,72%,48%,.42);border-left:5px solid hsla(120,72%,46%,.95)}
.page .wide--difficulty tbody tr:nth-child(11){background:hsla(136,72%,48%,.13)}
.page .wide--difficulty tbody tr:nth-child(11) td:first-child{background:hsla(136,72%,48%,.42);border-left:5px solid hsla(136,72%,46%,.95)}

/* ---- typography ---- */
/* Display faces per docs/style-guide.html: Anton for the headline,
   Bebas Neue for titles and labels, Montserrat for everything else. */
.page h1,.page h2,.page h3,.page h4,.page h5,.page h6{
  line-height:1.15; margin:0 0 .35em; color:var(--head); break-after:avoid;
}
.page h1{
  font-family:var(--font-display); font-weight:var(--font-display-weight);
  font-size:30pt; letter-spacing:.01em; text-transform:var(--font-display-case);
  margin-top:0; border-bottom:2px solid var(--accent); padding-bottom:.06em;
}
.page h2{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  font-size:19pt; letter-spacing:.02em; text-transform:var(--font-head-case);
  margin-top:1em; border-bottom:1px solid var(--rule); padding-bottom:.06em;
}
.page h3{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  font-size:15pt; letter-spacing:.02em; margin-top:.9em; color:var(--accent);
  text-transform:var(--font-head-case);
}
.page h4{
  font-family:var(--font-body); font-weight:600;
  font-size:10.5pt; margin-top:.8em;
}
/* Five and six sit below body size and lean on case and colour rather
   than scale - there is nowhere left to go downward at 10.5pt body. */
.page h5{
  font-family:var(--font-body); font-weight:600;
  font-size:9pt; letter-spacing:.08em; text-transform:uppercase;
  margin-top:.8em; color:var(--accent);
}
.page h6{
  font-family:var(--font-body); font-weight:600;
  font-size:9.5pt; font-style:italic; margin-top:.8em; color:var(--page-dim);
}
.page p{margin:0 0 .7em}
.page ul,.page ol{margin:0 0 .7em; padding-left:1.25em}
.page li{margin-bottom:.22em}
.page a{color:var(--accent); text-decoration:none}
.page hr{border:0; border-top:1px solid var(--rule); margin:1em 0}
.page img{max-width:100%}
.page code{
  font-family:var(--font-mono); font-size:9pt;
  background:var(--panel); padding:.1em .3em; border-radius:3px;
  overflow-wrap:anywhere;                 /* a long token must not widen the column */
}
/* Code wraps rather than scrolling. A scrollbar means nothing on paper,
   and anything past the edge would simply be clipped out of the PDF. */
.page pre{
  font-family:var(--font-mono); font-size:9pt;
  background:var(--panel); padding:.6em .8em; border-radius:4px;
  break-inside:avoid; overflow:visible;
  white-space:pre-wrap; overflow-wrap:anywhere;
}
.page pre code{background:none; padding:0; font-size:inherit}

.page blockquote{
  margin:0 0 .8em; padding:.5em .9em;
  border-left:3px solid var(--accent); background:var(--panel);
  color:var(--page-dim); font-style:italic; break-inside:avoid;
}

/* ---- tables ---- */
.page table{
  width:100%; table-layout:fixed; border-collapse:collapse;
  margin:0 0 .8em; font-size:9.5pt; break-inside:avoid;
}
.page th,.page td{
  border:1px solid var(--rule); padding:.32em .5em;
  text-align:left; vertical-align:top; overflow-wrap:anywhere;
}
.page thead th{
  background:var(--panel-2); color:var(--head);
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  font-size:11pt; letter-spacing:.03em; text-transform:var(--font-head-case);
}
.page tbody tr:nth-child(even){background:var(--panel)}

/* =============================================================
   Blocks. One class each; blocks.js owns the syntax.
   Add a block by adding a rule here and an entry there.
   ============================================================= */
.page .block-title{
  display:block; margin-bottom:.3em; color:var(--head);
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  font-size:13pt; letter-spacing:.02em; text-transform:var(--font-head-case);
}

/* The second half of an entry too tall to fit on one sheet.
 *
 * The name repeats, because a reader landing here needs to know whose
 * entry they are inside, and it carries a mark so they do not read it as
 * a second entry wearing the same name. The mark is set here rather than
 * left in the title: one rule instead of seven renderers, and the two
 * blocks that parse a parenthetical out of a title - a Boon's cost, a
 * Skill's Element - never see it and cannot print it as one.
 *
 * Nothing else changes. Same rule, same tint, same geometry: it is the
 * same object, continued. */
.page .is-continued .block-title::after,
.page .is-continued .gift-name::after,
.page .is-continued .flaw-name::after,
.page .is-continued .res-name::after,
.page .is-continued .boon-name::after,
.page .is-continued .skill-name::after{
  content:' (continued)';
  font-family:var(--font-mono); font-size:7.5pt; font-weight:400;
  letter-spacing:.08em; text-transform:uppercase;
  color:var(--page-dim); vertical-align:.18em; margin-left:.45em;
}

.page .aside{
  background:var(--panel); border-left:4px solid var(--accent);
  padding:.7em .9em; margin:0 0 .8em; font-size:9.5pt; break-inside:avoid;
}
.page .aside > :last-child{margin-bottom:0}

.page .box{
  background:var(--panel); border:1px solid var(--rule);
  padding:.7em .9em; margin:0 0 .8em; border-radius:4px; break-inside:avoid;
}
.page .box > :last-child{margin-bottom:0}

.page .roll-box{
  background:var(--panel-2); border:1px solid var(--accent); color:var(--head);
  font-family:var(--font-head); font-weight:var(--font-head-weight); font-size:13pt;
  letter-spacing:.03em; text-align:center;
  padding:.45em .8em; margin:0 0 .8em; border-radius:4px; break-inside:avoid;
}
.page .roll-box > p{margin:0}

/* The roll box, set for reading: the same frame in the body face at
   body size, for a rule stated in words rather than in numbers. Ranged
   left, unlike the roll box - centring is right for a formula on a
   plaque and wrong for a sentence, which needs a left edge to come
   back to. */
.page .note-box{
  background:var(--panel-2); border:1px solid var(--accent); color:var(--page-fg);
  padding:.55em .9em; margin:0 0 .8em; border-radius:4px; break-inside:avoid;
}
.page .note-box > :last-child{margin-bottom:0}

/* A gift entry. The biggest thing in the book - five levels plus Adders
   and Limiters - so it gets a little more room than the other entry
   blocks and does not try to be compact. Adders and Limiters are runs of
   options rather than a ladder, so they are labelled instead of
   numbered, and tinted apart from each other: one is something you buy,
   the other is something you accept. */
.page .gift{
  background:var(--panel); border-left:3px solid var(--v-moira);
  padding:.6em .8em; margin:0 0 .7em; border-radius:3px;
  font-size:9.5pt; break-inside:avoid;
}
.page .gift > :last-child{margin-bottom:0}
.page .gift-name{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  text-transform:var(--font-head-case);
  font-size:13pt; color:var(--head); letter-spacing:.02em;
}
.page .gift-flavour{
  color:var(--v-moira); font-style:italic; margin:.25em 0 .45em;
}
.page .gift-flavour > p{margin:0}
/* Emphasis inside an italic line flips to roman - italicising
 * italic text says nothing. */
.page .gift-flavour em{font-style:normal}
/* A level on the ladder.
 *
 * Five of these run together down a column, each a paragraph opening with
 * a small number, and at reading size they read as one grey mass - a
 * player looking for what Level 3 does has to find the digit and then
 * work out where that entry stops. So each gets a strip of its own: a
 * panel ground to separate it from the prose around it, and a rule down
 * the left whose strength climbs with the Level.
 *
 * Strength rather than five hues, for two reasons. The Elements already
 * own the colour vocabulary here, and a sixth palette competing with them
 * would say something the ladder does not mean. And the greyscale
 * palette collapses every variant to one grey, so anything keyed on hue
 * alone would arrive at the printer as five identical bands.
 *
 * The rule is drawn as a pseudo-element at a set opacity rather than
 * mixed into a colour, so it inherits whatever the theme's accent is and
 * survives a palette with no colour in it at all. */
.page .gift-level,
.page .flaw-level,
.page .res-level{
  position:relative;
  display:flex; gap:.5em; align-items:baseline;
  margin:.15em 0; padding:.25em .5em .25em .7em;
  background:var(--panel-2); border-radius:0 3px 3px 0;
  break-inside:avoid;
}
.page .gift-level::before,
.page .flaw-level::before,
.page .res-level::before{
  content:''; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--accent); opacity:.35;
  print-color-adjust:exact; -webkit-print-color-adjust:exact;
}
.page .flaw-level::before{background:var(--v-danger)}
/* Level 1 keeps the .35 above; 2 to 5 climb from it. */
.page .gift-level--2::before,
.page .flaw-level--2::before,
.page .res-level--2::before{opacity:.5}
.page .gift-level--3::before,
.page .flaw-level--3::before,
.page .res-level--3::before{opacity:.65}
.page .gift-level--4::before,
.page .flaw-level--4::before,
.page .res-level--4::before{opacity:.82}
.page .gift-level--5::before,
.page .flaw-level--5::before,
.page .res-level--5::before{opacity:1}
.page .gift-level > p{margin:0}
.page .gift-n{
  flex:0 0 auto; min-width:1.15em; text-align:center;
  background:var(--panel-2); border-radius:2px;
  font-family:var(--font-mono); font-size:8pt; font-weight:700;
  color:var(--v-moira); padding:.05em .25em;
}
.page .gift-section{
  display:block; margin:.5em 0 .2em;
  font-family:var(--font-mono); font-size:7.5pt;
  letter-spacing:.1em; text-transform:uppercase; color:var(--page-dim);
}
.page .gift-opt{
  border-left:2px solid var(--rule); padding-left:.6em; margin:.15em 0 .15em .2em;
}
.page .gift-opt > p{margin:0}
.page .gift-opt--adder{border-left-color:var(--v-pc)}
.page .gift-opt--limiter{border-left-color:var(--v-danger)}

/* A flaw entry. Structurally identical to a Resource, deliberately not
   coloured like one: it carries the danger tint so a reader flicking
   through never mistakes a Flaw for something they are buying. */
.page .flaw{
  background:var(--panel); border-left:3px solid var(--v-danger);
  padding:.55em .75em; margin:0 0 .55em; border-radius:3px;
  font-size:9.5pt; break-inside:avoid;
}
.page .flaw > :last-child{margin-bottom:0}
.page .flaw-name{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  text-transform:var(--font-head-case);
  font-size:12pt; color:var(--head); letter-spacing:.02em;
}
.page .flaw-flavour{
  color:var(--v-danger); font-style:italic; margin:.25em 0 .4em;
}
.page .flaw-flavour > p{margin:0}
.page .flaw-level{
  display:flex; gap:.5em; align-items:baseline;
  margin:.18em 0; padding-left:.1em;
}
.page .flaw-level > p{margin:0}
.page .flaw-n{
  flex:0 0 auto;
  min-width:1.15em; text-align:center;
  background:var(--panel-2); border-radius:2px;
  font-family:var(--font-mono); font-size:8pt; font-weight:700;
  color:var(--v-danger); padding:.05em .25em;
}

/* A resource entry. The 1-5 ladder is the substance, so each level gets
   its rating in a badge and sits on its own row - a reader looking up
   "what does Wealth 3 get me" should find it without reading 1 and 2. */
.page .resource{
  background:var(--panel); border-left:3px solid var(--accent);
  padding:.55em .75em; margin:0 0 .55em; border-radius:3px;
  font-size:9.5pt; break-inside:avoid;
}
.page .resource > :last-child{margin-bottom:0}
.page .res-name{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  text-transform:var(--font-head-case);
  font-size:12pt; color:var(--head); letter-spacing:.02em;
}
.page .res-flavour{
  color:var(--accent); font-style:italic; margin:.25em 0 .4em;
}
.page .res-flavour > p{margin:0}
.page .res-level{
  display:flex; gap:.5em; align-items:baseline;
  margin:.18em 0; padding-left:.1em;
}
.page .res-level > p{margin:0}
.page .res-n{
  flex:0 0 auto;
  min-width:1.15em; text-align:center;
  background:var(--panel-2); border-radius:2px;
  font-family:var(--font-mono); font-size:8pt; font-weight:700;
  color:var(--accent); padding:.05em .25em;
}

/* A boon entry. Same density as a skill - these arrive in runs too - but
   the cost sits where the element does on a skill, and tier lines get
   their own indented strip so the sixteen tiered Boons read differently
   at a glance from the twenty-six flat ones. */
.page .boon{
  background:var(--panel); border-left:3px solid var(--accent);
  padding:.55em .75em; margin:0 0 .55em; border-radius:3px;
  font-size:9.5pt; break-inside:avoid;
}
.page .boon > :last-child{margin-bottom:0}
.page .boon-name{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  text-transform:var(--font-head-case);
  font-size:12pt; color:var(--head); letter-spacing:.02em;
}
.page .boon-cost{
  display:inline-block; margin-left:.45em; padding:.05em .4em;
  border:1px solid var(--rule); border-radius:3px;
  font-family:var(--font-mono); font-size:7.5pt;
  letter-spacing:.06em; text-transform:uppercase;
  color:var(--page-dim); vertical-align:.15em;
}
.page .boon-flavour{
  color:var(--accent); font-style:italic; margin:.25em 0 .4em;
}
.page .boon-flavour > p{margin:0}
/* Emphasis inside an italic line flips to roman - italicising
 * italic text says nothing. */
.page .boon-flavour em{font-style:normal}
.page .boon-tier{
  border-left:2px solid var(--rule); padding-left:.6em;
  margin:.3em 0 .3em .2em;
}
.page .boon-tier > p{margin:0 0 .25em}
.page .boon-tier > :last-child{margin-bottom:0}

/* A skill entry. Compact on purpose - these come in runs of dozens, and
   they have to tile down a column without any one of them shouting. The
   left rule takes the element's colour, which is read out of the title
   by blocks.js rather than typed twice. */
.page .skill{
  background:var(--panel); border-left:3px solid var(--accent);
  padding:.55em .75em; margin:0 0 .55em; border-radius:3px;
  font-size:9.5pt; break-inside:avoid;
}
.page .skill > :last-child{margin-bottom:0}
.page .skill-name{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  text-transform:var(--font-head-case);
  font-size:12pt; color:var(--head); letter-spacing:.02em;
}
.page .skill-elem{
  display:inline-block; margin-left:.45em; padding:.05em .4em;
  border:1px solid var(--rule); border-radius:3px;
  font-family:var(--font-mono); font-size:7.5pt;
  letter-spacing:.08em; text-transform:uppercase;
  color:var(--page-dim); vertical-align:.15em;
}
/* The flavour line is the voice; the description under it is the rule.
   Keeping them visually distinct is the whole point of the block. */
.page .skill-flavour{
  color:var(--accent); font-style:italic;
  margin:.25em 0 .4em;
}
.page .skill-flavour > p{margin:0}

/* Equipment cards. Same shape as a Skill entry: a name, a rating pill, a
   line of what the thing is, then what it does. The rating is rendered
   by blocks.js out of the title rather than typed twice. */
.page .item{
  background:var(--panel); border-left:3px solid var(--accent);
  padding:.55em .75em; margin:0 0 .55em; border-radius:3px;
  font-size:9.5pt; break-inside:avoid;
}
.page .item > :last-child{margin-bottom:0}
.page .item-name{
  font-family:var(--font-head); font-weight:var(--font-head-weight);
  text-transform:var(--font-head-case);
  font-size:12pt; color:var(--head); letter-spacing:.02em;
}
.page .item-wr{
  display:inline-block; margin-left:.45em; padding:.05em .4em;
  border:1px solid var(--rule); border-radius:3px;
  font-family:var(--font-mono); font-size:7.5pt;
  letter-spacing:.08em; text-transform:uppercase;
  color:var(--page-dim); vertical-align:.15em;
}
/* What it is, against what it does. Same split the Skill card makes. */
.page .item-flavour{
  color:var(--accent); font-style:italic;
  margin:.25em 0 .4em;
}
.page .item-flavour > p{margin:0}

/* Element colours, matching the roll-box and stat variants. */
.page .skill--earth{border-left-color:var(--v-earth)}
.page .skill--earth .skill-flavour{color:var(--v-earth)}
.page .skill--air{border-left-color:var(--v-air)}
.page .skill--air .skill-flavour{color:var(--v-air)}
.page .skill--fire{border-left-color:var(--v-fire)}
.page .skill--fire .skill-flavour{color:var(--v-fire)}
.page .skill--water{border-left-color:var(--v-water)}
.page .skill--water .skill-flavour{color:var(--v-water)}
.page .skill--moira{border-left-color:var(--v-moira)}
.page .skill--moira .skill-flavour{color:var(--v-moira)}

/* A stat block reads as one object, so it never splits across a column
   or a page. The stat line gets its own strip - it is the thing a GM
   scans for mid-fight. */
.page .stat{
  background:var(--panel); border:1px solid var(--rule);
  border-top:3px solid var(--accent);
  padding:.7em .9em; margin:0 0 .9em; font-size:9.5pt;
  break-inside:avoid; page-break-inside:avoid;
}
.page .stat > :last-child{margin-bottom:0}
.page .stat .block-title{
  font-size:14pt; margin-bottom:.15em; color:var(--head);
}
.page .stat .stat-line{
  background:var(--panel-2); border-radius:3px;
  padding:.35em .55em; margin:0 0 .55em;
  font-size:9pt; line-height:1.5;
}
.page .stat .stat-line p{margin:0}
.page .stat p{margin:0 0 .45em}

/* Variants recolour the top rule and the name. */
.page .stat--pc{border-top-color:var(--v-pc)}
.page .stat--ally{border-top-color:var(--v-ally)}
.page .stat--npc,.page .stat--danger{border-top-color:var(--v-npc)}
.page .stat--text{border-top-color:var(--v-text)}
.page .stat--accent{border-top-color:var(--v-accent)}
.page .stat--earth{border-top-color:var(--v-earth)}
.page .stat--air{border-top-color:var(--v-air)}
.page .stat--fire{border-top-color:var(--v-fire)}
.page .stat--water{border-top-color:var(--v-water)}
.page .stat--moira{border-top-color:var(--v-moira)}

.page .stat--pc .block-title{color:var(--v-pc)}
.page .stat--ally .block-title{color:var(--v-ally)}
.page .stat--npc .block-title,.page .stat--danger .block-title{color:var(--v-npc)}
.page .stat--earth .block-title{color:var(--v-earth)}
.page .stat--air .block-title{color:var(--v-air)}
.page .stat--fire .block-title{color:var(--v-fire)}
.page .stat--water .block-title{color:var(--v-water)}
.page .stat--moira .block-title{color:var(--v-moira)}

.page .figure{margin:0 0 .9em; break-inside:avoid}
.page .figure img{display:block; width:100%; height:auto}
/* Variants: a thin colour override on the base block. Generated for
   every name in blocks.js VARIANTS - keep the two lists in step. */
.page .aside--pc{border-left-color:var(--v-pc)}
.page .aside--ally{border-left-color:var(--v-ally)}
.page .aside--npc,.page .aside--danger{border-left-color:var(--v-npc)}
.page .aside--earth{border-left-color:var(--v-earth)}
.page .aside--air{border-left-color:var(--v-air)}
.page .aside--fire{border-left-color:var(--v-fire)}
.page .aside--water{border-left-color:var(--v-water)}
.page .aside--moira{border-left-color:var(--v-moira)}
.page .aside--text{border-left-color:var(--v-text)}
.page .aside--accent{border-left-color:var(--v-accent)}

/* The aside's title takes the tint too, the way box's does. Without
   these the sample's own line - "colour tints the rule and the title" -
   was only half true for asides. */
.page .aside--pc .block-title{color:var(--v-pc)}
.page .aside--ally .block-title{color:var(--v-ally)}
.page .aside--npc .block-title,.page .aside--danger .block-title{color:var(--v-npc)}
.page .aside--earth .block-title{color:var(--v-earth)}
.page .aside--air .block-title{color:var(--v-air)}
.page .aside--fire .block-title{color:var(--v-fire)}
.page .aside--water .block-title{color:var(--v-water)}
.page .aside--moira .block-title{color:var(--v-moira)}
.page .aside--text .block-title{color:var(--v-text)}
.page .aside--accent .block-title{color:var(--v-accent)}

.page .box--pc{border-color:var(--v-pc)}
.page .box--ally{border-color:var(--v-ally)}
.page .box--npc,.page .box--danger{border-color:var(--v-npc)}
.page .box--earth{border-color:var(--v-earth)}
.page .box--air{border-color:var(--v-air)}
.page .box--fire{border-color:var(--v-fire)}
.page .box--water{border-color:var(--v-water)}
.page .box--moira{border-color:var(--v-moira)}
.page .box--text{border-color:var(--v-text)}
.page .box--accent{border-color:var(--v-accent)}

.page .box--pc .block-title{color:var(--v-pc)}
.page .box--ally .block-title{color:var(--v-ally)}
.page .box--npc .block-title,.page .box--danger .block-title{color:var(--v-npc)}
.page .box--earth .block-title{color:var(--v-earth)}
.page .box--air .block-title{color:var(--v-air)}
.page .box--fire .block-title{color:var(--v-fire)}
.page .box--water .block-title{color:var(--v-water)}
.page .box--moira .block-title{color:var(--v-moira)}
.page .box--text .block-title{color:var(--v-text)}
.page .box--accent .block-title{color:var(--v-accent)}

/* A roll box is a solid stamp, so the variant colours the border and
   the text rather than flooding the fill - a saturated fill behind
   Bebas Neue at 13pt loses legibility in CMYK. */
.page .roll-box--pc{border-color:var(--v-pc); color:var(--v-pc)}
.page .roll-box--ally{border-color:var(--v-ally); color:var(--v-ally)}
.page .roll-box--npc,.page .roll-box--danger{border-color:var(--v-npc); color:var(--v-npc)}
.page .roll-box--earth{border-color:var(--v-earth); color:var(--v-earth)}
.page .roll-box--air{border-color:var(--v-air); color:var(--v-air)}
.page .roll-box--fire{border-color:var(--v-fire); color:var(--v-fire)}
.page .roll-box--water{border-color:var(--v-water); color:var(--v-water)}
.page .roll-box--moira{border-color:var(--v-moira); color:var(--v-moira)}
.page .roll-box--text{border-color:var(--v-text); color:var(--v-text)}
.page .roll-box--accent{border-color:var(--v-accent); color:var(--v-accent)}

/* A note box tints its frame, not its text: the text is body copy and
   has to stay readable, which is the whole point of the block. */
.page .note-box--pc{border-color:var(--v-pc)}
.page .note-box--ally{border-color:var(--v-ally)}
.page .note-box--npc,.page .note-box--danger{border-color:var(--v-npc)}
.page .note-box--earth{border-color:var(--v-earth)}
.page .note-box--air{border-color:var(--v-air)}
.page .note-box--fire{border-color:var(--v-fire)}
.page .note-box--water{border-color:var(--v-water)}
.page .note-box--moira{border-color:var(--v-moira)}
.page .note-box--text{border-color:var(--v-text)}
.page .note-box--accent{border-color:var(--v-accent)}

.page .figure .caption{
  display:block; margin-top:.35em; color:var(--page-dim);
  font-family:var(--font-mono); font-size:8.5pt;
  letter-spacing:.02em; text-transform:uppercase;
}

/* =============================================================
   Print. @page size is injected by main.js so it tracks the
   selected trim size; everything else lives here.
   ============================================================= */
@media print{
  html,body{background:#fff; height:auto; overflow:visible; display:block}
  #bar,#editor,#drag{display:none !important}
  #split{display:block}
  #preview{
    overflow:visible; padding:0; background:none;
    print-color-adjust:exact; -webkit-print-color-adjust:exact;
  }
  .page{
    margin:0; box-shadow:none; break-after:page; zoom:1;
    print-color-adjust:exact; -webkit-print-color-adjust:exact;
  }
  .page:last-child{break-after:auto}
}
