/* ==================================================================
   TANSTAFL — web serial
   Art layers sit fixed behind everything; the reading panel floats over.
   Per-arc image URLs arrive as custom properties in an inline <style>,
   so adding an arc never means editing this file.
   ================================================================== */

:root{
  /* Ratios measured by tests/test_contrast.py on 2026-09-14, over the blue panel. The
     three under 7:1 are Amber's call to retune; see WEB_SERIAL_NOW.md. */
  --ink:#f5ebdd;        /* 10.1:1 over the panel at the art's brightest point  */
  --ink-soft:#cfc4a8;   /* 6.86:1 — just under AAA. Was #b9ae94 at 5.2:1        */
  --ink-faint:#cbc4b3;  /* 6.84:1 — Was #8a8271 at 3.0:1, below even AA         */
  --accent:#dec185;     /* 6.84:1 — Was #c9a86a at 5.0:1                        */
  --panel-alpha:.90;                       /* AAA holds to .81 — measured */
  /* Slate blue, sampled from Amber's mockup 2026-09-14 — trial. Was the warm grey
     rgba(38,36,34,…) with --base #22241f; revert by restoring those two and the
     phone masthead gradient below. */
  --panel:rgba(31,38,46,var(--panel-alpha));
  --base:#1f262e;
  --rule:rgba(245,235,221,.16);
  /* The homepage container, Amber's own hex from her mockup (2026-09-15). Opaque,
     and deliberately NOT --base: it is bluer, and it is the surround that makes
     the content box read, so it must not move with --base. */
  --home-frame:#1d2733;
  --measure:34em;
  --reading-size:19px;   /* reader-adjustable; 19px is the shipped default */
  --panel-max:720px;     /* reader-adjustable column width                 */
  --panel-gutter:460px;  /* art left visible either side of the column     */
  --serif:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,serif;
  --sans:"Nunito","Avenir Next","Helvetica Neue",system-ui,sans-serif;
}

*{box-sizing:border-box}
html{background:var(--base);-webkit-text-size-adjust:100%}
body{margin:0;background:var(--base);color:var(--ink);font-family:var(--serif);
     min-height:100vh;position:relative}

.skip{position:absolute;left:-9999px;top:0;z-index:50;background:var(--base);
      color:var(--ink);padding:.7rem 1.1rem;font-family:var(--sans);font-size:14px}
.skip:focus{left:8px;top:8px}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* ---------- art layers ---------- */
.layers{display:none}
.hero{display:none}
body.plain .layers,body.plain .hero,
html.plain .layers,html.plain .hero{display:none !important}

/* ---------- the reading panel ---------- */
/* The masthead outranks main: it is z-index:1 and later in the DOM, so it would
   otherwise paint over the reader panel dropping out of the masthead below it. */
main,footer{position:relative;z-index:1}
.masthead{position:relative;z-index:2}

main{width:min(var(--panel-max),100vw - var(--panel-gutter));margin:0 auto;background:var(--panel);
     padding:3.5rem 3.25rem 6rem}
/* Transparent, and no padding: .home covers main edge to edge, the frame's border
   supplies every margin, and the content's own var(--panel) must be the ONLY panel
   between the text and the art. Leave main's background on and it composites twice.
   The 6rem that used to be main's bottom padding is now the frame's bottom border,
   so the footer still gets its breathing room. */
.home-page main{background:none;padding:0}
.masthead{width:min(var(--panel-max),100vw - var(--panel-gutter));margin:0 auto;background:var(--panel);
     padding:1.4rem 3.25rem .1rem;display:flex;align-items:center;gap:1.2rem;
     flex-wrap:wrap;font-family:var(--sans)}
footer{width:min(var(--panel-max),100vw - var(--panel-gutter));margin:0 auto 4rem;background:var(--panel);
     padding:1.6rem 3.25rem 2.2rem;font-family:var(--sans);font-size:13px;
     color:var(--ink-soft);border-top:1px solid var(--rule)}
footer p{margin:.3rem 0}

.wordmark{font-family:var(--sans);font-weight:800;letter-spacing:.14em;
     text-transform:uppercase;font-size:14px;color:var(--ink);text-decoration:none;
     margin-right:auto}
/* The homepage logo already says the name. Hidden, not removed: its margin is
   what holds the nav on the right, so the nav stays exactly where it was. */
.home-page .wordmark{visibility:hidden}
.masthead nav{display:flex;gap:1.1rem;font-size:14px}
.masthead a{color:var(--ink-soft);text-decoration:none}
.masthead a:hover,.masthead a:focus{color:var(--ink)}
a{color:var(--accent)}

/* ---------- reader controls ---------- */
.reader{position:relative}
#reader-toggle,.reader-panel button{font-family:var(--sans);font-size:12px;
     color:var(--ink-soft);background:transparent;border:1px solid var(--rule);
     border-radius:5px;padding:.32rem .6rem;cursor:pointer}
#reader-toggle:hover,.reader-panel button:hover{color:var(--ink);border-color:var(--ink-soft)}
.reader-panel button[aria-pressed="true"]{color:var(--ink);border-color:var(--accent)}
.reader-panel button[aria-disabled="true"]{opacity:.4;cursor:default}
.reader-panel button[aria-disabled="true"]:hover{color:var(--ink-soft);border-color:var(--rule)}
.t-short{display:none}

/* Opaque, not var(--panel): the panel floats over the parallax, and moving art behind
   small controls is unreadable. */
.reader-panel{position:absolute;top:calc(100% + .5rem);right:0;z-index:10;
     background:var(--base);border:1px solid var(--rule);border-radius:8px;
     padding:.9rem 1rem;min-width:17rem;font-family:var(--sans)}
.reader-row{display:flex;align-items:center;gap:.5rem}
.reader-row + .reader-row{margin-top:.6rem}
.reader-label{font-size:11px;letter-spacing:.1em;text-transform:uppercase;
     color:var(--ink-faint);min-width:6.2em}
#size-value{font-size:12px;color:var(--ink-soft);min-width:4.6em;text-align:center}


/* ---------- prose ---------- */
.prose p,.home p,.notfound p{font-size:var(--reading-size);line-height:1.65;margin:0 0 1.35em;
     max-width:var(--measure);text-wrap:pretty}
.prose em{font-style:italic}
.prose p:first-child{margin-top:0}
hr.scene{border:0;text-align:center;margin:2.6em 0}
hr.scene::before{content:"* * *";color:var(--ink-faint);letter-spacing:.55em;font-size:15px}

h1{font-size:calc(var(--reading-size) * 31 / 19);font-weight:400;line-height:1.2;margin:0 0 .25em;letter-spacing:.01em}
h2{font-size:15px;font-family:var(--sans);font-weight:800;letter-spacing:.13em;
   text-transform:uppercase;color:var(--ink-soft);margin:2.6rem 0 .9rem}

.chapter-head{margin-bottom:2.2rem}
.chapter-num{font-family:var(--sans);font-size:12px;letter-spacing:.15em;
     text-transform:uppercase;color:var(--ink-soft);margin:0 0 .5rem}
.chapter-date{font-family:var(--sans);font-size:12px;color:var(--ink-faint);margin:.6rem 0 0}

/* Chapter icons. Her picture is 380x380 with the painted box at 36,35, 310 across
   (ICON_CANVAS and ICON_BOX in build.py; a test ties the numbers). The grid cell is
   the box, so the box sits flush with the column and the art spills into main's
   padding. has-icon comes from the inline script: scripts off, today's header. */
.chapter-icon{display:none}
.chapter-head.has-icon{--icon-box:158px;display:grid;
     grid-template-columns:var(--icon-box) minmax(0,1fr);column-gap:23px;align-items:center}
.has-icon .chapter-icon{display:block;position:relative;
     width:var(--icon-box);height:var(--icon-box)}
.chapter-icon img{position:absolute;max-width:none;height:auto;
     left:calc(var(--icon-box) * -36 / 310);top:calc(var(--icon-box) * -35 / 310);
     width:calc(var(--icon-box) * 380 / 310)}
/* The title column beside the icon is narrow at Narrow + Largest (335px) and on
   phones, so one long word must be allowed to break rather than spill past it. */
.has-icon h1{overflow-wrap:anywhere}

.note{margin-top:3rem;padding-top:1.4rem;border-top:1px solid var(--rule)}
.note p{font-size:calc(var(--reading-size) * 16 / 19);color:var(--ink-soft);max-width:var(--measure)}

/* ---------- chapter navigation ---------- */
.chapter-nav{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
     font-family:var(--sans);font-size:calc(var(--reading-size) * 13 / 19);
     padding:1rem 0;border-top:1px solid var(--rule)}
.chapter-nav.top{border-top:0;border-bottom:1px solid var(--rule);margin-bottom:2.4rem}
.chapter-nav.bottom{margin-top:3rem}
.chapter-nav a{color:var(--ink-soft);text-decoration:none;max-width:40%}
.chapter-nav a:hover{color:var(--ink)}
.chapter-nav .spacer{flex:1}

/* ---------- lists ---------- */
.chapter-list{list-style:none;padding:0;margin:0 0 1.5rem}
.chapter-list li{padding:.55rem 0;border-bottom:1px solid var(--rule);
     display:flex;gap:1rem;align-items:baseline;
     font-size:calc(var(--reading-size) * 16 / 19)}
.chapter-list .n{font-family:var(--sans);font-size:calc(var(--reading-size) * 12 / 19);
     color:var(--ink-faint);min-width:3.2em;letter-spacing:.06em}
.chapter-list a{text-decoration:none;color:var(--ink)}
.chapter-list a:hover{color:var(--accent)}
.chapter-list .interlude .n{font-style:italic;color:var(--accent)}

/* ---------- home: the framed container and the masthead ----------
   Amber's mockup, 2026-09-15. The surround is DARK and the content box is the
   normal reading panel — not the other way round.

   READ THIS BEFORE CHANGING ANY COLOUR HERE. The first build had it backwards: the
   mockup's content area measured ~+18 lighter than its surround, and that was taken
   for a deliberate lighter fill. It was not. It was the ART SHOWING THROUGH the
   ordinary --panel at 10%, exactly as it does on every chapter page; the surround
   only looked darker because it was opaque. Amber caught it by eye and named her
   own hex: "we go back to the darker color for the content layer (so it matches the
   content on the following pages that we didn't change) and then make the container
   box darker."

   So: .home-inner carries plain var(--panel) and NOTHING else, which is what makes
   the homepage's content identical to a chapter page, art bleed and all. The
   container is a solid --home-frame border around it, and main must stay
   transparent underneath or the panel would composite twice and go dark.

   That also ended the contrast question. The lighter fill had cost the homepage
   1.45 points; the panel is back, so the homepage reads exactly as the rest of the
   site does and there is no homepage-specific contrast penalty at all.

   NO HAIRLINE BORDER, deliberately. Her mockup had a faint line running the full
   height; she said it was an artefact and asked for it gone. Do not add one back.

   THE BAND HAS NO HEIGHT OF ITS OWN. The h1 takes an aspect-ratio of the art's
   UPPER portion (1800x886 of an 1800x977 picture); the img inside is height:auto
   and therefore taller, so it overhangs the bottom by exactly the sword tip —
   at every column width, on phones, and after a re-export at any size. There is
   no pixel number to re-derive. Do not put a height on .home-band.

   WHY THE SWORD IS VISIBLE, and the declaration that holds it up:
   .home-inner carries container-type:inline-size, which applies layout containment,
   and layout containment creates a stacking context (css-contain-2 3.1). So
   .home-inner is NOT a plain static box painting at Appendix E step 4 — it paints
   atomically as a z-index:0 stacking context at step 8. The sword clears it only
   because .home-band is positioned at z-index:1 and therefore paints at step 9.
   THAT z-index IS LOAD-BEARING. Delete it and the sword is covered everywhere
   container queries exist (Safari 16+, Chrome), while still looking correct in
   Safari 15, which has no containment and so really does paint it at step 7.
   For the same reason .home-inner must never be given a z-index above 0. */
.home{margin:0}
/* padding-bottom:1px stops the text title's bottom margin collapsing out of
   the band, which showed a strip of the darker band colour above the fill
   when no masthead has been exported. */
.home-band{position:relative;z-index:1;padding-top:14px;padding-bottom:1px;
     background:var(--home-frame)}
/* No display:flex here: the flex item would be the h1, whose max-content
   contribution comes from the image's 1800px intrinsic width, and min-width:auto
   can then refuse to shrink on a phone. */
/* min-height:0 is the load-bearing declaration. A block with a preferred
   aspect-ratio gets an automatic minimum size from its content, so without it the
   h1 grows to the picture's full height and the sword does not overhang at all —
   measured, not assumed. Where a browser ignores it the sword simply sits inside
   the band; nothing breaks. */
.home-logo-shown .home-title{display:block;width:var(--masthead-w,68%);
     margin:0 auto;aspect-ratio:1800/886;min-height:0;
     /* The alt text is the title AND the tagline, ~60 characters. At 34px caps in
        a ratio-locked box it would clip or spill onto the buttons for a reader
        with images off, which is one of the readers that alt exists to serve. */
     font-size:16px;letter-spacing:normal}
.home-masthead{display:block;width:100%;height:auto}
/* The container is a BORDER, not a margin and not a parent's background: a border
   paints outside the content box, so the panel inside still has nothing but the
   fixed art layers behind it. A dark parent would sit behind the panel's 10% and
   flatten the art bleed the whole site is built on.
   No top border — the mockup's content starts flush at the band's bottom edge, and
   the sword crosses straight from one into the other.
   20px + 2rem padding = 52px, exactly where main's padding used to put the text.
   .5rem top padding, not 2rem: .quests already carries a 5rem top margin. */
.home-inner{background:var(--panel);
     border:0 solid var(--home-frame);border-left-width:20px;border-right-width:20px;
     border-bottom-width:6rem;
     padding:.5rem 2rem 3.5rem}
/* The text title, when no masthead has been exported. */
.home-title{font-family:var(--sans);font-weight:800;letter-spacing:.16em;
     text-transform:uppercase;font-size:34px;margin-bottom:.15em}

/* ---------- home: quest buttons ----------
   Shield "Start Reading", sword "Where You Left Off" (mockups, 2026-09-14).
   Interface, not reading: these do not follow Reader controls' text size.
   Stacked by default — phones, the Narrow column, and any browser without
   container queries (Safari 15) — and side by side from 560px, in @container
   below. The container is .home-inner — see the rule itself for why — and never
   .quests: a container query cannot restyle the element that is itself the
   container.
   No cqi anywhere: Safari 15 has none, and there a cqi value blanks the property
   instead of falling back — the shield rendered at its full 537px. */
/* The container is .home-inner, not .home: a size query evaluates against the
   CONTENT box, so 560px keeps meaning the room the buttons actually have. On
   .home it would have measured 104px more once main lost its padding, which
   flips the Narrow column to side by side and shreds "Where You Left Off"
   into four lines. Still not .quests: a container cannot restyle itself. */
.home-inner{container-type:inline-size}
/* Stacked, the art overhangs each box by up to ~12px top and bottom; the row gap
   and margins clear it from the masthead above, the other button and "Latest". */
.quests{display:grid;grid-template-columns:1fr;row-gap:clamp(2.6rem,15vw,6rem);
     margin:5rem 0 4.5rem}
/* isolation keeps each button its own layer, so the picture (z 1) and the words
   (z 2) stack inside it and never against the rest of the page.
   Text starts past the sword's width (1.08x) in both boxes, so the sword never
   touches its words and the two titles line up. 118px, not 128: "Start Reading »"
   is 174px at 26px, and at 128 a 375px phone had only 166px for it and wrapped. */
.quest{--art-w:118px;--inset:.75rem;--t:26px;--s:18px;
     position:relative;isolation:isolate;display:flex;align-items:center;
     min-height:128px;margin-left:var(--inset);
     padding:1.2rem 1rem 1.2rem calc(var(--art-w) * 1.08 - var(--inset) + .6rem);
     text-decoration:none;color:var(--accent);font-family:var(--serif);
     border:1px solid rgba(150,186,200,.55);
     background:radial-gradient(ellipse 75% 95% at 36% 50%,#1b2b31 0%,#0c1518 48%,#030506 100%)}
.quest:hover{border-color:var(--accent)}
.quest:focus-visible{outline-offset:5px}
/* Centred on the box, not pinned to its top, so a title that wraps to two lines
   grows the box around the picture instead of leaving it stranded. */
.quest-art{position:absolute;z-index:1;top:50%;left:calc(-1 * var(--inset));
     width:var(--art-w);height:auto;transform:translateY(-50%);pointer-events:none}
.left-off .quest-art{width:calc(var(--art-w) * 1.08)}
.quest-text{position:relative;z-index:2;display:flex;flex-direction:column;gap:.5rem;
     text-wrap:balance}   /* a phone gets "Where You / Left Off", not a lone "Off" */
.quest-title{font-size:var(--t);line-height:1.12}
/* The chapter line in the site's white, the headings in its yellow (Amber, 2026-09-14).
   --ink, not #fff: it is the white of the story text, warm like the rest. 12.4:1 on
   the button's lightest point. */
.quest-sub{font-size:var(--s);line-height:1.3;color:var(--ink)}
/* Side by side. Measured 2026-09-14: at the Default column each box has ~170px
   for text, so "Where You Left Off" wraps to two lines at 24px — Amber's choice
   over one line at 19px. The column gap only has to clear the 7px focus outline:
   each picture overhangs its own box's margin, inside its own column. */
@container (min-width:560px){
  /* Tighter than stacked: at this size the art barely overhangs its box, and the
     stacked margins left ~90px of empty panel above and below. */
  /* minmax(0,…): a plain 1fr column cannot shrink below its content, so one
     unbreakable word would push the page sideways. */
  .quests{grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:1.5rem;
       margin:3rem 0 2.5rem}
  /* The chapter line stays at the stacked 18px on purpose — not 16px; small
     text is hard for Amber to read. */
  .quest{--art-w:100px;--t:24px;min-height:112px;padding-right:.9rem}
}


/* ==================================================================
   DESKTOP — parallax. Layer URLs come from --layer-N on <body>.
   Everything image-related lives inside this query so phones never
   download the desktop layer set.
   ================================================================== */
/* The nav row sits directly above the band and shares the column, so on the
   homepage it takes the container colour too — otherwise there is a visible seam
   where --panel meets --home-frame. Desktop only: on a phone .masthead is a
   gradient floating over the hero image and must stay that way. */
@media (min-width:1101px) and (min-height:501px){
  .home-page .masthead{background:var(--home-frame)}

  /* Height, not a pinned bottom: on an iPad in landscape the toolbar shrinks as you
     scroll, a box pinned top and bottom grows with it, and cover zooms the painting.
     The large viewport holds still. 100vh is the fallback before Safari 15.4, and on
     iOS it already means the large viewport. */
  .layers{display:block;position:fixed;top:0;left:0;right:0;height:100vh;height:100lvh;
          z-index:0;overflow:hidden;pointer-events:none}
  .layer{position:absolute;inset:0;background-size:cover;background-position:center;
         background-repeat:no-repeat;will-change:transform}
  .layer-0{background-image:var(--layer-0)}
  .layer-1{background-image:var(--layer-1)}
  .layer-2{background-image:var(--layer-2)}
}

/* ==================================================================
   MOBILE & TABLET PORTRAIT — no parallax. One full-bleed look at the
   world, then unobstructed reading. Height is set in CSS, so the
   image cannot shift the page as it loads.
   ================================================================== */
@media (max-width:1100.98px),(max-height:500px){
  .hero{display:block;height:45svh;min-height:220px;
        background-image:var(--hero);background-size:cover;
        background-position:var(--hero-pos,center);background-repeat:no-repeat;
        position:relative;z-index:0}
  .hero::after{content:"";position:absolute;inset:auto 0 0 0;height:38%;
        background:linear-gradient(to bottom,transparent,var(--base))}
  .masthead{position:absolute;top:0;left:0;right:0;width:auto;z-index:2;
        padding:1rem 1.25rem 2.2rem;
        background:linear-gradient(to bottom,rgba(31,38,46,.88),transparent)}  /* --base; was rgba(34,36,31,.88) */
  .masthead a{color:var(--ink)}
  .wordmark{text-shadow:0 1px 3px rgba(0,0,0,.5)}
  main,footer{width:auto;margin:0;padding-left:1.35rem;padding-right:1.35rem}
  /* 8 + 1 + 13 = 22px, against the 1.35rem (21.6px) every other page has. The
     frame replaces that padding rather than adding to it, so the reading width
     on a phone is where it was. */
  .home-page main{padding:0}
  .home{margin:0}
  /* 8px border + 13px padding = 21px, against the 1.35rem (21.6px) every other
     page has. The frame replaces that padding rather than adding to it. */
  .home-inner{border-left-width:8px;border-right-width:8px;border-bottom-width:4rem;
       padding:1.5rem 13px 2rem}
  .home-logo-shown{--masthead-w:100%}
  main{padding-top:2rem;padding-bottom:4rem;background:var(--base)}
  footer{margin-bottom:0;background:var(--base);padding-bottom:5.5rem}  /* room for the pill */
  .reader{position:static}
  .t-long{display:none}
  .t-short{display:inline}
  #reader-toggle{position:fixed;right:1rem;z-index:10;
       bottom:calc(1rem + env(safe-area-inset-bottom,0px));
       background:var(--base);border-radius:999px;
       width:44px;height:44px;padding:0;font-size:15px;font-weight:800}
  .reader-panel{position:fixed;right:1rem;left:auto;
       bottom:calc(4.25rem + env(safe-area-inset-bottom,0px));top:auto}
  /* The only two controls on the phone panel, on a panel whose whole purpose is
     readers who struggle to read. 44px, like the pill. */
  .reader-panel button{min-width:44px;min-height:44px;font-size:14px}
  .reader-width,.reader-bg{display:none}   /* meaningless on a full-bleed column */

  h1{font-size:calc(var(--reading-size) * 26 / 19)}
  .chapter-nav a{max-width:44%}
  /* Amber's call from the phone screenshot, 2026-09-15: smaller than the 96px tried first. */
  .chapter-head.has-icon{--icon-box:76px;column-gap:14px}
}

/* ==================================================================
   Motion. Full-viewport parallax is a vestibular trigger; this is not
   a nicety. The JS also checks the same query and never attaches.
   ================================================================== */
@media (prefers-reduced-motion:reduce){
  .layer{transform:none !important}
  *{scroll-behavior:auto !important}
}
