/* Rushlight Books — hub mockup stylesheet (shared by every page)
   Palette: bone/cream page · ink text · rushlight amber accent. Type: EB Garamond (display) + Inter (UI). */
:root{
  --bg:#f5efe3; --card:#fcfaf4; --alt:#efe7d6; --ink:#26211b; --muted:#6c6153; --faint:#9a8f7d;
  --amber:#c8862c; --amberdark:#9a5f13; --deep:#1a1410; --border:#e4dac6;
  --serif:'EB Garamond',Georgia,serif; --sans:'Inter',system-ui,sans-serif;
  /* franchise bands */
  --endurance:#3d4b5a; --wireless:#8a6f47; --wayhouses:#5c7355; --keptflame:#b5732a;
}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--ink);font-family:var(--sans);line-height:1.6;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
.wrap{max-width:1080px;margin:0 auto;padding:0 28px}
.serif{font-family:var(--serif)}
.mock{background:var(--deep);color:#e9dcbf;text-align:center;font-size:12.5px;letter-spacing:.06em;padding:6px}

/* header */
header{border-bottom:1px solid var(--border)}
.nav{display:flex;align-items:center;justify-content:space-between;padding:20px 0}
.brand{display:flex;align-items:center;gap:11px}
.flame{width:26px;height:34px;flex:0 0 auto}
.brand .name{font-family:var(--serif);font-size:23px;font-weight:600;letter-spacing:.02em;line-height:1}
.brand .sub{font-size:10px;letter-spacing:.34em;color:var(--faint);text-transform:uppercase;margin-top:3px}
nav.links{display:flex;gap:26px;font-size:14.5px;color:var(--muted)}
nav.links a:hover,nav.links a.on{color:var(--ink)}

/* buttons */
.btn{display:inline-block;font-size:14px;font-weight:500;padding:9px 18px;border-radius:2px;border:1px solid var(--deep);background:var(--deep);color:#f5efe3;transition:.15s;cursor:pointer}
.btn:hover{background:transparent;color:var(--deep)}
.btn.amber{background:var(--amber);border-color:var(--amber);color:#2a1c05}
.btn.amber:hover{background:transparent;color:var(--amberdark)}
.btn.ghost{background:transparent;color:var(--deep)}
.btn.ghost:hover{background:var(--deep);color:#f5efe3}

/* type + sections */
.rule{width:44px;height:1px;background:var(--amber);margin:0 auto 26px}
.sec{padding:56px 0}
.sec.alt{background:var(--alt);border-top:1px solid var(--border);border-bottom:1px solid var(--border)}
.eyebrow{font-size:11px;letter-spacing:.28em;text-transform:uppercase;color:var(--faint);text-align:center;margin-bottom:8px}
.sec h2{font-family:var(--serif);font-weight:500;font-size:30px;text-align:center;margin-bottom:34px}
.pagehead{text-align:center;padding:56px 0 34px;border-bottom:1px solid var(--border)}
.pagehead h1{font-family:var(--serif);font-weight:500;font-size:40px;margin-bottom:10px}
.pagehead p{color:var(--muted);max-width:56ch;margin:0 auto;font-size:16.5px}

/* hero */
.hero{text-align:center;padding:78px 0 64px}
.hero h1{font-family:var(--serif);font-weight:500;font-size:46px;line-height:1.15;max-width:15ch;margin:0 auto 20px}
.hero p{font-size:18px;color:var(--muted);max-width:52ch;margin:0 auto 30px}
.hero .cta{display:flex;gap:14px;justify-content:center}

/* covers */
.cover{aspect-ratio:5/8;border-radius:3px;box-shadow:0 6px 22px rgba(30,22,10,.16);display:flex;flex-direction:column;justify-content:space-between;padding:16px 14px;color:#f0eae0}
.cover .ct{font-family:var(--serif);font-size:19px;line-height:1.1;font-weight:600}
.cover .ca{font-size:10px;letter-spacing:.14em;text-transform:uppercase;opacity:.82}
.cover .cs{font-size:9px;letter-spacing:.2em;text-transform:uppercase;opacity:.7}
.cover.sm .ct{font-size:15px}

/* featured book */
.feature{display:grid;grid-template-columns:200px 1fr;gap:38px;align-items:center;background:var(--card);border:1px solid var(--border);border-radius:6px;padding:34px}
.fq{font-family:var(--serif);font-style:italic;font-size:20px;color:var(--amberdark);margin-bottom:12px}
.feature h3{font-family:var(--serif);font-size:26px;font-weight:600;margin-bottom:4px}
.meta{font-size:12.5px;letter-spacing:.06em;color:var(--faint);text-transform:uppercase;margin-bottom:14px}
.feature p{color:var(--muted);font-size:15.5px;margin-bottom:20px;max-width:60ch}
.row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.ku{font-size:12.5px;color:var(--faint)}

/* franchise cards — real key art + the franchise wordmark in its own cover face */
.worlds{display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
.world{background:var(--card);border:1px solid var(--border);border-radius:6px;overflow:hidden;display:block;transition:.15s}
.world:hover{border-color:var(--amber);transform:translateY(-2px)}
.world .art{aspect-ratio:3/2;background-size:cover;background-position:center;position:relative;display:flex;align-items:flex-end;padding:18px 20px}
.world .art::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,rgba(12,10,8,.72) 0%,rgba(12,10,8,.28) 38%,rgba(12,10,8,0) 68%)}
.world .wm{position:relative;z-index:1;color:#f2e7d2;line-height:1.05}
.world .inner{padding:20px 22px 22px}
.world .pen{font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);margin-bottom:8px}
.world .tag{font-family:var(--serif);font-style:italic;font-size:17px;color:var(--amberdark);margin-bottom:9px}
.world p{font-size:14.5px;color:var(--muted);margin-bottom:14px}
.world .enter{font-size:13.5px;font-weight:500;color:var(--amberdark)}
/* the four locked cover faces (ref-cover-typography.md) */
.wm-endurance{font-family:'EB Garamond',Georgia,serif;font-weight:600;font-size:27px;letter-spacing:.20em;text-transform:uppercase}
.wm-wireless {font-family:'Lora',Georgia,serif;font-weight:600;font-size:24px;letter-spacing:.14em;text-transform:uppercase}
.wm-wayhouses{font-family:'Fraunces',Georgia,serif;font-weight:600;font-size:30px;letter-spacing:.01em}
.wm-keptflame{font-family:'Cinzel','Trajan Pro',Georgia,serif;font-weight:600;font-size:24px;letter-spacing:.22em;text-transform:uppercase}

/* catalogue grid */
.filters{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-bottom:34px}
.chip{font-size:13px;padding:6px 14px;border:1px solid var(--border);border-radius:20px;background:var(--card);color:var(--muted);cursor:pointer}
.chip.on{background:var(--deep);color:#f5efe3;border-color:var(--deep)}
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:24px}
.bk .cover{margin-bottom:10px}
.bk h4{font-family:var(--serif);font-size:17px;font-weight:600;line-height:1.2}
.bk .bm{font-size:12px;color:var(--faint);margin-top:2px}
.shelf{margin-bottom:44px}
.shelf .sh{display:flex;align-items:baseline;justify-content:space-between;border-bottom:1px solid var(--border);padding-bottom:8px;margin-bottom:20px}
.shelf .sh h3{font-family:var(--serif);font-size:23px;font-weight:600}
.shelf .sh .pen{font-size:12.5px;color:var(--faint)}

/* book detail */
.detail{display:grid;grid-template-columns:280px 1fr;gap:44px;align-items:start}
.detail h1{font-family:var(--serif);font-size:38px;font-weight:600;line-height:1.15;margin-bottom:6px}
.detail .blurb p{color:var(--muted);font-size:16px;margin-bottom:14px;max-width:62ch}
.buy{background:var(--card);border:1px solid var(--border);border-radius:6px;padding:20px;margin:24px 0}
.buy .row{margin-bottom:8px}
.facts{border-top:1px solid var(--border);padding-top:16px;margin-top:22px;font-size:13.5px;color:var(--muted)}
.facts div{display:flex;gap:10px;margin-bottom:5px}
.facts span:first-child{color:var(--faint);min-width:110px}

/* authors */
.pens{display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
.pen-card{background:var(--card);border:1px solid var(--border);border-radius:6px;padding:26px}
.pen-card h3{font-family:var(--serif);font-size:24px;font-weight:600}
.pen-card .shelf-line{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);margin:2px 0 12px}
.pen-card p{font-size:14.5px;color:var(--muted);margin-bottom:14px}

/* newsletter */
.news{background:var(--deep);color:#f2e8d4;border-radius:8px;padding:46px 40px;text-align:center}
.news h2{font-family:var(--serif);color:#f6eeda;font-size:29px;font-weight:500;margin-bottom:10px}
.news p{color:#cdbfa4;max-width:50ch;margin:0 auto 22px;font-size:15.5px}
.news form{display:flex;gap:10px;max-width:440px;margin:0 auto}
.news input{flex:1;padding:12px 15px;border-radius:2px;border:1px solid #4a4030;background:#241d15;color:#f2e8d4;font-family:var(--sans);font-size:14.5px}
.news input::placeholder{color:#8a7c63}
.news small{display:block;margin-top:12px;color:#8a7c63;font-size:12px}

/* prose */
.prose{max-width:62ch;margin:0 auto}
.prose p{font-size:17px;color:var(--muted);margin-bottom:18px}
.prose p.lead{font-family:var(--serif);font-size:22px;color:var(--ink);line-height:1.5}

/* footer */
footer{border-top:1px solid var(--border);padding:44px 0 30px;margin-top:16px}
.fcols{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:30px;margin-bottom:30px}
.fcols h4{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);margin-bottom:12px}
.fcols a{display:block;font-size:14px;color:var(--muted);margin-bottom:8px}
.fcols a:hover{color:var(--ink)}
.fbrand .name{font-family:var(--serif);font-size:20px;font-weight:600}
.fbrand p{font-size:13px;color:var(--muted);margin-top:8px;max-width:34ch}
.legal{border-top:1px solid var(--border);padding-top:18px;display:flex;justify-content:space-between;font-size:12.5px;color:var(--faint);flex-wrap:wrap;gap:8px}

@media(max-width:860px){.grid{grid-template-columns:repeat(2,1fr)}.detail{grid-template-columns:1fr}}
@media(max-width:760px){
  .feature{grid-template-columns:1fr;text-align:center}.feature .cover{width:170px;margin:0 auto}
  .worlds,.pens{grid-template-columns:1fr}.fcols{grid-template-columns:1fr 1fr}.hero h1{font-size:36px}nav.links{display:none}
}

/* --- generator additions (appended to _brand/mockups/rushlight.css at build) ------- */

/* ⛔ .cover in rushlight.css was written for a DIV (the mockup drew fake covers with the title
   typeset inside it, hence padding + flex + a text colour). The generator uses a real <img>.
   Padding on an <img> shows the PAGE BACKGROUND inside the element — which is what put a cream
   "white border" around all four Kettle covers. The art is clean; the class was for a different
   element. Reset everything the div version assumed. */
.cover{width:100%;height:auto;aspect-ratio:5/8;object-fit:cover;border-radius:3px;
  box-shadow:0 6px 22px rgba(30,22,10,.16);display:block;
  padding:0;background:none;border:0}
.cover.sm{box-shadow:0 4px 14px rgba(30,22,10,.14)}
.coverlink{display:block}
.detail img.cover{max-width:280px}
.blurb p{color:var(--muted);font-size:16px;margin-bottom:14px;max-width:62ch}
.bk.sm{display:block}
.wgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.wcard{display:block;background:var(--card);border:1px solid var(--border);border-radius:6px;
  padding:20px 22px;transition:.15s}
.wcard:hover{border-color:var(--accent);transform:translateY(-2px)}
.wcard h4{font-size:19px;font-weight:600;margin-bottom:6px}
.wcard p{font-size:14px;color:var(--muted)}
.news form input:disabled,.news form button:disabled{opacity:.5;cursor:not-allowed}
.news small strong{color:#e8c98a}

/* ⛔ CLASS-NAME MISMATCH — the real reason "The Wireless War" looked small.
   build_site derives the class by stripping hyphens: the-wireless-war -> .wm-wirelesswar
   but rushlight.css only defines .wm-wireless. No rule matched, so the wordmark rendered
   completely UNSTYLED — not merely small, but sentence-case and untracked while the other
   three were uppercase and letter-spaced. (The other three survive by luck: wayhouses,
   endurance and keptflame happen to collapse to the names the stylesheet already uses.)
   Defining the derived name here fixes it without touching the shared design system.
   Lora's caps run smaller than Fraunces/Cinzel, so it is sized up slightly to sit optically
   level with its neighbours. */
.wm-wirelesswar{font-family:'Lora',Georgia,serif;font-weight:600;font-size:26px;
  letter-spacing:.13em;text-transform:uppercase}
/* --- the home page's free-book row: four peers, four-up -----------------------------
   Reuses .grid (4 cols → 2 at 860px) and .bk, plus the bits a taller card needs: the
   title becomes a link, a pen-name line, a line of copy, and a per-franchise CTA.
   ⛔ NO HERO. The home page used to lead with a single full-width featured book, which
   made one world — always the same one — read as the house default. Four worlds, four
   identical cards (hub plan §11.6). This row's four-up shape is Rowan's own instruction
   and is deliberately NOT differentiated; the two sections around it are.
   ⛔ The button on each card points at THAT franchise's own MailerLite page. */
.mgrid{align-items:start}
.mg .bkt a{color:inherit}
.mg .bkt a:hover{color:var(--amberdark)}
.mg .bm{margin-top:4px}
.mg .bpen{font-size:12px;color:var(--faint);margin-top:2px}
.mg p{font-size:14px;color:var(--muted);margin-top:10px}
.mg .row{margin-top:12px}
.mgbtn{font-size:13px}
/* the free book's art is a real cover on three of the four worlds and a typographic plate
   where the catalogue has none — both must occupy the same box, or the row stops reading
   as four peers. .bk .cover already carries the 10px gap, so the wrapper must not add a
   second one. */
.mg-art{display:block;margin-bottom:10px}
.mg-art .cover,.mg-art .plate{margin-bottom:0}

/* --- the home page's Book One SHELF (28 Jul 2026) ----------------------------------
   ⛔ WHY THIS IS NOT A GRID. The free-book row above and the worlds row below both show
   four items; when this one did too, in the same card shape as the row above it, three
   consecutive sections read as one long list and the page lost its shape. So this is a
   shelf, not a card grid: small covers in one tight CENTRED row standing on a hairline,
   with the blurb paragraph and the bordered button removed. It is narrower than the
   column it sits in — that is the point; it should not fill the width the way the row
   above it does.
   Nothing here reuses .bk, so the .bk rules further down do not reach it and it carries
   its own type + tap-target sizes. */
.b1shelf{display:flex;flex-wrap:wrap;justify-content:center;gap:18px 44px;
  border-bottom:1px solid var(--border);padding-bottom:26px}
.b1item{width:150px;text-align:center}
.b1item .cover{margin-bottom:8px}
.b1item .bkt{font-family:var(--serif);font-size:16px;font-weight:600;line-height:1.25}
/* 16px x 1.25 = 20 + 20 padding = 40, so min-height carries it to the 44px floor */
.b1item .bkt a{display:inline-block;min-height:44px;padding:10px 2px;color:inherit}
.b1item .bkt a:hover{color:var(--amberdark)}
.b1item .bm{font-size:12px;color:var(--faint);margin-top:-2px;line-height:1.35}
/* the notify link — a DIFFERENT intent from the amber "Get a free book" buttons, so
   deliberately a different affordance as well as different words.
   13px x 1.6 = 20.8 + 24 = 44.8 */
.b1notify{display:inline-block;font-size:13px;line-height:1.6;color:var(--amberdark);
  padding:12px 6px;margin:2px -6px 0}
.b1notify:hover{text-decoration:underline}
/* a phone is 334px of content at 390px wide: 128 + 22 + 128 = 278, so it stays two-up
   rather than collapsing to a single column of four */
@media(max-width:760px){
  .b1shelf{gap:14px 22px;padding-bottom:20px}
  .b1item{width:128px}
  .b1item .bkt{font-size:15px}
}

/* --- the home page's worlds row: the widest moment on the site ----------------------
   ⛔ THE ONE PLACE THE 1080px COLUMN IS BROKEN, and only here. These are the only items
   on the home page that are PLACES rather than books, and the only ones with key art;
   letting them out past the text column is what makes the section read as a different
   moment from the two book rows above it instead of a third row of four.
   .worlds is already 2-across in the base stylesheet — this widens the container, not
   the column count, so the CARDS get bigger rather than more numerous.
   Card width = (1240 − 56 padding − 30 gap) / 2 = 577px, which is what KEYART_W = 1200
   in build_site.py is sized to serve at 2x DPI. Change one and change the other. */
.wrap.wide{max-width:1240px}
.worlds.big{gap:30px}

/* --- the world, split one index per franchise (27 Jul 2026) -------------------------
   Each world's index now sits on ITS OWN franchise page at #world (no new route — see
   world_section() for why a third `/world*` path was rejected). `/world/` keeps its URL
   and becomes a chooser of four. The heading is the whole point either way: a reader must
   never meet one world's people presented as another's. */
/* the chooser's cards carry an <h2> (they sit directly under the page <h1>, and a level
   may not be skipped). .sec h2 would centre it at 30px with a 34px gap, so it is reset to
   the card heading it actually is — same specificity as .sec h2, and extra.css is later. */
.wcard h2{font-family:var(--serif);font-size:22px;font-weight:600;text-align:left;
  margin-bottom:6px;line-height:1.25}
/* the franchise with no public world entities yet: present, honest, and not a link to
   nothing. A <div>, so there is nothing to click and nothing for a crawler to follow.
   ⛔ Quieted with the dashed --alt treatment the greyed series shelf uses, NOT with
   opacity: opacity would blend the copy toward the card and drop it under 4.5:1, and this
   card's whole job is to say clearly that the world is coming. --muted on --alt = 4.92:1. */
.wcard.off{background:var(--alt);border-style:dashed;cursor:default}
.wcard.off:hover{border-color:var(--border);transform:none}
/* four worlds, four peers: 2x2, not a 3-across row with one orphan underneath.
   Must stay ABOVE the 760px rule below, which collapses every .wgrid to one column. */
.wchoose{grid-template-columns:repeat(2,1fr)}

/* --- portraits: an enhancement layered on the card, never a slot (28 Jul 2026) -------
   ⛔ ONE ENTITY IN SEVENTY-ONE HAS ART. So the design problem is not "how does the picture
   look" — it is "how do the seventy cards WITHOUT one look standing beside it". Two rules
   follow, and they are the whole of this block:
     1. FLOAT, never grid. A float occupies space only when the element exists, so a card
        with no portrait is byte-for-byte and pixel-for-pixel the card the site already
        renders. There is no reserved box, no placeholder, no grey hole to explain.
     2. SMALL AND ROUND. At 56px it reads as an avatar decorating a text card, not as the
        card's hero image. A large portrait would make the row it sits in look like a grid
        of missing pictures with one filled; an avatar looks like a card that happens to
        have a face on it — which is exactly the truth.
   The text wraps around it, so nothing shifts and no min-height is needed. */
.wcard .wthumb{float:right;width:56px;height:56px;border-radius:50%;object-fit:cover;
  /* the master is a 2:3 headshot with the face high in frame; a centred square crop would
     cut the chin. 22% from the top puts the eyes just above the circle's centre. */
  object-position:center 22%;margin:2px 0 6px 14px;
  border:1px solid var(--border);box-shadow:0 2px 8px rgba(30,22,10,.14)}

/* the entity's own page: the portrait sits ABOVE the entry, not floated beside it.
   ⛔ MEASURED, not preferred. Floated right at 200px it took 226px out of the .prose column's
   570px reading measure and left the text at 32–38 characters a line — visibly ragged, and well
   under the ~45ch floor for comfortable reading. The picture is not worth breaking the one thing
   the page is for. As a block above the prose the entry keeps its full 58ch measure, the portrait
   still reads at a proper size, and it needs no responsive exception because it never competes
   with the text for width. An entity with no portrait gets the page it has today, unchanged. */
.wportrait{display:block;width:190px;aspect-ratio:2/3;object-fit:cover;object-position:center 22%;
  border-radius:4px;margin:6px 0 24px;box-shadow:0 6px 22px rgba(30,22,10,.16)}

@media(max-width:760px){.wgrid{grid-template-columns:1fr}}

/* ===================================================================================
   THE IA PASS — nav dropdowns, franchise/series/author pages, shelf labels, filters
   (hub plan §11, built 27 Jul 2026)
   =================================================================================== */

/* --- nav: two axes, Books ▾ and Worlds ▾ -------------------------------------------
   ⛔ NO JAVASCRIPT OPENS THESE. They open on :hover AND on :focus-within, which means a
   tap works (tapping the <button> focuses it) and Tab works. A hover-only menu is
   invisible to every phone reader, and the phone is where the back-of-book QR lands. */
nav.links{align-items:center;position:relative}
.ni{position:relative}
.nt{background:none;border:0;padding:0;font:inherit;color:var(--muted);cursor:pointer;
  display:inline-flex;align-items:center;gap:5px;line-height:inherit}
.nt::after{content:"▾";font-size:9px;opacity:.75;position:relative;top:1px}
.nt:hover,.nt.on,.ni:hover .nt,.ni:focus-within .nt{color:var(--ink)}
.menu{display:none;position:absolute;left:-16px;top:100%;padding-top:14px;z-index:80}
.ni:hover>.menu,.ni:focus-within>.menu{display:block}
.mpane{background:var(--card);border:1px solid var(--border);border-radius:6px;padding:8px 0;
  box-shadow:0 12px 34px rgba(30,22,10,.16);min-width:238px}
.mf{display:flex;align-items:baseline;justify-content:space-between;gap:18px;padding:9px 18px;
  font-size:14.5px;color:var(--ink)}
.mfsub{font-size:11.5px;color:var(--faint)}
.mchev{color:var(--faint);font-size:15px}
.mrow{position:relative}
.mrow:hover>.mf,.mrow:focus-within>.mf{background:var(--alt);color:var(--amberdark)}
.mseries{display:none;position:absolute;left:100%;top:-9px;min-width:250px;padding:8px 0;
  background:var(--card);border:1px solid var(--border);border-radius:6px;
  box-shadow:0 12px 34px rgba(30,22,10,.16)}
.mrow:hover>.mseries,.mrow:focus-within>.mseries{display:block}
.msh{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);
  padding:4px 18px 8px}
.ms{display:block;padding:7px 18px;font-size:14px;color:var(--ink)}
a.ms:hover{background:var(--alt);color:var(--amberdark)}
/* ⛔ the greyed, unclickable series (hub plan §11.3). A <span>, never an <a>: there is no
   page, so there must be nothing to click and nothing for a crawler to follow. */
.ms.off{color:var(--faint);cursor:default}
.ms.off i.pill{display:inline-block;margin-top:5px}

/* ⛔ TOUCH + NARROW — the Books menu is FOUR ROWS, not thirty-seven.
   The flyout cannot fly out on a phone, so every .mseries used to be forced open: ~37 rows in a
   560px scroll pane, 29 of them dead grey names, as the primary navigation on the device the
   back-of-book QR lands on. It worked; it just asked a reader to scroll a wall of things they
   cannot click. Now: the four franchises, each with one "+N more in this world →" row into the
   franchise page — where the same names sit under "Still to come", which frames them as ambition
   rather than as a broken menu. Desktop hover/focus behaviour is untouched: it works there. */
.mmore{display:none}
@media(hover:none),(max-width:900px){
  .mseries,.mrow:hover>.mseries,.mrow:focus-within>.mseries{display:none}
  .mmore{display:block;padding:11px 18px 13px 18px;font-size:13px;color:var(--amberdark)}
  .mrow+.mrow{border-top:1px solid var(--border)}
  .mf{font-weight:600;padding-bottom:4px}
  .mpane{max-height:min(70vh,560px);overflow-y:auto}
}
/* rushlight.css hides the whole nav below 760px — which left a phone with no menu at all.
   Wrap it onto its own row instead. */
@media(max-width:760px){
  .nav{flex-wrap:wrap;row-gap:12px}
  nav.links{display:flex;order:3;width:100%;gap:20px;padding-top:12px;
    border-top:1px solid var(--border)}
  .menu{left:0;padding-top:10px}
  .mpane{min-width:min(86vw,320px);max-width:calc(100vw - 44px)}
}

/* --- shelf labels: genre(+style) + audience ---------------------------------------- */
.labs{display:flex;gap:7px;flex-wrap:wrap;margin:8px 0 10px}
.pagehead .labs,.worlds .labs{justify-content:center}
.world .labs{justify-content:flex-start;margin:0 0 9px}
.lab{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--muted);
  border:1px solid var(--border);background:var(--card);border-radius:20px;padding:3px 10px}
/* ⛔ over KEY ART, so the background is whatever the photograph happens to be. At .32 the label
   measured 1.73:1 against a light patch of art — the scrim has to carry the contrast on its own,
   because the art underneath cannot be relied on. At .68 the worst case (pure white art) is
   5.71:1. */
.labs.onart .lab{color:#f0e6d2;border-color:rgba(242,231,210,.52);background:rgba(12,10,8,.68)}
.shelflabs{margin:-8px 0 16px}
/* ⛔ THE STYLE QUALIFIER IS NOT A GENRE (Rowan, 28 Jul 2026). "literary" is the register these
   books are written in, and it rides INSIDE the primary genre chip after a middot — lower-case and
   italic against its chip-mate's uppercase tracking, so it reads as a qualifier of the shelf rather
   than as a second shelf. It is never a filter chip and never a chip of its own; a reader filtering
   by genre must not meet it standing between Dystopian Fiction and cozy fantasy.
   Contrast measured, not estimated: --muted (#5f5648) on --card = 5.79:1, so the qualifier keeps
   the same colour as the chip and is distinguished by CASE and SLANT, not by going fainter — the
   faint tones on this palette are what the 27 Jul accessibility pass had to climb out of. */
.lab .qual{font-style:italic;text-transform:lowercase;letter-spacing:.04em}
.lab .qual::before{content:"·";font-style:normal;margin:0 5px 0 4px;opacity:.6}
/* ⛔ THE SECONDARY GENRES GET NO SEPARATE TREATMENT, and that is a measured decision rather than
   an omission. They were first given a dashed border to mark them as secondary — but --border on
   --card measures 1.33:1, so solid-vs-dashed was a distinction no reader could actually see, and
   the alternatives (a lighter tone, lower opacity) all buy the distinction by dropping the text
   under the 4.5:1 floor the 27 Jul pass exists to hold. The primary shelf is already marked, twice
   and legibly: it comes FIRST, and it is the only chip carrying the style qualifier. Three chips
   reading as three shelves is also simply true — these books do sit on all three. */

/* --- /books filters ---------------------------------------------------------------- */
.filters{align-items:center;gap:10px 8px}
.fgroup{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.flab{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);
  margin-right:2px}
.filters+.shelf{margin-top:8px}
.shelf .sh h3 a:hover,.shelf .sh .shx a:hover,.shelf .sh .pen a:hover,
.bk .bkt a:hover{color:var(--amberdark)}

/* --- franchise page ---------------------------------------------------------------- */
.fhero{background-size:cover;background-position:center;position:relative}
.fhinner{background:linear-gradient(to top,rgba(12,10,8,.86) 0%,rgba(12,10,8,.5) 55%,rgba(12,10,8,.3) 100%);
  padding:96px 0 40px;text-align:center;color:#f2e7d2}
.fhero .wm{color:#f4ead6;line-height:1.05;display:block;margin-bottom:14px}
.ftag{font-style:italic;font-size:20px;color:#e9c98f;margin-bottom:10px}
.fmeta{font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;color:#cdbfa4}
.fmeta a:hover{color:#fff}
.worlds.one{grid-template-columns:1fr;max-width:520px;margin:0 auto}

/* --- the greyed "still to come" shelf ----------------------------------------------- */
.shelf.coming .sh{border-bottom-style:dashed}
.greylist{display:flex;flex-wrap:wrap;gap:10px}
.greyed{font-family:var(--serif);font-size:18px;color:var(--faint);background:var(--alt);
  border:1px dashed var(--border);border-radius:4px;padding:7px 15px;cursor:default}
.greynote{font-size:13px;color:var(--faint);margin-top:14px;max-width:60ch}

@media(max-width:760px){.fhinner{padding:64px 0 32px}.ftag{font-size:17px}}

/* ===================================================================================
   1 · THE ACCESSIBILITY FLOOR (27 Jul 2026)
   Every ratio below is measured against the REAL palette, not estimated. AA wants 4.5:1
   for normal text; nothing on this site is large enough to claim the 3:1 allowance.
   =================================================================================== */
:root{
  /* --faint was #9a8f7d: 2.78:1 on --bg, 2.59:1 on --alt, 3.05:1 on --card — and it carried
     .eyebrow 11px, .meta 12.5px, .bm 12px, .legal 12.5px and the footer headings. All of the
     small print on the site was below the floor.  #776b5b -> bg 4.54, card 4.98. */
  --faint:#776b5b;
  /* --amberdark was #9a5f13: 4.25:1 on --alt, which is where the menu hovers live.
     #8a540f -> alt 5.09, bg 5.46, card 6.00. Every other amberdark use gets better too. */
  --amberdark:#8a540f;
  /* the franchise accent, resolved per franchise below; amber is the house default */
  --accent:var(--amber); --accent-rgb:200,134,44;
}
/* --alt is a darker ground, so --faint is re-resolved darker ON it rather than darkening the
   one token until it collapses into --muted:  #706555 -> 4.64:1 on --alt. */
.sec.alt{--faint:#706555}
/* the unreleased series names are meaningful, not chrome — muted, 4.92:1 on --alt */
.greyed{color:var(--muted)}
/* on --deep: #8a7c63 measured 4.47 (12px) and the same value was the input placeholder.
   #a2937a -> 6.07:1 on --deep, 5.54:1 on the input's own #241d15. */
.news small,.news input::placeholder{color:#a2937a}

/* --- "Coming soon" stops being chrome ---------------------------------------------
   On a pre-launch site this is the most decision-relevant string on a book card: it is the
   answer to "can I have this today?". It was 12px of the faintest tone in the palette.
   A bordered pill in --muted (5.79:1 on --card, 5.28:1 on --bg). */
.pill{display:inline-block;font-size:11px;line-height:1.55;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);border:1px solid var(--border);
  background:var(--card);border-radius:20px;padding:2px 10px;font-style:normal;white-space:nowrap}
.pill.free{color:var(--amberdark);border-color:var(--amber)}   /* 6.00:1 on --card */
.bk .bm{margin-top:7px}
.sec.alt .pill,.news .pill{background:var(--bg)}

/* --- headings: one level at a time -------------------------------------------------
   80 of 81 pages skipped a level, 57 of them purely because the shared footer put <h4> under
   the page <h1>. The footer headings are <h2 class=fh> now; the visual treatment is identical. */
.fcols .fh{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);
  margin-bottom:12px;font-weight:600}
/* the series title on a shelf is the section heading (was <h3> under an <h1>) */
.shelf .sh .shx{font-family:var(--serif);font-size:23px;font-weight:600;text-align:left;
  margin-bottom:0}
/* a book card's title (was <h4> under an <h2>) */
.bk .bkt{font-family:var(--serif);font-size:17px;font-weight:600;line-height:1.2}
.bk.sm .bkt{font-size:15px}
/* an author / free-book card's own title (was <h3> under the page <h1> on /authors and /free) */
.pen-card .pct{font-family:var(--serif);font-size:24px;font-weight:600;text-align:left;
  margin-bottom:0}
/* (`.feature .ft` lived here — the home page's single featured book. The feature was retired
   27 Jul 2026 for the four-up free-book row above, so the rule is gone with the element it
   styled. `.feature` itself is still declared in the base stylesheet, which is design-source.) */

/* --- tap targets: 44px minimum on anything you can press ---------------------------
   Nothing on the site reached it. The nav buttons matter most — 55x23.2 was the entire mobile
   menu affordance. Height comes from PADDING, never from font-size: the type stays as designed. */
.nt,nav.links>a{min-height:44px;display:inline-flex;align-items:center}
.brand{min-height:44px}
.btn{padding:11px 18px}                    /* 14px x 1.6 + 22 + 2 = 46.4 */
.mgbtn{font-size:13px;padding:11px 14px}   /* 13px x 1.6 + 22 + 2 = 44.8 */
.chip{padding:11px 16px;min-height:44px}
.mf,.ms{padding-top:11px;padding-bottom:11px}
.bk .bkt a{display:inline-block;min-height:44px;padding:10px 0}
.bk .cover{margin-bottom:0}
.fcols a{padding:11px 0;margin-bottom:0}   /* 14px x 1.6 + 22 = 44.4 */
/* the shelf/card title links measured 30-31px; padding takes them past 44 without moving the type */
.shelf .sh .shx a,.pen-card .pct a{display:inline-block;padding:7px 0}
/* the franchise·author byline under a shelf head — 15px tall, in a line of text. Padded out and
   pulled back by the same amount, so the target grows and the baseline does not move. */
.shelf .sh .pen a,.fmeta a,.meta a{display:inline-block;padding:15px 4px;margin:-15px -4px}

/* measured over the REAL key art (worst pixel behind the type, not an average): the franchise
   tagline sat at 4.18:1 on the Wireless War hero, where the art goes lightest. */
.ftag{color:#f2dcb0}

/* ===================================================================================
   2 · THE FOUR WORLDS — an accent, never a reskin
   rushlight.css has declared these four colours since day one and used them zero times, so
   all four worlds rendered in the same cream card with the same amber hover.
   ⛔ Rushlight is the landlord and the franchises are tenants: the accent may tint a rule, a
   border or a scrim. No franchise gets its own background, and NO TEXT is set in an accent —
   Kept Flame's #b5732a is 3.69:1 on --card, below the floor for body copy. .btn.amber is
   deliberately untouched: it passes at 5.45:1 and stays that way on all four pages.
   =================================================================================== */
[data-franchise="the-endurance"]   {--accent:#3d4b5a;--accent-rgb:61,75,90}    /* 8.55:1 on card */
[data-franchise="the-wireless-war"]{--accent:#8a6f47;--accent-rgb:138,111,71}  /* 4.53:1 */
[data-franchise="the-wayhouses"]   {--accent:#5c7355;--accent-rgb:92,115,85}   /* 4.98:1 */
[data-franchise="the-kept-flame"]  {--accent:#b5732a;--accent-rgb:181,115,42}  /* 3.69:1 — non-text only */
.rule{background:var(--accent)}
.world .inner{border-top:3px solid var(--accent)}
.world:hover{border-color:var(--accent)}
/* the franchise hero: the house scrim, with this world's colour warming it */
body[data-franchise] .fhinner{background:
  linear-gradient(to top,rgba(12,10,8,.86) 0%,rgba(12,10,8,.5) 55%,rgba(12,10,8,.3) 100%),
  linear-gradient(to top,rgba(var(--accent-rgb),.55) 0%,rgba(var(--accent-rgb),.18) 100%)}
/* the franchise page's own CTA block */
body[data-franchise] .news{border-top:3px solid var(--accent)}

/* ===================================================================================
   3 · THE CONVERSION PATH — /free, and the classes that were never defined
   =================================================================================== */
/* .tag had NO rule outside `.world .tag`, so the magnet's title — the actual name of the free
   book, on the only live conversion page — rendered as unstyled body copy. */
.tag{font-family:var(--serif);font-style:italic;font-size:18px;color:var(--amberdark);
  margin-bottom:8px}
/* likewise .shelf-line.sub on /authors: the author's SHELF and the franchise's GENRE are
   different tiers (see PEN_SHELF) and were rendering identically, which made the distinction
   the two lines exist to draw invisible. */
.pen-card .shelf-line{margin:2px 0 4px}
.pen-card .shelf-line.sub{font-size:11px;letter-spacing:.04em;text-transform:none;
  color:var(--muted);font-style:italic;margin:0 0 12px}
/* the free-book cards: a cover, because a cover is what a reader recognises as a book */
.free-card{display:grid;grid-template-columns:104px 1fr;gap:20px;align-items:start}
.fc-art{display:block}
.fc-cover{width:104px}
.fc-text .tag{margin-top:2px}
/* where the magnet is not in the catalogue there is no cover to show and none is invented —
   a typographic plate instead. CSS, so it costs no bytes and cannot 404. */
/* the accent band is a BACKGROUND layer, not a border-top. With no side borders a
   border-top curls around the 3px radius and terminates against nothing, leaving a
   small tail at each top corner; a background band is clipped by the radius and
   follows the curve. The radius stays — it matches .cover (rushlight.css:52) and the
   real cover images the plate stands beside. */
.plate{aspect-ratio:5/8;border-radius:3px;color:#f2e7d2;
  background:linear-gradient(var(--accent) 0 3px,transparent 3px) var(--deep);
  display:flex;flex-direction:column;justify-content:space-between;padding:14px 12px;
  box-shadow:0 6px 22px rgba(30,22,10,.16)}
.plate .pt{font-size:15px;line-height:1.15;font-weight:600}
.plate .pb{font-size:7.5px;letter-spacing:.16em;text-transform:uppercase;color:#c9b998}
/* ⛔ SCOPED TO .free-card. Unscoped, this capped EVERY .plate at 104px — including the
   full-width plate in the home page's four-up free-book row, which would have made the one
   world without a catalogue cover a quarter the size of its three peers on a phone. */
@media(max-width:420px){.free-card{grid-template-columns:1fr}
  .free-card .fc-cover,.free-card .plate{max-width:104px}}
