/* ╔═══════════════════════════════════════════════════════════════════╗
   ║  THE DRYING LINE — static styles                                  ║
   ║  Loads on index.html only. The per-print state rules live in      ║
   ║  line.generated.css, which build.js writes from data/prints.json. ║
   ╠═══════════════════════════════════════════════════════════════════╣
   ║  HOW THE STATE WORKS (still pure CSS, no JS)                      ║
   ║    :target gives only ONE piece of state, so the hash encodes     ║
   ║    BOTH which print AND which direction you arrived from:         ║
   ║      #f7  = print 7, arrived FORWARD  -> swipes in from the right ║
   ║      #b7  = print 7, arrived BACKWARD -> swipes in from the left  ║
   ║    Each panel therefore has two invisible stub anchors.           ║
   ║                                                                   ║
   ║    Filters are <details> toggles, NOT :target, so they hold their ║
   ║    own state and don't fight the easel. Bonus: they stack.        ║
   ║                                                                   ║
   ║  ★ WHAT GOT BETTER OFF JANITORAI ★                                ║
   ║    Genres, tags and verses are now data-* attributes instead of   ║
   ║    stacked classes (.pg-rpg .pt-fluff .pu-morcadia). JAI stripped ║
   ║    data-* silently, which is the only reason they were classes.   ║
   ║    Multi-valued tags use the ~= selector: [data-tags~="fluff"].   ║
   ║                                                                   ║
   ║    The friends monitor also used to steal :target from the line   ║
   ║    (one hash per page, so clicking a friend reset the easel).     ║
   ║    It lives on studio.html now, so that conflict is simply gone.  ║
   ║                                                                   ║
   ║  ⚠ SIZING IS em-BASED. .line-track sets font-size in px; print    ║
   ║    width / gap / pan offsets are all em, so ONE value rescales    ║
   ║    the whole wire (see the mobile block at the bottom). If you    ║
   ║    change print width or gap you must also change the two         ║
   ║    constants at the top of build.js — it derives every pan        ║
   ║    offset from them.                                              ║
   ╚═══════════════════════════════════════════════════════════════════╝ */

.line { width: 100%; padding: 50px 0 20px; position: relative; }

/* ---- NO-JUMP ANCHOR STUBS ----
   Navigating to a #hash makes the browser scroll that element into view,
   which yanked the page down to the wire on every arrow click. Making
   the stubs position:fixed means they are ALWAYS already inside the
   viewport, so there is nothing to scroll to and the page stays put.
   :has()/:target still match — those are DOM relationships, unaffected
   by layout.
   ⚠ Do not give these a static or relative position or the jump returns.
   .nul is the "do nothing" stub; it is deliberately NOT .stub so the
   default-state :not() selectors still apply. */
.stub, .nul {
  position: fixed; top: 0; left: 0;
  width: 0; height: 0; overflow: hidden; pointer-events: none;
}

/* ══════════════ FILTER BAR ══════════════ */
.line-filter { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin: 22px 0 4px; }
.line-filter details { display: inline-block; }
.line-filter summary {
  list-style: none; padding: 9px 18px;
  border: 1px solid var(--line); color: #b39894;
  font-family: var(--mono); font-weight: 700; font-size: 0.86rem;
  letter-spacing: 1.5px; text-transform: uppercase;
  transition: 0.25s ease; white-space: nowrap;
}
.line-filter summary::-webkit-details-marker { display: none; }
.line-filter summary::marker { content: ""; }
.line-filter summary:hover { color: var(--red); border-color: var(--red); box-shadow: 0 0 14px rgba(255,45,45,0.3); }
.line-filter .flt[open] > summary {
  color: var(--red); border-color: var(--red);
  background: var(--inset); box-shadow: 0 0 14px rgba(255,45,45,0.3);
}
/* tag filters run bone-white, verse filters run amber, so the three
   groups stay visually distinct when several are lit at once */
.line-filter .ft > summary { color: #9c8f7e; border-color: #33261f; }
.line-filter .ft > summary:hover, .line-filter .ft[open] > summary {
  color: #d8c9a8; border-color: #d8c9a8; background: var(--inset);
  box-shadow: 0 0 14px rgba(216,201,168,0.28);
}
.line-filter .fu > summary { color: #b58a5a; border-color: #3a2620; }
.line-filter .fu > summary:hover, .line-filter .fu[open] > summary {
  color: var(--amber); border-color: var(--amber); background: var(--inset);
  box-shadow: 0 0 14px rgba(224,134,60,0.35);
}
.fb-label {
  align-self: center; font-family: var(--mono);
  font-size: 0.62rem; font-weight: 700; letter-spacing: 3px;
  text-transform: uppercase; color: #6b544a; padding: 0 4px 0 10px;
}

/* ══════════════ THE WIRE ══════════════ */
.line-view {
  overflow: hidden; padding: 46px 0 34px; margin-bottom: 30px;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 13%, #000 87%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 13%, #000 87%, transparent 100%);
}
.line-track {
  position: relative; left: 50%;
  display: flex; gap: 2.2em; width: max-content;
  font-size: 10px;
  transition: transform 0.6s cubic-bezier(0.3, 0.9, 0.3, 1);
}
.line-track::before {
  content: ""; position: absolute; top: 0.7em; left: 0; right: 0; height: 2px;
  background: linear-gradient(180deg, #6b5148, #2a1a16);
  box-shadow: 0 1px 6px rgba(0,0,0,0.8), 0 0 14px rgba(255,45,45,0.18);
}
@media (prefers-reduced-motion: reduce) { .line-track { transition: none; } }

/* ---- a hanging print ---- */
.peg {
  display: block; flex: 0 0 11em; width: 11em;
  margin-top: 0.7em; padding: 0.55em 0.55em 0;
  background: var(--paper);
  transform-origin: top center; transform: rotate(-2deg);
  transition: transform 0.45s cubic-bezier(0.3,0.9,0.3,1), box-shadow 0.45s ease, background 0.45s ease;
  text-decoration: none; position: relative;
  box-shadow: 0 0.6em 1.2em rgba(0,0,0,0.55);
}
.peg:nth-child(even) { transform: rotate(2deg); }
/* the bulldog clip */
.pgclip {
  position: absolute; top: -1.15em; left: 50%; margin-left: -0.95em;
  width: 1.9em; z-index: 3; pointer-events: none;
  filter: brightness(0.85); transition: filter 0.35s ease;
}
.peg[data-genre="rpg"]     .pgclip { filter: brightness(0.95) sepia(0.7) hue-rotate(-30deg) saturate(3); }
.peg[data-genre="villain"] .pgclip { filter: brightness(0.62) sepia(0.8) hue-rotate(-25deg) saturate(3.4); }
.peg[data-genre="comedy"]  .pgclip { filter: brightness(1) sepia(0.85) saturate(2.2); }
.peg[data-genre="drama"]   .pgclip { filter: brightness(0.9) grayscale(1); }
/* the emulsion — dark and red-washed until selected */
.pgf { display: block; width: 100%; aspect-ratio: 4 / 5; overflow: hidden; background: var(--inset); position: relative; }
.pgf img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  filter: brightness(0.4) contrast(1.15) sepia(0.55) hue-rotate(-24deg) saturate(2.2);
  transition: filter 0.55s ease, transform 0.55s ease;
}
/* name written on the paper margin in marker */
.pgc {
  display: block; text-align: center;
  font-family: var(--hand); font-size: 1.5em; line-height: 1.1;
  color: #4a3a34; padding: 0.5em 0.2em 0.6em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color 0.4s ease;
}
.peg:hover { transform: rotate(0deg) scale(1.06); z-index: 5; box-shadow: 0 1em 1.8em rgba(0,0,0,0.7); }
.peg:hover .pgf img { filter: brightness(0.72) contrast(1.1) sepia(0.3) hue-rotate(-18deg) saturate(1.6); }

/* ══════════════ THE EASEL ══════════════ */
.easel { position: relative; padding: 0 58px; overflow: hidden; }
.easel-panel { display: none; }
@keyframes sw-f { from { opacity: 0; transform: translateX(70px); }  to { opacity: 1; transform: translateX(0); } }
@keyframes sw-b { from { opacity: 0; transform: translateX(-70px); } to { opacity: 1; transform: translateX(0); } }
@keyframes sw-n { from { opacity: 0; transform: scale(0.97); }       to { opacity: 1; transform: scale(1); } }

.easel-layout { display: grid; grid-template-columns: 340px 1fr; gap: 46px; align-items: center; }
.easel-shot {
  position: relative; background: var(--paper); padding: 12px 12px 0;
  box-shadow: 0 26px 44px rgba(0,0,0,0.7);
  transform: rotate(-1.2deg);
  transition: transform 0.45s ease, box-shadow 0.45s ease;
}
.easel-shot::before {
  content: ""; position: absolute; top: -18px; left: 50%; margin-left: -16px;
  width: 32px; height: 34px;
  background: linear-gradient(180deg, #cfc3b4 0 45%, #8a7d70 45% 100%);
  border: 1px solid #2a1a16; z-index: 4;
}
.easel-shot img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; display: block; filter: contrast(1.05) saturate(1.02); }
.easel-shot .cap {
  display: block; text-align: center;
  font-family: var(--hand); font-size: 1.5rem;
  color: #4a3a34; padding: 10px 6px 14px;
}
.easel-shot:hover { transform: rotate(0deg) scale(1.02); }

/* ⚠ THE SCRIM IS LOAD-BEARING FOR LEGIBILITY.
   The contact tape runs behind this whole section, and a strip of
   bright character art directly under "Frame 01 / 23" makes the small
   type unreadable. This pools darkness behind the text column only —
   the print itself, the arrows and the tape either side stay clear.
   z-index:-1 keeps it behind the text but above the panel background;
   .easel-info must stay position:relative for that to hold. */
.easel-info { position: relative; z-index: 0; }
.easel-info::before {
  content: ""; position: absolute; inset: -26px -30px; z-index: -1;
  background: radial-gradient(ellipse 70% 60% at 40% 50%,
    rgba(7,4,6,0.93) 0%, rgba(7,4,6,0.80) 55%, rgba(7,4,6,0) 100%);
  pointer-events: none;
}

.easel-index { font-family: var(--mono); font-size: 0.66rem; letter-spacing: 4px; color: var(--muted); text-transform: uppercase; margin-bottom: 10px; }
.easel-name { font-family: var(--slab); font-weight: 400; font-size: 1.85rem; letter-spacing: 0.5px; color: var(--text); margin: 0 0 8px; line-height: 1.2; }
.easel-genre {
  display: inline-block; color: var(--amber); font-family: var(--mono);
  letter-spacing: 4px; text-transform: uppercase; font-size: 0.7rem;
  padding-bottom: 12px; margin-bottom: 16px;
  border-bottom: 1px solid var(--line); width: 100%;
}
.easel-quote { color: #cbb8b4; line-height: 1.75; font-size: 0.92rem; font-family: var(--mono); }
.easel-tags { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 18px; }
.easel-tags span {
  background: var(--inset); color: #ff5a4a; border: 1px solid var(--line);
  font-size: 0.74rem; letter-spacing: 1px; text-transform: uppercase;
  padding: 4px 9px; font-family: var(--mono);
}
.easel-meta { display: flex; gap: 26px; margin-top: 20px; flex-wrap: wrap; }
.easel-meta .label { font-size: 0.58rem; letter-spacing: 2px; color: var(--muted); text-transform: uppercase; font-family: var(--mono); }
.easel-meta .value { font-family: var(--slab); font-size: 1.2rem; color: var(--red); }
.easel-link { margin-top: 22px; }

.line-nav { display: contents; }
.line-arrow {
  position: absolute; top: 50%; margin-top: -24px; z-index: 10;
  width: 46px; height: 48px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel); border: 1px solid var(--line);
  color: var(--red); font-family: var(--mono); font-size: 1.6rem; line-height: 1;
  text-decoration: none; transition: 0.25s ease;
}
.line-prev { left: 0; }
.line-next { right: 0; }
.line-arrow:hover { background: var(--red); color: #0a0506; border-color: var(--red); box-shadow: 0 0 22px rgba(255,45,45,0.45); }

/* ══════════════ FILTERED VIEW ══════════════
   With any filter open the wire stops being a pannable strip and
   becomes a centred row of just the matches. Only the middle copy
   (.copyB) is shown, because the strip is tripled and we do not want
   three of everything. !important is needed because the per-print pan
   rules carry an id inside :has() and would otherwise out-specify. */
.line:has(.flt[open]) .peg { display: none; }
.line:has(.flt[open]) .line-track {
  left: 0 !important; width: 100% !important;
  justify-content: center !important; transform: none !important;
  flex-wrap: wrap; row-gap: 3.2em;
}
.line:has(.flt[open]) .line-track::before { left: 4%; right: 4%; }

.line:has(.f-rpg[open])      .peg.copyB[data-genre="rpg"],
.line:has(.f-villain[open])  .peg.copyB[data-genre="villain"],
.line:has(.f-comedy[open])   .peg.copyB[data-genre="comedy"],
.line:has(.f-drama[open])    .peg.copyB[data-genre="drama"],
.line:has(.f-fluff[open])    .peg.copyB[data-tags~="fluff"],
.line:has(.f-magical[open])  .peg.copyB[data-tags~="magical"],
.line:has(.f-male[open])     .peg.copyB[data-tags~="male"],
.line:has(.f-group[open])    .peg.copyB[data-tags~="group"],
.line:has(.f-morcadia[open]) .peg.copyB[data-verse="morcadia"],
.line:has(.f-well[open])     .peg.copyB[data-verse="well"] { display: block; }

/* ══════════════ MOBILE ══════════════ */
@media screen and (max-width: 900px) {
  .easel { padding: 0; }
  .easel-layout { grid-template-columns: 1fr; gap: 26px; }
  .easel-shot { max-width: 260px; margin: 0 auto; }
  .easel-name, .easel-genre, .easel-quote { text-align: center; }
  .easel-tags, .easel-meta { justify-content: center; }
  .easel-link, .easel-link .chem-link { display: block; text-align: center; }
  .line-arrow { position: static; margin: 0; width: 100%; height: 44px; }
  .line-nav { display: flex; gap: 10px; margin-top: 22px; }
  /* rescales the whole wire — peg size, gaps and every pan offset are
     em-based, so this one value drives all of them.
     10px only fitted ~3 prints on a phone; 5.2px fits ~5. Because the
     prints get narrow, captions hide EXCEPT on the centred one — the
     generated selected-state rules re-show it (they carry an id inside
     :has() so they out-specify this) and the easel names it anyway. */
  .line-track { font-size: 5.2px; }
  .pgc { display: none; font-size: 11px; }
  .line-filter summary { font-size: 0.78rem; padding: 8px 14px; letter-spacing: 1px; }
  .fb-label { width: 100%; text-align: center; padding: 6px 0 0; }
  .easel-tags span { font-size: 0.7rem; }
  .line-view {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%);
  }
}
