/* =========================================================================
   True Iglesia
   Warm paper, ink lines, hand-lettered headings — the site should feel like
   the comic it wraps.  Mobile-first; every width below is a max-width.
   ========================================================================= */

@font-face {
  font-family: "Sue Ellen Francisco";
  src: url("/fonts/sue-ellen-francisco.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

/* --- tokens -------------------------------------------------------------
   Light values live on bare :root so they are the default; the dark block
   only redefines colours.  Nothing gets its sole definition inside a media
   query. */
:root {
  --paper:        #f6efe1;
  --paper-raised: #fffdf7;
  --paper-sunk:   #efe5d2;
  --ink:          #23201c;
  --ink-soft:     #5c554a;
  --ink-faint:    #8a8172;
  --rule:         #d9cdb4;
  --rule-strong:  #23201c;

  --accent:       #3f7a4d;   /* the comic's green */
  --accent-soft:  #e4efe2;
  --accent-ink:   #2b5636;
  --hot:          #d1462f;   /* Conley's orange-red */
  --hot-soft:     #fbe6e0;

  --shadow:       rgba(35, 32, 28, .16);

  --display: "Sue Ellen Francisco", "Comic Sans MS", cursive;
  --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;

  --measure: 34rem;
  --wide: 68rem;

  /* Height of the sticky masthead, excluding its 2px bottom border.  The
     comic sidebar sticks directly beneath it and sizes itself against this,
     so it is a shared number rather than a local guess. */
  --masthead-h: 3.4rem;

  /* The classic uneven-radius trick: a box that reads as drawn by hand. */
  --sketch: 14px 40px 18px 34px / 32px 16px 38px 18px;
  --sketch-alt: 34px 16px 40px 14px / 18px 36px 16px 32px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:        #1b1916;
    --paper-raised: #262320;
    --paper-sunk:   #141210;
    --ink:          #ece5d8;
    --ink-soft:     #b3aa9a;
    --ink-faint:    #8a8172;
    --rule:         #3d3831;
    --rule-strong:  #6f6759;
    --accent:       #7fb98c;
    --accent-soft:  #233025;
    --accent-ink:   #a5d4af;
    --hot:          #f0785f;
    --hot-soft:     #33201b;
    --shadow:       rgba(0, 0, 0, .5);
  }
}

:root[data-theme="dark"] {
  --paper:        #1b1916;
  --paper-raised: #262320;
  --paper-sunk:   #141210;
  --ink:          #ece5d8;
  --ink-soft:     #b3aa9a;
  --ink-faint:    #8a8172;
  --rule:         #3d3831;
  --rule-strong:  #6f6759;
  --accent:       #7fb98c;
  --accent-soft:  #233025;
  --accent-ink:   #a5d4af;
  --hot:          #f0785f;
  --hot-soft:     #33201b;
  --shadow:       rgba(0, 0, 0, .5);
}

/* --- base --------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.65;
  /* A faint speckle so the background reads as paper rather than flat fill. */
  background-image:
    radial-gradient(circle at 15% 12%, var(--paper-sunk) 0 1px, transparent 1.5px),
    radial-gradient(circle at 72% 58%, var(--paper-sunk) 0 1px, transparent 1.5px);
  background-size: 37px 41px, 53px 47px;
}

img, picture, svg { max-width: 100%; height: auto; display: block; }

a { color: var(--accent-ink); text-underline-offset: .18em;
    text-decoration-thickness: from-font; }
a:hover { color: var(--hot); }

:focus-visible { outline: 3px solid var(--hot); outline-offset: 3px; border-radius: 2px; }

h1, h2, h3 { line-height: 1.15; text-wrap: balance; }

hr { border: 0; border-top: 2px dashed var(--rule); margin: 2.5rem 0; }

kbd {
  font: inherit; font-size: .85em;
  border: 1.5px solid var(--rule-strong); border-bottom-width: 3px;
  border-radius: 5px; padding: 0 .35em; background: var(--paper-raised);
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: -999px; top: 0; z-index: 20;
  background: var(--ink); color: var(--paper); padding: .6rem 1rem;
}
.skip:focus { left: .5rem; top: .5rem; }

/* --- masthead ----------------------------------------------------------- */
.masthead {
  border-bottom: 2px solid var(--rule-strong);
  background: var(--paper-raised);
  position: sticky; top: 0; z-index: 10;
}

.masthead__inner {
  max-width: var(--wide); margin: 0 auto;
  padding: .55rem clamp(1rem, 4vw, 2rem);
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}

.brand { display: flex; align-items: center; gap: .5rem;
         text-decoration: none; color: var(--ink); }
/* Sized by height only — the mark is the Philippine Arena and must keep its
   3.8:1 proportions, so never give this both a width and a height. */
.brand__mark { height: 22px; width: auto; }
.brand__name {
  font-family: var(--display); font-size: 1.5rem; letter-spacing: .06em;
  line-height: 1; padding-top: .18em; white-space: nowrap;
}
.brand:hover .brand__name { color: var(--hot); }

.nav { display: flex; gap: .25rem; }
.nav a {
  font-family: var(--display); font-size: 1.2rem; letter-spacing: .04em;
  color: var(--ink); text-decoration: none;
  padding: .3rem .7rem .15rem; border-radius: var(--sketch);
  border: 2px solid transparent;
}
.nav a:hover { border-color: var(--rule); color: var(--hot); }
.nav a[aria-current="page"] {
  border-color: var(--rule-strong); background: var(--accent-soft);
  color: var(--accent-ink);
}

/* Four nav items plus the wordmark do not fit one phone-width row, so drop
   the nav onto its own line.  The header stops sticking there too — two rows
   pinned to the top would eat a tenth of a phone screen on every scroll. */
@media (max-width: 34rem) {
  .masthead { position: static; }
  .masthead__inner {
    flex-wrap: wrap; justify-content: center; gap: .3rem;
    padding-inline: .75rem;
  }
  .nav { width: 100%; justify-content: space-between; }
  .nav a { font-size: 1.15rem; padding: .3rem .5rem .15rem; }
}

/* --- shared shells ------------------------------------------------------ */
.page { max-width: var(--wide); margin: 0 auto;
        padding: clamp(1.5rem, 5vw, 3rem) clamp(1rem, 4vw, 2rem) 4rem; }
.page--narrow { max-width: 46rem; }
.page--center { text-align: center; }

.page__head { margin-bottom: 2.5rem; }
.page__title {
  font-family: var(--display); font-size: clamp(2.4rem, 8vw, 3.6rem);
  margin: 0 0 .4rem; letter-spacing: .02em;
}
.page__lede { font-size: 1.15rem; color: var(--ink-soft); max-width: var(--measure);
              margin: 0 0 1.25rem; }
.page--center .page__lede { margin-inline: auto; }
.page__note { font-size: .95rem; color: var(--ink-faint); max-width: var(--measure); }
.page__actions { display: flex; flex-wrap: wrap; gap: .75rem; margin: 1.5rem 0; }
.page--center .page__actions { justify-content: center; }
.page__art { margin: 2rem 0; border-radius: var(--sketch); }

/* Heading text and its illustration side by side, at every width — stacking
   it on phones is exactly the vertical space this is meant to save.  The art
   is capped to the text's height so the header can never grow taller than
   the words in it. */
.page__head--split {
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(7rem, 26vw, 20rem);
  gap: clamp(.75rem, 3vw, 2rem); align-items: center;
}
.page__head--split .page__lede { margin-bottom: 0; }
/* The grid item is the <picture>; the class from m.picture lands on the <img>
   inside it, so both need addressing. */
.page__head--split > picture { align-self: center; min-width: 0; }
.page__art--aside { margin: 0; width: 100%; height: auto; }

/* --- buttons ------------------------------------------------------------ */
.button {
  display: inline-block; font-family: var(--display); font-size: 1.3rem;
  letter-spacing: .04em; line-height: 1;
  padding: .7rem 1.3rem .5rem;
  border: 2.5px solid var(--rule-strong); border-radius: var(--sketch);
  background: var(--paper-raised); color: var(--ink); text-decoration: none;
  box-shadow: 3px 3px 0 var(--shadow);
  transition: transform .12s ease, box-shadow .12s ease;
}
.button:hover {
  color: var(--ink); transform: translate(-1px, -1px);
  box-shadow: 5px 5px 0 var(--shadow);
}
.button:active { transform: translate(2px, 2px); box-shadow: 0 0 0 var(--shadow); }
.button--primary { background: var(--accent); color: #fff; border-color: var(--rule-strong); }
.button--primary:hover { color: #fff; }

/* Discord's own blurple, so the button is recognisable as theirs before the
   label is read.  White stays white in both themes — this one is a brand
   colour rather than a site colour, so it does not follow the palette. */
.button--discord {
  display: inline-flex; align-items: center; gap: .55rem;
  background: #5865f2; color: #fff; border-color: #3d47b3;
}
.button--discord:hover, .button--discord:active { background: #4752c4; color: #fff; }
.button--discord .icon { width: 1.15em; height: 1.15em; fill: currentColor; }
:root[data-theme="dark"] .button--primary,
:root:not([data-theme="light"]) .button--primary { color: #14211a; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .button--primary { color: #fff; }
}

.more {
  font-family: var(--display); font-size: 1.25rem; letter-spacing: .03em;
  text-decoration: none; border-bottom: 2.5px solid var(--accent);
}

/* --- home --------------------------------------------------------------- */
.hero {
  max-width: var(--wide); margin: 0 auto;
  padding: clamp(2rem, 6vw, 4rem) clamp(1rem, 4vw, 2rem);
  display: grid; gap: clamp(1.5rem, 5vw, 3rem); align-items: center;
}
@media (min-width: 56rem) { .hero { grid-template-columns: 1.1fr .9fr; } }

.hero__title {
  font-family: var(--display); font-size: clamp(2.6rem, 9vw, 4.4rem);
  margin: 0 0 1rem; letter-spacing: .02em;
}
.hero__lede { font-size: 1.2rem; color: var(--ink-soft); max-width: 32rem; margin: 0; }
.hero__actions { display: flex; flex-wrap: wrap; gap: .75rem; margin: 1.75rem 0 0; }
.hero__cover {
  border: 3px solid var(--rule-strong); border-radius: var(--sketch);
  box-shadow: 8px 8px 0 var(--shadow); background: var(--paper-raised);
  transform: rotate(-1.5deg);
}

.strip { border-top: 2px solid var(--rule-strong); background: var(--paper-raised); }
.strip--alt { background: var(--paper-sunk); }
.strip__inner { max-width: var(--wide); margin: 0 auto;
                padding: clamp(2rem, 5vw, 3.5rem) clamp(1rem, 4vw, 2rem); }
.strip__title { font-family: var(--display); font-size: clamp(2rem, 6vw, 2.8rem);
                margin: 0 0 .35rem; }
.strip__lede { color: var(--ink-soft); max-width: var(--measure); margin: 0 0 1.75rem; }

.filmstrip {
  list-style: none; margin: 0 0 1.5rem; padding: 0 0 .75rem;
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(140px, 1fr);
  gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
}
.filmstrip li { scroll-snap-align: start; }
.filmstrip a { display: block; position: relative; text-decoration: none; }
.filmstrip img {
  border: 2.5px solid var(--rule-strong); border-radius: var(--sketch);
  background: #fff; box-shadow: 4px 4px 0 var(--shadow);
  transition: transform .15s ease;
}
.filmstrip a:hover img { transform: translate(-2px, -2px) rotate(-1deg); }
.filmstrip__num {
  position: absolute; right: -6px; bottom: -8px;
  font-family: var(--display); font-size: 1.3rem; line-height: 1;
  background: var(--hot); color: #fff; border: 2.5px solid var(--rule-strong);
  border-radius: 50%; width: 2rem; height: 2rem;
  display: grid; place-items: center; padding-top: .15em;
}

.cards { display: grid; gap: 1rem; margin-bottom: 1.75rem;
         grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
.card {
  display: flex; gap: .9rem; align-items: center; text-decoration: none;
  color: var(--ink); background: var(--paper-raised); padding: .75rem;
  border: 2.5px solid var(--rule-strong); border-radius: var(--sketch);
  box-shadow: 3px 3px 0 var(--shadow);
  transition: transform .12s ease, box-shadow .12s ease;
}
.card:nth-child(even) { border-radius: var(--sketch-alt); }
.card:hover { color: var(--ink); transform: translate(-2px, -2px);
              box-shadow: 6px 6px 0 var(--shadow); }
.card__art { flex: 0 0 4.5rem; }
.card__art img { border-radius: 6px; }
.card__title { font-weight: 650; line-height: 1.3; display: block; }

/* --- comic index -------------------------------------------------------- */
.grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.5rem 1rem;
        grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }
.thumb { display: block; text-decoration: none; color: var(--ink); }
.thumb img {
  border: 2.5px solid var(--rule-strong); border-radius: var(--sketch);
  background: #fff; box-shadow: 4px 4px 0 var(--shadow);
  transition: transform .15s ease, box-shadow .15s ease;
}
.thumb:nth-child(3n) img { border-radius: var(--sketch-alt); }
.thumb:hover img { transform: translate(-2px, -3px) rotate(-.75deg);
                   box-shadow: 7px 8px 0 var(--shadow); }
.thumb__caption { display: flex; gap: .5rem; align-items: baseline;
                  margin-top: .6rem; font-size: .95rem; line-height: 1.35; }
.thumb__num { font-family: var(--display); font-size: 1.3rem; color: var(--hot);
              flex: 0 0 auto; }
.thumb:hover .thumb__text { color: var(--hot); }

/* --- comic reader ------------------------------------------------------- */
/* Mobile first: the page list is a drawer pinned to the bottom of the screen,
   and the reader is a single column.  The sidebar layout only appears once
   there is width to spare for it. */
.reader-shell { display: block; }

/* Bottom padding clears the closed drawer, which is fixed over the page. */
.reader { max-width: 64rem; margin: 0 auto;
          padding: clamp(1.25rem, 4vw, 2.5rem) clamp(.75rem, 3vw, 2rem) 6rem; }

.pagenav {
  /* Every part of the element's height is named here so the list's max-height
     can be derived rather than guessed.  A guessed number is how it ended up
     hanging off the bottom of the screen. */
  --pagenav-handle: 3.25rem;   /* fixed height of the summary bar, below */
  --pagenav-frame: 5px;        /* 2px border top + 2px bottom + 1px list rule */
  --pagenav-top: 0rem;         /* sticky offset; only set on desktop */
  --pagenav-gap: 0rem;         /* clearance below the element */

  position: fixed; left: 0; right: 0; bottom: 0; z-index: 15;
  background: var(--paper-raised);
  border-top: 2px solid var(--rule-strong);
  box-shadow: 0 -4px 12px var(--shadow);
  /* Clip to the border so nothing can render outside the box, whatever the
     content does. */
  overflow: hidden;
}
/* Note on why the list sizes itself rather than being sized by this box:
   a <details> element's non-summary children sit inside an anonymous
   ::details-content wrapper in current browsers.  That wrapper — not the
   list — is the child here, so making .pagenav a flex column sized nothing,
   and the list grew to its content and never scrolled.  The scroll container
   is .pagenav__list, with a max-height of its own. */
.pagenav__handle {
  /* A fixed height, not padding plus whatever the line box works out to —
     the list's max-height subtracts this, so it has to be knowable. */
  height: var(--pagenav-handle);
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; padding: 0 clamp(.75rem, 3vw, 2rem); cursor: pointer;
  font-family: var(--display); font-size: 1.2rem; letter-spacing: .04em;
  line-height: 1; list-style: none;
}
.pagenav__handle::-webkit-details-marker { display: none; }
.pagenav__handle::after {
  content: "▾"; font-family: var(--body); font-size: .9rem;
  color: var(--ink-faint); transition: transform .15s ease;
}
.pagenav[open] .pagenav__handle::after { transform: rotate(180deg); }
.pagenav__handle-now { font-family: var(--body); font-size: .85rem;
                       color: var(--ink-faint); margin-left: auto; }
.pagenav__handle:hover { color: var(--hot); }

.pagenav__list {
  list-style: none; margin: 0;
  /* The scroll container is the list itself, with a height of its own rather
     than one inherited from a flex parent — see the note on ::details-content
     above.  This is what actually makes the 28 entries scrollable.
     As a bottom drawer it takes half the screen; the sidebar case computes
     its height from the named parts instead, below. */
  overflow-y: auto;
  max-height: 50vh;
  overscroll-behavior: contain;  /* reaching the end must not scroll the page */
  padding: 0 .5rem 1rem clamp(.75rem, 3vw, 2rem);
  border-top: 1px dashed var(--rule);

  /* Firefox and modern Chrome. */
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}

/* WebKit's older pseudo-elements, so Safari matches.  A thin ink-coloured
   thumb on the sunk paper, rather than the platform's grey slab. */
.pagenav__list::-webkit-scrollbar { width: 10px; }
.pagenav__list::-webkit-scrollbar-track {
  background: transparent; margin: .25rem 0;
}
.pagenav__list::-webkit-scrollbar-thumb {
  background: var(--rule); border-radius: 999px;
  /* Border in the panel colour insets the thumb so it reads as a slim bar
     rather than filling the gutter edge to edge. */
  border: 3px solid var(--paper-raised); background-clip: padding-box;
}
.pagenav__list::-webkit-scrollbar-thumb:hover { background: var(--accent); }
.pagenav__item {
  display: flex; align-items: baseline; gap: .6rem; padding: .35rem .4rem;
  text-decoration: none; color: var(--ink); border-radius: 6px;
}
.pagenav__item:hover { background: var(--accent-soft); color: var(--accent-ink); }
.pagenav__item.is-current { background: var(--accent-soft); color: var(--accent-ink);
                            font-weight: 700; }
.pagenav__num {
  flex: none; min-width: 2.4em; text-align: right;
  font-variant-numeric: tabular-nums; font-size: .85rem; color: var(--ink-faint);
}
.pagenav__item.is-current .pagenav__num { color: inherit; }
.pagenav__name { font-size: .9rem; overflow: hidden; text-overflow: ellipsis;
                 white-space: nowrap; }

@media (min-width: 62rem) {
  /* Give the masthead a known height so the sidebar's sticky offset can be
     derived from it instead of estimated.  min-height with no vertical
     padding means the number below IS the height, border excluded. */
  .masthead__inner { min-height: var(--masthead-h); padding-block: 0; }

  .reader-shell {
    display: grid; grid-template-columns: 15rem minmax(0, 1fr);
    gap: clamp(1rem, 3vw, 2.5rem); align-items: start;
    max-width: 82rem; margin: 0 auto;
    /* No top padding: the sidebar must start exactly where it will stick, or
       it hangs off the bottom of the screen until you scroll far enough for
       the two positions to meet.  The reader column re-adds the spacing. */
    padding: 0 clamp(.75rem, 3vw, 2rem) 0;
  }
  .reader { padding-top: clamp(1.25rem, 4vw, 2.5rem); }
  .pagenav {
    /* Reset the fixed-drawer offsets one at a time.  `inset: auto` would do
       it in one line but also clears `top`, leaving sticky with no offset to
       stick to — which looks exactly like sticky being broken. */
    position: sticky; left: auto; right: auto; bottom: auto;
    z-index: 1;
    border: 2px solid var(--rule-strong); border-radius: var(--sketch);
    box-shadow: 4px 4px 0 var(--shadow);
  }
  .pagenav__handle { cursor: default; }
  .pagenav__handle-now { display: none; }
  /* The sidebar sits below the masthead's height plus its 2px border, plus a
     gap so it does not touch the header.  The margin sets where it rests and
     `top` sets where it sticks; both add the same inset, so the two positions
     coincide and one max-height is correct in either state.  Changing the
     inset alone keeps that true — which is the point of writing it once. */
  .pagenav {
    --pagenav-inset: 1.25rem;
    margin-top: var(--pagenav-inset);
    top: calc(var(--masthead-h) + 2px + var(--pagenav-inset));
    --pagenav-top: calc(var(--masthead-h) + 2px + var(--pagenav-inset));
    --pagenav-gap: 1rem;
  }
  /* Fill the column, minus everything outside the list that still occupies
     height: the sticky offset above it, the summary bar, the borders, and
     the clearance it should leave at the bottom of the viewport.  Guessing
     one number here is what left it hanging off the screen. */
  .pagenav__list {
    max-height: calc(
      100vh - var(--pagenav-top) - var(--pagenav-gap)
            - var(--pagenav-handle) - var(--pagenav-frame)
    );
  }
  .reader { padding: 0 0 4rem; max-width: none; }
}
.reader__head { text-align: center; margin-bottom: 1.25rem; }
.reader__eyebrow { font-size: .9rem; color: var(--ink-faint);
                   text-transform: uppercase; letter-spacing: .1em; margin: 0 0 .4rem; }
.reader__eyebrow a { color: inherit; }
.reader__title { font-family: var(--display); font-size: clamp(1.9rem, 6vw, 3rem);
                 margin: 0; }

.reader__page { margin: 1.25rem 0; }
.reader__hit { display: block; }
.reader__img {
  width: 100%; background: #fff;
  border: 3px solid var(--rule-strong); border-radius: var(--sketch);
  box-shadow: 6px 6px 0 var(--shadow);
}

/* A comic page is portrait, so filling the available width makes it several
   screens tall on a wide monitor.  Bound the height instead, so one page is
   roughly one screenful and reading does not mean scrolling.
   This has to sit after the rule above: `width: 100%` there would otherwise
   win and fight max-height into squashing the aspect ratio. */
@media (min-width: 46rem) {
  .reader__img {
    width: auto; max-width: 100%;
    /* 100vh is not the space available to the art: the sticky masthead, the
       page's eyebrow and title above it, and the Prev/Next row below it all
       want room too.  Subtracting only the masthead left the page running off
       the bottom of the screen.  The 9rem covers heading and pager. */
    max-height: calc(100vh - var(--masthead-h) - 9rem);
    margin-inline: auto;
  }
}

.pager { display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
         gap: .4rem; margin: 1.25rem 0; }
.pager__btn {
  font-family: var(--display); font-size: 1.2rem; line-height: 1;
  padding: .55rem .8rem .4rem; min-width: 2.75rem; text-align: center;
  border: 2.5px solid var(--rule-strong); border-radius: var(--sketch);
  background: var(--paper-raised); color: var(--ink); text-decoration: none;
  box-shadow: 2px 2px 0 var(--shadow);
}
.pager__btn--wide { min-width: 5.5rem; }
.pager__btn:hover { background: var(--accent-soft); color: var(--accent-ink);
                    transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--shadow); }
.pager__btn.is-off { opacity: .35; box-shadow: none; }
.pager__count { font-family: var(--display); font-size: 1.25rem;
                padding: 0 .6rem; color: var(--ink-soft); white-space: nowrap; }
@media (max-width: 30rem) { .pager__count span { display: none; } }

.transcript { margin-top: 3rem; border-top: 2px dashed var(--rule); padding-top: 1.5rem; }
.transcript__title { font-family: var(--display); font-size: 1.8rem; margin: 0 0 .75rem; }
.transcript__body { margin: 0; max-width: var(--measure); }
.transcript__body dt { font-weight: 700; margin-top: .9rem; color: var(--accent-ink); }
.transcript__body dd { margin: 0; }
.transcript__note { color: var(--ink-soft); font-style: italic; margin-top: .9rem; }

.reader__foot { margin-top: 2.5rem; display: flex; flex-wrap: wrap;
                gap: 1rem; align-items: center; justify-content: space-between; }
.reader__hint { font-size: .9rem; color: var(--ink-faint); margin: 0; }
@media (hover: none) { .reader__hint { display: none; } }

/* --- article index ------------------------------------------------------ */
.finder { margin: 0 0 2.5rem; max-width: 34rem; }
.finder__field input {
  width: 100%; font: inherit; padding: .7rem .9rem;
  color: var(--ink); background: var(--paper-raised);
  border: 2.5px solid var(--rule-strong); border-radius: var(--sketch);
  box-shadow: 3px 3px 0 var(--shadow);
}
.finder__field input::placeholder { color: var(--ink-faint); }
.finder__status { font-size: .9rem; color: var(--ink-faint); margin: .5rem 0 0;
                  min-height: 1.3em; }
.finder__empty { text-align: center; color: var(--ink-soft); margin: 3rem 0; }
.finder__empty button { font: inherit; color: var(--accent-ink); background: none;
                        border: 0; border-bottom: 2px solid var(--accent);
                        cursor: pointer; padding: 0; }

.topic { margin-bottom: 2.75rem; }
.topic__title {
  font-family: var(--display); font-size: clamp(1.7rem, 5vw, 2.2rem);
  margin: 0 0 .9rem; padding-bottom: .3rem;
  border-bottom: 2.5px solid var(--rule-strong);
  display: flex; align-items: baseline; gap: .6rem;
  scroll-margin-top: 4.5rem;
}
.topic__count { font-family: var(--body); font-size: .8rem; font-weight: 700;
                color: var(--ink-faint); }

.list { list-style: none; margin: 0; padding: 0;
        display: grid; gap: .5rem;
        grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr)); }
.list a {
  display: flex; gap: .8rem; align-items: center; padding: .5rem .6rem;
  text-decoration: none; color: var(--ink); border: 2px solid transparent;
  border-radius: var(--sketch);
}
.list a:hover { border-color: var(--rule-strong); background: var(--paper-raised);
                color: var(--ink); }
.list__art { flex: 0 0 3.25rem; }
.list__art img { border-radius: 5px; }
.list__title { display: block; line-height: 1.35; }
.list a:hover .list__title { color: var(--hot); }

.tag {
  display: inline-block; font-size: .7rem; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; padding: .1rem .45rem; margin-top: .25rem;
  border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink);
}

/* --- prose -------------------------------------------------------------- */
.prose {
  max-width: var(--measure); margin: 0 auto;
  padding: clamp(1.5rem, 5vw, 3rem) clamp(1rem, 4vw, 2rem) 4rem;
  font-size: 1.125rem;
}
.prose__head { margin-bottom: 2rem; }
.prose__eyebrow { margin: 0 0 .5rem; font-size: .8rem; letter-spacing: .12em;
                  text-transform: uppercase; color: var(--ink-faint); }
.prose__eyebrow a { color: var(--hot); text-decoration: none;
                    border-bottom: 2px solid var(--hot-soft); }
.prose__title { font-family: var(--display); font-size: clamp(2.2rem, 7vw, 3.2rem);
                margin: 0; letter-spacing: .02em; }
.prose__lang { margin: .9rem 0 0; font-size: .95rem; color: var(--ink-soft); }

.prose p { margin: 0 0 1.15em; }
.prose h2 {
  font-family: var(--display); font-size: clamp(1.6rem, 5vw, 2.1rem);
  margin: 2.25em 0 .5em; letter-spacing: .02em; scroll-margin-top: 4.5rem;
}
.prose h2:first-of-type { margin-top: 1.5em; }
.prose strong { font-weight: 750; }

.prose__figure { margin: 2rem auto; }
.prose__figure img {
  margin: 0 auto; border: 2.5px solid var(--rule-strong);
  border-radius: var(--sketch); background: #fff;
  box-shadow: 5px 5px 0 var(--shadow);
}

.prose blockquote {
  margin: 1.75rem 0; padding: 1rem 1.25rem;
  background: var(--paper-raised); color: var(--ink);
  border: 2.5px solid var(--rule-strong); border-radius: var(--sketch-alt);
  box-shadow: 4px 4px 0 var(--shadow);
  font-size: 1.02em;
}
.prose blockquote p { margin: 0; }

.anchor { float: none; margin-left: .3em; color: var(--rule);
          text-decoration: none; font-family: var(--body); font-size: .6em;
          opacity: 0; transition: opacity .15s ease; }
.prose h2:hover .anchor, .anchor:focus { opacity: 1; }

.prose__fntitle { font-size: 1.35rem !important; }
.footnote { font-size: .92rem; color: var(--ink-soft); margin-bottom: .6em !important;
            scroll-margin-top: 4.5rem; }
.footnote__back { font-weight: 700; margin-right: .35em; text-decoration: none; }
.footnote__back::before { content: "["; }
.footnote__back::after { content: "]"; }
.fnref { text-decoration: none; }
.fnref sup::before { content: "["; }
.fnref sup::after { content: "]"; }

.prose__rule { margin: 3rem 0 1.5rem; }
.prose__fineprint { font-size: .82rem; color: var(--ink-faint); }
.prose__foot { margin-top: 3rem; padding-top: 1.5rem;
               border-top: 2px dashed var(--rule);
               display: flex; flex-wrap: wrap; gap: 1rem;
               align-items: center; justify-content: space-between; }
.prose__foot p { margin: 0; }

.linklist { padding-left: 1.2em; }
.linklist li { margin-bottom: .25em; }

/* --- share -------------------------------------------------------------- */
.share { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.share__label { font-family: var(--display); font-size: 1.15rem;
                color: var(--ink-faint); }
.share__copy {
  font: inherit; font-size: .85rem; cursor: pointer;
  padding: .25rem .7rem; color: var(--ink); background: var(--paper-raised);
  border: 2px solid var(--rule-strong); border-radius: var(--sketch);
}
.share__copy:hover { background: var(--accent-soft); color: var(--accent-ink); }

/* --- chat --------------------------------------------------------------- */
.chat { border: 3px solid var(--rule-strong); border-radius: var(--sketch);
        overflow: hidden; background: var(--paper-raised);
        box-shadow: 5px 5px 0 var(--shadow); }

.chat__log {
  list-style: none; margin: 0; padding: 1rem; overflow-y: auto;
  height: min(60vh, 26rem); background: var(--paper-sunk);
  display: flex; flex-direction: column; gap: .55rem;
  overflow-wrap: anywhere;
}
/* Three states, not two: a quiet channel must not sit on "Loading…" forever,
   which is what happens when the only signal is "has it rendered anything". */
.chat__log[data-empty="yes"]::before,
.chat__log[data-empty="none"]::before {
  color: var(--ink-faint); font-size: .9rem; margin: auto; text-align: center;
}
.chat__log[data-empty="yes"]::before { content: "Loading the conversation…"; }
.chat__log[data-empty="none"]::before {
  content: "Say hello — replies will appear here.";
}

.chat__line { display: grid; gap: 0 .5rem; font-size: .95rem;
              grid-template-columns: auto 1fr auto; align-items: baseline; }
.chat__who { font-weight: 700; color: var(--accent-ink); }
/* Visitors relayed in from this page read as quieter than our own replies. */
.chat__line--guest .chat__who { color: var(--ink-soft); font-weight: 600; }
.chat__said { color: var(--ink); white-space: pre-wrap; }
.chat__when { color: var(--ink-faint); font-size: .75rem; font-variant-numeric: tabular-nums; }
.chat__file { grid-column: 2; font-size: .85rem; }

.chat__form {
  display: flex; flex-direction: column; gap: .5rem; padding: .75rem;
  border-top: 2px solid var(--rule-strong);
}

/* The name is its own row, so the message box keeps the full width. */
.chat__identity { display: flex; align-items: center; gap: .5rem; }
.chat__label { font-size: .7rem; text-transform: uppercase;
               letter-spacing: .06em; color: var(--ink-faint); flex: none; }
.chat__nick { flex: 0 1 12rem; }

.chat__compose { display: flex; align-items: flex-end; gap: .5rem; }
.chat__say { flex: 1 1 auto; resize: none; overflow-y: auto; max-height: 140px; }

.chat__form input, .chat__form textarea {
  font: inherit; font-size: .95rem; width: 100%; padding: .4rem .6rem;
  color: var(--ink); background: var(--paper-raised);
  border: 2px solid var(--rule); border-radius: 8px;
}
.chat__form input:focus-visible,
.chat__form textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Square icon button.  A fixed size keeps it aligned with the first line of
   the message box while that box grows underneath it. */
.chat__send {
  flex: none; display: grid; place-items: center; cursor: pointer;
  width: 2.6rem; height: 2.6rem; padding: 0;
  color: var(--ink); background: var(--paper-raised);
  border: 2px solid var(--rule-strong); border-radius: var(--sketch);
}
.chat__send .icon { width: 1.15rem; height: 1.15rem; }
.chat__send:hover:not(:disabled) { background: var(--accent-soft); color: var(--accent-ink); }
.chat__send:disabled { opacity: .55; cursor: default; }

.chat__hint { margin: 0; font-size: .75rem; color: var(--ink-faint); }

/* Off-screen rather than display:none — a bot reading the DOM should still
   find it, which is the whole point of the trap. */
.chat__trap { position: absolute; left: -9999px; width: 1px; height: 1px;
              overflow: hidden; }

.chat__status:empty { display: none; }
.chat__status { margin: 0; padding: 0 .75rem .75rem; font-size: .85rem;
                color: var(--ink-soft); }
.chat__status[data-kind="error"] { color: var(--hot); }

/* --- footer ------------------------------------------------------------- */
.footer { border-top: 2px solid var(--rule-strong); background: var(--paper-raised);
          margin-top: 3rem; }
.footer__inner { max-width: var(--wide); margin: 0 auto;
                 padding: 2rem clamp(1rem, 4vw, 2rem); }
.footer__links, .footer__social { display: flex; flex-wrap: wrap; gap: 1rem;
                                  margin: 0 0 .75rem; }
.footer__links a { font-family: var(--display); font-size: 1.25rem;
                   text-decoration: none; color: var(--ink); }
.footer__links a:hover { color: var(--hot); }
.footer__social a { font-size: .9rem; color: var(--ink-soft);
                    display: inline-flex; align-items: center; gap: .4rem; }

/* Each mark in its own brand colour, with the label left in ink so the row
   still reads as text rather than a strip of logos.  On hover the whole link
   takes the brand colour. */
.social .icon { fill: var(--brand); }
.social:hover { color: var(--brand); }
.social--facebook { --brand: #1877f2; }
.social--gitlab   { --brand: #fc6d26; }
.social--discord  { --brand: #5865f2; }

/* Both brand blues sit too dark on the dark paper; lift them rather than
   letting the icons disappear into the background. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .social--facebook { --brand: #64a3ff; }
  :root:not([data-theme="light"]) .social--gitlab   { --brand: #ff9257; }
  :root:not([data-theme="light"]) .social--discord  { --brand: #8b95f7; }
}
:root[data-theme="dark"] .social--facebook { --brand: #64a3ff; }
:root[data-theme="dark"] .social--gitlab   { --brand: #ff9257; }
:root[data-theme="dark"] .social--discord  { --brand: #8b95f7; }

/* Inline brand marks.  `svg { display: block; height: auto }` in the base
   rules would collapse these, so both axes are set explicitly. */
.icon { width: 1em; height: 1em; flex: none; fill: currentColor; }
.footer__legal { font-size: .8rem; color: var(--ink-faint); margin: 1rem 0 0;
                 max-width: 46rem; }

/* --- print -------------------------------------------------------------- */
@media print {
  .masthead, .footer, .pager, .share, .finder, .skip,
  .reader__hint, .reader__eyebrow, .anchor { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .prose, .reader, .page { max-width: none; padding: 0; }
  .prose__figure img, .reader__img, .prose blockquote {
    border-width: 1px; border-radius: 0; box-shadow: none;
  }
  .prose__figure { float: right; width: 34%; margin: 0 0 1rem 1.5rem; }
  a { color: #000; }
  .prose h2, .prose__title, .reader__title { page-break-after: avoid; }
  blockquote, figure { page-break-inside: avoid; }
}
