/* FEAT-030 public stylesheet.
   Sections 1-6 are the CSS of the approved design (pm/resources/designs/list-page-v1.html), shipped as written,
   with one rename: the design's `.sill.has-x` (a media line of a row opened from the compact list) is
   `.compact .sill` here, because the server renders one row markup for both views.
   The last section adds what the server-rendered page needs: one <li> per item that works in both views,
   the no-JavaScript state (html.no-js) and the undrawn states (404, 500, empty list).
   Fonts: /static/fonts/fonts.css (self-hosted, linked before this file); the families below are the design's. */
/* ================= tokens (locked palette and type; three-state theme) ================= */
:root, [data-theme="light"] {
  --ground: #F5F5F1; --card: #FFFFFF; --ink: #141414; --soft: #5E5E5E; --line: #DCDCD6;
  --red-ink: #C00812; --up: #46D369; --down: #C00812;
  --btn: #141414; --on-btn: #FFFFFF; --btn-line: #9A9A94; --focus: #141414;
  --black: #000000; --white: #FFFFFF; --grey: #B3B3B3; --edge: #262626; --raise: #1C1C1C;
  --red: #E50914;
  --display: 'Big Shoulders Display', 'Arial Narrow', sans-serif;
  --body: 'Libre Franklin', 'Helvetica Neue', Arial, sans-serif;
  --mono: 'Spline Sans Mono', ui-monospace, Consolas, monospace;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground: #141414; --card: #1F1F1F; --ink: #FFFFFF; --soft: #B3B3B3; --line: #303030;
    --red-ink: #FF4F57; --down: #FF4F57; --btn: #FFFFFF; --on-btn: #141414; --btn-line: #5A5A5A; --focus: #FFFFFF;
    color-scheme: dark;
  }
}
[data-theme="dark"] {
  --ground: #141414; --card: #1F1F1F; --ink: #FFFFFF; --soft: #B3B3B3; --line: #303030;
  --red-ink: #FF4F57; --down: #FF4F57; --btn: #FFFFFF; --on-btn: #141414; --btn-line: #5A5A5A; --focus: #FFFFFF;
  color-scheme: dark;
}

/* ================= base ================= */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--ground); color: var(--ink); font: 400 1rem/1.5 var(--body); }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.page { max-width: 920px; margin: 0 auto; padding: 0 0 48px; }

/* ================= the list ================= */
/* ---------- the row: one item per row ---------- */
.list { container: list content / inline-size; list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.row { position: relative; display: grid; column-gap: 12px; row-gap: 4px; align-items: start; padding: 12px;
  grid-template-columns: minmax(2.75rem, max-content) 56px minmax(0, 1fr) auto;
  grid-template-areas: "rk pic tx tx" "rk dt dt act" "pn pn pn pn";
  background: var(--card); border-bottom: 1px solid var(--line); min-width: 0; }
.rk { grid-area: rk; position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.rk .mine { justify-content: center; }
.rk .menu { text-align: left; }
.cx .row > .rk { align-self: stretch; justify-content: center; min-width: 57px; padding-right: 12px; border-right: 1px solid var(--line); }
/* The head of a full row: the rank (with "my" under it when voted), the name and the upvote share one centre line. */
.row.full.P4 > .rk { justify-content: center; min-height: 71px; }
.row.full.P4 > .tx { align-self: center; padding-top: 0; }
.row.full.P4 > .act { align-self: center; margin-top: 0; }
/* Each row is its own layer (it is named for the view transitions), so a row with its menu open must sit above the rows after it. */
.row:has(.mine[aria-expanded="true"]) { z-index: 10; }
.g { display: block; font: 800 2.2rem/1 var(--display); letter-spacing: -.01em; }
/* The media slot is a fixed square on a neutral ground; any shape is shown whole inside it. */
.pic { grid-area: pic; width: 56px; height: 56px; background: var(--line); display: grid; place-items: center; overflow: hidden; position: relative; }
.pic img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.pic .ini { font: 800 1.3rem var(--display); color: var(--soft); }
.tx { grid-area: tx; min-width: 0; align-self: center; }
.name { font: 600 1rem/1.25 var(--body); color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.name:hover { text-decoration: underline; text-underline-offset: 3px; }
.act { grid-area: act; justify-self: end; align-self: center; display: inline-flex; align-items: center; gap: 8px; min-height: 44px; }
.act .up { justify-content: flex-end; margin-right: -3px; padding-right: 3px; }
.ptext { font: 500 .9rem/1.3 var(--body); color: var(--soft); }
svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; flex: none; display: block; }
.ds { margin: 0; font: 400 .95rem/1.55 var(--body); max-width: 62ch; overflow-wrap: anywhere; }
.dt { grid-area: dt; font: inherit; color: var(--soft); background: none; border: 0; padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; text-align: left; }
.chev { width: 15px; height: 15px; stroke-width: 2; transition: transform .2s ease; }
.dt[aria-expanded="true"] .chev { transform: rotate(180deg); }
.dt[aria-expanded="true"] { color: var(--ink); }
@media (hover: hover) { .dt:hover { color: var(--ink); } }

/* ---------- the full view: media and text shown by default ---------- */
.viewbtn { min-height: 44px; display: inline-flex; align-items: center; gap: 8px; padding: 0 12px; background: transparent; color: var(--ink);
  border: 1px solid var(--btn-line); border-radius: 2px; font: 600 .9rem var(--body); cursor: pointer; }
.viewbtn svg { width: 17px; height: 17px; stroke-width: 2; }
@media (hover: hover) { .viewbtn:hover { border-color: var(--ink); } }
.row.full { grid-template-columns: minmax(2.75rem, max-content) minmax(0, 1fr) auto; row-gap: 6px;
  grid-template-areas: "media media media" "rk tx act" "rk body body" "rk dt dt"; }
.media { grid-area: media; min-width: 0; }
.scr { aspect-ratio: 16 / 9; background: var(--line); position: relative; overflow: hidden; display: grid; place-items: center; }
.scr img, .scr iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; object-fit: contain; }
.scr .ini { font: 800 2rem var(--display); color: var(--soft); }
/* The sill: media controls sit under the media, never on it. */
.sill { display: flex; flex-wrap: wrap; align-items: center; gap: 0 18px; min-height: 44px; }
.sill button { min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; gap: 6px; padding: 0; background: none; border: 0; color: var(--soft);
  font: 500 .875rem var(--body); cursor: pointer; }
.sill button[aria-pressed="true"] { color: var(--ink); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; }
.sill svg { width: 12px; height: 12px; fill: currentColor; stroke: none; }
@media (hover: hover) { .sill button:hover { color: var(--ink); } }
.full .tx { align-self: center; }
.body { grid-area: body; min-width: 0; }
.full .ds { max-width: 62ch; }
.clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.full .dt { margin-top: -4px; }
.row.P4 { grid-template-areas: "rk tx act" "media media media" "body body body" "dt dt dt"; row-gap: 8px; }
.P4 .rk { min-height: 71px; }
.P4 .tx { align-self: start; padding-top: 4px; }
.P4 .name { font-size: 1.15rem; }
.P4 .media { border: 1px solid var(--line); container-type: inline-size; }
.P4 .scr { aspect-ratio: var(--ar, 4 / 3); }
/* While the video plays, the frame is the 16:9 picture plus YouTube's own control bands, which the player draws
   over the frame's edges with the picture centred between them: 52px of title and settings at the top (100px
   below ~340px wide, where the icons stack above the title), 128px of time, progress bar and share row at the
   bottom (measured on the youtube-nocookie embed, the same at every width). 256px above the picture's height
   keeps both bands clear of it. On phones the playing frame is the still's own 4:5 frame (R-C14): the row never
   moves when play starts or stops, and from 372px wide that is taller than the bands need (at 360px it is 8px
   short, the fullscreen button's box then touches the picture by 5px; its glyph does not). Beside the text
   (320px wide) the frame is 436px. Below 360px wide the frame grows while playing (FEAT-040 R-D3, below the
   home feed's rules). */
/* One rule for both pages (R-C14; FEAT-031 R-C2 / ASSUMPTION-22): the row's frame on the list page and the item
   frame while a video plays. cqw is the frame's own column (.P4 .media / .item .media are inline-size containers);
   the 700px threshold is the content column, named `content` on both .list and .item. */
.row.P4.playing .scr, .item .frame.playing { aspect-ratio: auto; height: 125cqw; }
@container content (min-width: 700px) { .row.P4.playing .scr, .item .frame.playing { height: calc(56.25cqw + 256px); } }
.H5 { --ar: 4 / 5; }
.H5 .media { border: 0; margin: 0 -12px; }
.row.H5 .sill { justify-content: center; padding: 0 12px; border-top: 0; border-bottom: 1px solid var(--line); min-height: 0; }
.H5 .sill:empty { border-bottom: 0; }
.P4 .sill { justify-content: space-between; padding: 0 4px 0 0; border-top: 1px solid var(--line); gap: 0 10px; }
.tabs { display: inline-flex; }
.P4 .tabs button { width: 56px; justify-content: center; position: relative; }
.P4 .tabs svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.9; }
.P4 .tabs button[aria-pressed="true"] { text-decoration: none; }
.P4 .tabs button svg { stroke-width: 1.6; }
.P4 .tabs button[aria-pressed="true"] svg { stroke-width: 2.6; }
.src { display: flex; justify-content: center; gap: .35em; min-width: 0; margin: 0; padding: 6px 12px 0; font: 400 .78rem/1.4 var(--body); color: var(--soft); white-space: nowrap; }
.src span { flex: none; }
/* A long address is cut at its left end, so the site's own name at the right stays readable. */
.src bdi { min-width: 0; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; }
.row.P4 .media .src { padding-left: 12px; padding-right: 12px; }
.P4 .clamp { display: block; max-height: var(--cut, calc(1.55em * 3)); -webkit-mask-image: linear-gradient(#000 35%, transparent); mask-image: linear-gradient(#000 35%, transparent); }
.P4 .dt { justify-self: center; margin: -6px 0 -4px; color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); }
@container (min-width: 700px) {
  .H5 .media { margin: 0; }
  .row.full.P4 { column-gap: 16px; align-items: start; grid-template-rows: auto auto 1fr;
    grid-template-columns: minmax(3.4rem, max-content) 320px minmax(0, 1fr) auto;
    grid-template-areas: "rk tx tx act" ". media body body" ". media dt dt"; }
  .full.P4 .dt { justify-self: start; align-self: start; margin: 0 0 0 -6px; }
  /* FEAT-040 R-D4: text beside the media is cut level with the 4:5 media area, on a whole line (the script's `--cut`);
     the fade covers the last line only. The script removes the button where it all fits. */
  .P4 .clamp { -webkit-mask-image: linear-gradient(#000 calc(100% - 1.55em), transparent); mask-image: linear-gradient(#000 calc(100% - 1.55em), transparent); }
}

/* ---------- wide rows ---------- */
@container (min-width: 600px) {
  .row { column-gap: 16px; padding: 12px 16px; align-items: center;
    grid-template-columns: minmax(3.4rem, max-content) 64px minmax(0, 1fr) auto auto;
    grid-template-areas: "rk pic tx dt act" "pn pn pn pn pn"; }
  .rk { min-height: 72px; justify-content: center; }
  .pic { width: 64px; height: 64px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
/* The picked "my rank" label (my-rank-6 c12-s2), copied as built. It appears under the global rank once voted. */
.lbl { font-size: calc(var(--k, 1) * 1rem); display: inline-flex; flex: none; max-width: 100%; }
.lbl .n { font: 700 var(--nz)/1 var(--display); white-space: nowrap; letter-spacing: .005em; }
.pl { --int: .375em; --inb: .375em; --inx: .375em; --pr: .75em; --h: 1.95em; --nz: 1.16em; --pt: .2em; --px: .72em; --mw: 3.1em;
  --my: max(10px, .625em); --dy: -50%; --plate: var(--line); --hair: var(--ink);
  background: var(--plate); border-radius: var(--pr); padding: var(--int) var(--inx) var(--inb); margin-top: .1em; }
.pl .ln { position: relative; display: inline-flex; align-items: center; justify-content: center; min-width: var(--mw); height: var(--h); padding: var(--pt) var(--px) 0;
  border: 1px solid var(--hair); border-radius: calc(var(--pr) - var(--inx)); }
.pl .my { position: absolute; left: 50%; top: -.5px; transform: translate(-50%, var(--dy)); padding: 0 .32em; background: var(--plate);
  font: 600 var(--my)/1 var(--body); white-space: nowrap; }
.ys2 { --k: .7; --my: max(9px, .64em); }
.land { animation: land .35s cubic-bezier(.2, .9, .3, 1.2) both; }
@keyframes land { from { transform: translateY(8px) scale(.9); opacity: 0; } }

/* ---------- upvote ---------- */
.up { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0;
  background: none; border: 0; color: var(--ink); font-family: var(--body); cursor: pointer; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; }
.dn :focus-visible { outline-offset: 2px; }
.win { display: grid; place-items: center; overflow: hidden; }
.busy svg { animation: rise 1.1s ease-in-out infinite; }
@keyframes rise { 0% { transform: translateY(130%); } 45%, 60% { transform: none; } 100% { transform: translateY(-130%); } }
.busy { cursor: progress; }
.roll { --sz: 32px; --rad: 999px; --rw: 2px; --rc: var(--btn); --fill: transparent; --fg: var(--ink); --aw: 17px; --as: 2.8; }
.pillv { display: inline-flex; align-items: center; height: var(--sz); border-radius: var(--rad); background: var(--fill); color: var(--fg);
  box-shadow: inset 0 0 0 var(--rw) var(--rc); transition: background .18s, color .18s, box-shadow .18s; }
.in { display: inline-flex; align-items: center; height: 100%; border-radius: inherit; }
.chip { width: var(--sz); height: 100%; flex: none; }
.chip svg { width: var(--aw); height: var(--aw); stroke-width: var(--as); }
.roll.busy { --fill: var(--btn); --fg: var(--on-btn); --rc: var(--btn); display: inline-flex; }
.v2 { --sz: 38px; --rw: 1.25px; --aw: 19px; --as: 2; }
/* ---------- the "my" label as a menu button ---------- */
/* A 44px box around the picked label; the label itself is unchanged. */
.mine { min-width: 44px; min-height: 44px; margin: -7px 0; padding: 0; display: inline-flex; align-items: center; justify-content: flex-start; gap: 3px;
  background: none; border: 0; color: var(--ink); cursor: pointer; }
.mine .pl { transition: background .15s; }
.mine .my { transition: background .15s; }
.mine[aria-expanded="true"] .pl { --plate: color-mix(in srgb, var(--line) 76%, var(--ink)); }
@media (hover: hover) { .mine:hover .pl { --plate: color-mix(in srgb, var(--line) 76%, var(--ink)); } }
.mine:focus-visible { outline: none; }
.mine:focus-visible .pl { outline: 3px solid var(--focus); outline-offset: 2px; }

.menu { position: absolute; z-index: 5; left: 0; top: calc(100% + 4px); width: max-content; max-width: min(16rem, calc(100vw - 48px));
  margin: 0; padding: 4px; list-style: none; background: var(--card); color: var(--ink); border: 1px solid var(--ink); border-radius: 8px; }
.menu[hidden] { display: none; }
.menu .mi { width: 100%; min-height: 44px; display: flex; align-items: center; gap: 10px; padding: 0 14px 0 10px; border: 0; border-radius: 5px; background: none;
  color: var(--ink); font: 500 .92rem/1.25 var(--body); text-align: left; text-decoration: none; cursor: pointer; }
.menu .mi:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
@media (hover: hover) { .menu .mi:hover { background: var(--line); } }
.menu .mi svg { width: 18px; height: 18px; stroke-width: 1.9; color: var(--soft); }
.menu .sep { height: 1px; margin: 4px 0; background: var(--line); }
/* After "Remove from my list": a line under the row, with Undo. */
.gone { grid-column: 1 / -1; margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0 10px; border-top: 1px solid var(--line);
  font: 400 .9rem/1.3 var(--body); color: var(--soft); }
.undo { min-height: 44px; min-width: 44px; padding: 0 6px; background: none; border: 0; color: var(--ink); font: 600 .9rem var(--body); cursor: pointer;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* ---------- the row's foot: "Continue reading" and, on a row opened from the compact list, "Close" ---------- */
.ft:empty { display: none; }
.ft { grid-area: dt; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0 22px; margin: -6px 0 -4px; }
.ft .dt { margin: 0; }
.ft .dt { min-height: 44px; display: inline-flex; align-items: center; font: 500 .9rem var(--body); }
/* Compact row: one line. The small picture is the opener, with a chevron tab under it (outside the picture). */
.cx .row:not(.full) { grid-template-columns: minmax(2.75rem, max-content) 56px minmax(0, 1fr) auto; grid-template-areas: "rk dt tx act"; align-items: center; }
.opener { grid-area: dt; width: 56px; display: grid; padding: 0; margin: 0; background: none; border: 0; color: var(--ink); cursor: pointer; }
.opener .pic { grid-area: auto; width: 100%; }
.opener .tab { display: grid; place-items: center; height: 18px; margin-top: 3px; background: var(--line); transition: background .15s, color .15s; }
.opener .tab svg { width: 14px; height: 14px; stroke-width: 2; }
@media (hover: hover) { .opener:hover .tab { background: var(--btn); color: var(--on-btn); } }
.opener:focus-visible { outline-offset: 3px; }
/* Opened from the compact list: the chevron at the end of the media line closes it, and so does the picture. */
.compact .sill { display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px; }
.compact .sill .tabs { grid-column: 2; justify-self: center; }
.sill .cls { grid-column: 3; width: 44px; height: 44px; display: grid; place-items: center; padding: 0; background: none; border: 0; color: var(--ink); cursor: pointer; }
.sill .cls svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; }
.cx.compact .row.full .scr:not(:has(iframe)) { cursor: zoom-out; }
@container (min-width: 600px) {
  .cx .row:not(.full) { grid-template-columns: minmax(3.4rem, max-content) 64px minmax(0, 1fr) auto; }
  .opener { width: 64px; }
  .opener .pic { height: 64px; }
}
.row.full.P4 .more { min-height: 44px; }
/* ---------- the upvote cue ----------
   At rest the ring is 38px. When the cue plays it swells to 44px (a transform, so nothing around it moves),
   "upvote" travels once round the inside, anticlockwise from the bottom, and the ring returns to 38px. */
.pillv { position: relative; }
.orbit { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; fill: currentColor; stroke: none; opacity: 0; pointer-events: none;
  transform-origin: 50% 50%; font: 700 7.4px var(--body); letter-spacing: .05em; }
.orbit path { fill: none; stroke: none; }
.cue .pillv, .up:focus-visible .pillv { animation: swell 3.4s cubic-bezier(.3, .8, .3, 1) both; }
.cue .chip svg, .up:focus-visible .chip svg { animation: tuck 3.4s cubic-bezier(.3, .8, .3, 1) both; }
.cue .orbit, .up:focus-visible .orbit { animation: orbit 3.4s cubic-bezier(.45, 0, .35, 1) both; }
@media (hover: hover) {
  .up:hover .pillv { animation: swell 3.4s cubic-bezier(.3, .8, .3, 1) both; }
  .up:hover .chip svg { animation: tuck 3.4s cubic-bezier(.3, .8, .3, 1) both; }
  .up:hover .orbit { animation: orbit 3.4s cubic-bezier(.45, 0, .35, 1) both; }
}
@keyframes swell { 0%, 100% { transform: scale(1); } 9%, 91% { transform: scale(1.158); } }
@keyframes tuck { 0%, 100% { transform: scale(1); } 9%, 91% { transform: scale(.7); } }
@keyframes orbit {
  0% { opacity: 0; transform: rotate(0deg); }
  8% { opacity: 1; }
  78% { opacity: 1; transform: rotate(-360deg); }
  91% { opacity: 1; transform: rotate(-360deg); }
  100% { opacity: 0; transform: rotate(-360deg); }
}
.busy .orbit { display: none; }
@media (prefers-reduced-motion: reduce) {
  .cue .orbit, .up:focus-visible .orbit { opacity: 1; }
}
/* ---------- motion between states ---------- */
/* Switching the list between full and compact, and opening or closing a compact row: each row keeps its own
   name across the change, so the browser moves and resizes it from where it was to where it is. */
::view-transition-group(*) { animation-duration: .38s; animation-timing-function: cubic-bezier(.3, .8, .3, 1); overflow: clip; }
::view-transition-old(*), ::view-transition-new(*) { height: 100%; width: 100%; object-fit: none; object-position: top left; }
::view-transition-old(root), ::view-transition-new(root) { animation: none; object-fit: fill; }
@media (prefers-reduced-motion: reduce) { ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; } }
/* FEAT-039 My lists: a card's hand is drawn above and beside its box (the fan's negative margin, the side cards' turn),
   so the clip above would hide it until the transition ends. A card's group clips its bottom edge only: an opening
   card's new rows still show as the group grows, and the hand stays drawn. */
::view-transition-group(*.ml-card) { overflow: visible; clip-path: inset(-100vh -100vw 0 -100vw); }

/* ---------- item-to-item separator ---------- */
/* Locked: S7, a band of the page ground between items, edge to edge. */
.S7.list { border-top: 0; }
.S7 .row { border-bottom: 8px solid var(--ground); }

/* ================= list header ================= */
.lh { display: block; padding: 22px 12px 0; }
.lh h1 { font: 800 2.5rem/.98 var(--display); letter-spacing: -.005em; margin: 0; overflow-wrap: anywhere; }
.lh p { margin: 0; }
.cnt { color: var(--soft); font: 400 .9rem/1.4 var(--body); white-space: nowrap; }
.ldesc { margin-top: 12px; }
.ldesc p { font: 400 .95rem/1.55 var(--body); max-width: 62ch; overflow-wrap: anywhere; }
.ldesc .cut { max-height: var(--cut, calc(1.55em * 2)); overflow: hidden; -webkit-mask-image: linear-gradient(#000 30%, transparent); mask-image: linear-gradient(#000 30%, transparent); }
.lnk { min-height: 44px; display: inline-flex; align-items: center; gap: 6px; padding: 0; background: none; border: 0; color: var(--ink); cursor: pointer;
  font: 500 .9rem var(--body); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); }
.lh .meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; margin-top: 10px; }
.lh .ldesc { margin-top: 10px; }
.lh .ldesc p { color: var(--ink); }
.lh { padding-bottom: 12px; }
.lh .facts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; }
/* ----- tags: grey chips, in the list header only. Plain labels. Items carry no tags. ----- */
.ftags { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 0; padding: 0; list-style: none; }
/* Locked: G2. 24px tall, 8px at the sides, 2px corners. */
.ftag { display: inline-flex; align-items: center; min-height: 24px; padding: 0 8px; background: var(--line); border-radius: 2px;
  color: var(--ink); font: 600 .8rem/1.2 var(--body); overflow-wrap: anywhere; }

/* ---------- the end of the page of items: more, loading, the end ---------- */
.bx { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 0 6px; background: transparent; color: var(--ink);
  border: 1px solid var(--btn-line); border-radius: 2px; font: 600 .875rem var(--body); cursor: pointer; white-space: nowrap; }
.bx svg { width: 16px; height: 16px; stroke-width: 2; }
@media (hover: hover) { .bx:hover { border-color: var(--ink); } }
.foot { padding: 20px 12px 28px; text-align: center; }
.foot .bx { width: 100%; max-width: 320px; }
.foot p { margin: 0; font: 400 .92rem/1.5 var(--body); color: var(--soft); min-height: 44px; display: grid; place-items: center; }
@media (min-width: 760px) { .lh { padding-left: 16px; padding-right: 16px; } }

/* ================= global nav: header 09, bottom dock (locked) =================
   Below 760px the bar keeps the wordmark and the account; Search, Add item, My list and My lists sit in a dock
   at the bottom of the screen. From 760px it is one bar. */
.bar svg, .dock svg { width: 20px; height: 20px; stroke-width: 1.8; }
.bar :focus-visible, .dock :focus-visible { outline-color: var(--white); outline-offset: 2px; }
.bar .panel :focus-visible { outline-color: var(--focus); }
/* The bar and the dock are named for the view transitions too, so moving rows never paint over them. */
.bar.live { view-transition-name: site-bar; }
.dock.live { view-transition-name: site-dock; }
.bar { position: relative; background: var(--black); color: var(--white); border-bottom: 1px solid var(--edge); }
/* the slot takes no box, so the live bar sticks to the page, not to a wrapper its own height */
#live-slot { display: contents; }
.bar.live { position: sticky; top: 0; z-index: 20; }
/* reading down the page sends the nav away; any move back up brings it back */
.bar.live, .dock.live { transition: transform .22s ease; }
.bar.live.away { transform: translateY(calc(-100% - 1px)); }
.dock.live.away { transform: translateY(100%); }
@media (prefers-reduced-motion: reduce) { .bar.live, .dock.live { transition: none; } }
.wrap { max-width: 1280px; margin: 0 auto; padding: 0 16px; min-height: 64px; display: flex; align-items: stretch; gap: 6px; }
.word { font: 800 2rem/1 var(--display); letter-spacing: -.015em; color: var(--white); text-decoration: none; margin-right: auto;
  display: inline-flex; align-items: center; padding-right: 8px; }
.word .hi { color: var(--red); }
.tools { display: flex; align-items: stretch; gap: 2px; }

/* bar controls: sentence case, no tracking; the red "you are here" mark sits flush on the bar's bottom edge */
.nb { min-width: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 0 10px;
  border: 0; background: transparent; color: var(--white); font: 600 .94rem var(--body); text-decoration: none; cursor: pointer;
  position: relative; white-space: nowrap; }
.nb:hover { background: var(--raise); }
.nb[aria-current="page"]::after, .nb[aria-expanded="true"]::after { content: ""; position: absolute; left: 8px; right: 8px; bottom: -1px; height: 3px; background: var(--red); }
.signin { align-self: center; min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 0 12px; margin-left: 4px; background: transparent; color: var(--white); border: 1.5px solid var(--grey); border-radius: 2px;
  font: 600 .94rem var(--body); cursor: pointer; white-space: nowrap; }
.signin:hover { border-color: var(--white); }
.signin[aria-expanded="true"] { background: var(--white); color: var(--black); border-color: var(--white); }
.me { align-self: center; width: 44px; height: 44px; margin-left: 4px; border: 0; background: transparent; padding: 0; cursor: pointer; display: grid; place-items: center; border-radius: 50%; }
.me .av { width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; background: var(--white); color: var(--black); font: 700 .95rem var(--body); }
.me[aria-expanded="true"] .av { box-shadow: 0 0 0 2px var(--black), 0 0 0 4px var(--red); }
/* FEAT-034 R-D6: the server serves the control as a link (the script upgrades it to a button); it looks the same. */
a.signin, a.me { text-decoration: none; }
.bar .lbl { display: none; }

/* My list: signed in, the control shows the reader's own #1 */
.top-th { width: 30px; height: 30px; border-radius: 2px; overflow: hidden; background: #2A2A2A; display: grid; place-items: center;
  font: 800 1rem var(--display); color: var(--grey); flex: none; }
.top-th img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ml-text { display: none; min-width: 0; text-align: left; line-height: 1.15; }
.ml-text small { display: block; font: 500 .74rem var(--body); color: var(--grey); }
.ml-text b { font: 600 .9rem var(--body); max-width: 150px; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.ml-text .n { font: 600 .82rem var(--mono); color: var(--grey); margin-right: 4px; }

@media (min-width: 760px) {
  .bar .lbl, .ml-text { display: block; }
  .nb { padding: 0 12px; }
  .signin { padding: 0 16px; }
}
@media (max-width: 359px) { .wrap { padding: 0 10px; gap: 0; } .word { font-size: 1.6rem; padding-right: 2px; } .nb { padding: 0 8px; } .tools { gap: 0; } .signin, .me { margin-left: 0; } }
/* search row under the bar: FEAT-038 serves one, under the bar at every width (design 02b, R-D1) */
.srow { border-top: 1px solid var(--edge); }
.srow form { max-width: 1280px; margin: 0 auto; padding: 10px 16px 12px; display: flex; gap: 6px; align-items: center; }
.field { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 0 0 14px;
  background: var(--raise); border: 1px solid #3A3A3A; border-radius: 2px; color: var(--grey); }
/* FEAT-038: the field's border marks focus on the input itself (the clear control inside it draws its own ring), so the
   field and the clear control each show a focus indicator the other state does not (R-E3, TC-038-52 (b)). */
.field:has(input:focus) { border-color: var(--white); }
.field input { flex: 1; min-width: 0; width: 100%; background: transparent; border: 0; outline: none; color: var(--white); font: 500 1rem var(--body); min-height: 46px; }
.field input::placeholder { color: var(--grey); }
.field input::-webkit-search-cancel-button { display: none; }
.field .clr { min-width: 44px; min-height: 44px; border: 0; background: transparent; color: inherit; display: grid; place-items: center; cursor: pointer; }
.cancel { min-height: 44px; padding: 0 10px; border: 0; background: transparent; color: var(--white); font: 600 .94rem var(--body); cursor: pointer; }
.dock { display: none; }
.dock .items { display: grid; grid-template-columns: repeat(4, 1fr); align-items: stretch; max-width: 520px; margin: 0 auto; padding: 0 6px; }
/* FEAT-037: "My list" is in the dock only on pages with a root, so the dock holds three or four controls (two or three
   without the script): one equal column per control shown. */
.dock .items { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 1fr; }
.dk { min-height: 60px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 6px 4px 8px;
  border: 0; background: transparent; color: var(--grey); font: 600 .76rem var(--body); text-decoration: none; cursor: pointer; position: relative; }
.dk[aria-current="page"], .dk[aria-expanded="true"] { color: var(--white); }
.dk[aria-current="page"]::before, .dk[aria-expanded="true"]::before { content: ""; position: absolute; top: -1px; left: 22%; right: 22%; height: 3px; background: var(--red); }
.dk .top-th { width: 24px; height: 24px; font-size: .85rem; }
.panel { position: absolute; top: 100%; right: max(16px, calc((100vw - 1280px) / 2 + 16px)); width: min(340px, calc(100vw - 32px));
  background: var(--card); color: var(--ink); border: 1px solid var(--line); border-top: 0; padding: 16px; z-index: 30; }
.panel h3 { margin: 0 0 4px; font: 800 1.6rem/1 var(--display); }
.panel p { margin: 0 0 14px; color: var(--soft); font-size: .92rem; }
.panel .refused { color: var(--red-ink); font-weight: 600; } /* FEAT-034 R-A5: the refused line, above the panel's text */
.who { display: flex; gap: 12px; align-items: center; margin-bottom: 8px; }
.who .av { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: var(--btn); color: var(--on-btn); font: 700 1rem var(--body); flex: none; }
.panel ul { list-style: none; margin: 0 0 14px; padding: 0; }
.panel li a { display: flex; flex-direction: column; justify-content: center; min-height: 52px; color: var(--ink); text-decoration: none; border-top: 1px solid var(--line); font-weight: 600; }
.panel li a small { font-weight: 400; color: var(--soft); overflow-wrap: anywhere; }
.panel li:last-child a { border-bottom: 1px solid var(--line); }
.tl { font: 600 .86rem var(--body); margin: 0 0 6px; }
.theme { display: grid; grid-template-columns: repeat(3, 1fr); border: 1px solid var(--btn-line); border-radius: 2px; overflow: hidden; margin-bottom: 14px; }
.theme label { min-height: 44px; display: grid; place-items: center; font: 600 .86rem var(--body); cursor: pointer; position: relative; }
.theme input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.theme label:has(input:checked) { background: var(--btn); color: var(--on-btn); }
.theme label:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: -3px; }
.pbtn { width: 100%; min-height: 44px; border-radius: 2px; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 10px; font: 600 .94rem var(--body); }
.pbtn.ghost { background: transparent; color: var(--ink); border: 1.5px solid var(--btn-line); }
.pbtn.google { background: #FFFFFF; color: #1F1F1F; border: 1px solid #747775; font-weight: 500; margin-bottom: 16px; }
.pbtn.google svg { width: 20px; height: 20px; stroke: none; }
@media (max-width: 759px) {
  .bar .desk { display: none; }
  .dock { display: block; background: var(--black); color: var(--white); border-top: 1px solid var(--edge); }
  .dock.live { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; padding-bottom: env(safe-area-inset-bottom); }
  body { padding-bottom: 64px; }
}

/* ================= FEAT-030: the server-rendered page ================= */
/* `hidden` always wins over a component's own display (the script hides fitted buttons, panels, rows of search). */
[hidden] { display: none !important; }

/* ---------- one <li> per item, for both views ----------
   The server renders every row full (`row full P4 H5`). The compact view is `compact` on the <ol>; the script takes
   `full P4 H5` off each row and puts them back on a row opened from the compact list (it also gets `open`). */
.row.full > .opener { display: none; }
.row:not(.full) > .media, .row:not(.full) > .body, .row:not(.full) > .ft { display: none; }
/* The closer on the media line exists only on a row opened from the compact list. */
.list:not(.compact) .sill .cls, .list:not(.compact) .sill.notabs { display: none; }
.sill .cls svg { transform: rotate(180deg); }
/* A row opened from the compact list shows all its text, with no "Continue reading". */
.compact .row.full .clamp { max-height: none; -webkit-mask-image: none; mask-image: none; }
.compact .row.full .ft { display: none; }
/* While the video plays it covers the picture or still and the letter. */
.row.playing .scr > :not(iframe) { display: none; }

/* ---------- descriptions as text: one <p> per paragraph (a <br> between its lines), inside the element that is cut ---------- */
.ds p { margin: 0; font: inherit; }
.ldesc .ldtext { font: 400 .95rem/1.55 var(--body); max-width: 62ch; overflow-wrap: anywhere; }
.ldesc .ldtext p { margin: 0; font: inherit; }
/* FEAT-040 R-D1 (FEAT-030 UAT-P-01's spec): a half-line gap between consecutive paragraphs, in the list description,
   the rows (reader list pages too) and the home entries; open or cut alike. Every cut's `max-height` is the script's
   `--cut`, which ends on a whole line (R-D5); the line-count height is only its first-paint stand-in. */
.ds p + p, .ldesc .ldtext p + p { margin-top: .5em; }
/* When the lines hold all the text the script hides the button and the fade goes. */
.P4 .clamp.fits, .ldesc .cut.fits { -webkit-mask-image: none; mask-image: none; }

/* ---------- the foot: "Show more items" is a link the script upgrades ---------- */
a.bx { text-decoration: none; }
.foot .bx + p, .foot p + .bx { margin-top: 4px; }

/* ---------- undrawn states (PRD § F): plain copy inside the layout ---------- */
.empty { margin: 0; padding: 20px 12px 28px; text-align: center; font: 400 .92rem/1.5 var(--body); color: var(--soft); border-top: 1px solid var(--line); }
.err { padding-bottom: 32px; }
.err .line { margin: 12px 0 0; font: 400 1rem/1.5 var(--body); color: var(--ink); }
.err .go { margin-top: 8px; }
.home { min-height: 44px; display: inline-flex; align-items: center; color: var(--ink); font: 600 .94rem var(--body);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); }

/* ---------- JavaScript off: controls that need the script are present but not shown; nothing is cut ----------
   FEAT-034 R-D6: Sign in / the account control are links to the page with the panel served open, so they and a
   served-open panel show; a closed panel is `hidden`. The theme switch needs the script, so it stays hidden. */
.no-js .viewbtn, .no-js .sill, .no-js .ft, .no-js .ldesc .lnk, .no-js [data-act="search"],
.no-js .act, .no-js .opener, .no-js .srow, .no-js .panel .tl, .no-js .panel .theme { display: none !important; }
.no-js .clamp, .no-js .ldesc .cut { display: block; max-height: none; -webkit-line-clamp: none; line-clamp: none; -webkit-mask-image: none; mask-image: none; }
.no-js .dock .items { grid-template-columns: none; }

/* The script keeps the reader's place across a view change itself (holdPlace); the browser's own scroll anchoring
   would move the page a second time. Everything after the list is excluded too (FEAT-037 CLAR-02 Q-3): with the rows
   out of the anchoring, the browser anchored on the foot (in sight while a batch loads) or on the announcer after it,
   and kept that in place as the rows were appended above it — the view jumped past the whole batch, the new foot
   landed in sight and the next batch left at once. An anchor can now only be above the list, and nothing above it
   moves when a batch is appended (FEAT-030 R-D4: one reach, one batch). */
.list, .list ~ * { overflow-anchor: none; }

/* The nav comes back without its slide when keyboard focus enters it (the script adds `snap` for one frame). */
.bar.live.snap, .dock.live.snap { transition: none; }

/* ===== FEAT-031 the item page ===== */
/* The approved design (pm/resources/designs/item-page-v1.html, "the page") ported onto the server's markup
   (contract: `article.item[data-item]`). Every rule is scoped under `.item` or `.viewer`, so the list page is
   untouched. The tile grids are container queries on `.item`; the two-column head (frame beside the text) is a
   viewport query, because a container cannot query its own width. */
.item { container: content / inline-size; background: var(--card); padding-bottom: 8px; }
.item > .hd, .item > .desc, .item > .set, .item > .rel, .item > .inlists { padding-left: 12px; padding-right: 12px; }
.item .sh { margin: 0 0 10px; font: 800 1.5rem/1.05 var(--display); letter-spacing: -.005em; }

/* ---------- the head: name, facts, tags, read more (R-B1..R-B6) ---------- */
.item .hd { display: grid; row-gap: 12px; min-width: 0; padding-top: 16px; padding-bottom: 16px; }
.item .hd > * { min-width: 0; }
/* A 500-character name wraps anywhere and never makes the page scroll sideways. */
.item .nm { margin: 0; overflow-wrap: anywhere; font: 800 clamp(2.4rem, 10vw, 3.6rem)/1.15 var(--display); /* R-B1 / TC-031-08: a line box tall enough for the display face, so a 500-character name is never clipped */ letter-spacing: -.005em; }
.item .facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 4px 14px; align-items: baseline; margin: 0; }
.item .fact { display: contents; }
.item .facts dt { font: 500 .85rem/1.4 var(--body); color: var(--soft); }
.item .facts dd { margin: 0; font: 600 .95rem/1.4 var(--mono); letter-spacing: -.01em; overflow-wrap: anywhere; }
.item .ftags { margin: 0; }
.item .more { margin: 0; }
.item .more a { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin: -8px 0; color: var(--ink); font: 500 .92rem var(--body);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); overflow-wrap: anywhere; }
.item .more a:hover { text-decoration-color: var(--ink); }
.item .more a svg, .item .wiki .wa svg { flex: none; width: 15px; height: 15px; stroke-width: 2; color: var(--soft); }

/* ---------- the frame (R-C1..R-C5) ----------
   4:5 until the picture loads and when it fails (the letter on the picture background); then the picture's own
   shape, clamped between 4:5 and 16:9 (the script sets it inline); a video still 16:9; while a video plays the
   list page's playing frame (R-C14, the shared rule above: 4:5 of its width, 56.25% + 256px from 700px of content).
   Without JavaScript the frame is the `<a>` the server renders (R-F2), with the same box. */
.item .media { display: flex; flex-direction: column; min-width: 0; margin: 0 0 16px; container-type: inline-size; }
.item .media > .frame { order: 0; }
.item .media > .tabs { order: 1; }
.item .media > .src { order: 2; }
.item .frame { aspect-ratio: 4 / 5; width: 100%; color: inherit; text-decoration: none; }
.item .media[data-yt]:not([data-pic]) .frame, .item .frame.still { aspect-ratio: 16 / 9; }
/* No picture left (the failed one was removed by the layout's handler): the letter at 4:5. */
.item .frame:not(:has(img)):not(.playing) { aspect-ratio: 4 / 5 !important; }
.item .frame.still img { object-fit: cover; }
.item .frame .ini { font: 800 3rem var(--display); color: var(--soft); }
/* While the video plays it covers the picture or still and the letter. */
.item .frame.playing > :not(iframe) { display: none; }
/* The two media icons under the frame (R-C3), as the design's sill. */
.item .media > .tabs { display: flex; justify-content: center; gap: 0 10px; padding: 0 12px; border-bottom: 1px solid var(--line); }
.item .tabs button { min-height: 44px; min-width: 44px; width: 56px; display: inline-flex; align-items: center; justify-content: center; padding: 0;
  background: none; border: 0; color: var(--soft); cursor: pointer; }
.item .tabs svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.item .tabs button[aria-pressed="true"] { color: var(--ink); }
.item .tabs button[aria-pressed="true"] svg { stroke-width: 2.6; }
@media (hover: hover) { .item .tabs button:hover { color: var(--ink); } }
/* "Picture from <host>": a long host is cut at its left end so the site's name stays readable (R-C4; .src bdi). */
.item .media .src { padding: 6px 12px 0; }

/* ---------- the description (R-D1): the sanitiser's HTML ---------- */
.item > .desc { margin: 0 0 8px; max-width: calc(62ch + 24px); font: 400 .95rem/1.55 var(--body); overflow-wrap: anywhere; }
.item .desc p, .item .desc ul, .item .desc ol, .item .desc blockquote { margin: 0; }
.item .desc > :is(p, ul, ol, blockquote) + * { margin-top: .8em; }
.item .desc ul, .item .desc ol { padding-left: 1.4em; }
.item .desc li + li { margin-top: .25em; }
.item .desc blockquote { padding-left: 12px; border-left: 3px solid var(--line); }
.item .desc a { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: var(--btn-line); }
.item .desc a:hover { text-decoration-color: var(--ink); }

/* ---------- Wikipedia (R-D6, design W2e: bracketed between two ink rules) ---------- */
.item > .wiki { max-width: 62ch; margin: 22px 12px 8px; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); }
.item > .media + .wiki { margin-top: 10px; }
.item .wiki .wh { width: fit-content; margin: -.55em 0 6px; padding-right: 10px; background: var(--card); font: 800 1.05rem/1 var(--display); letter-spacing: .01em; }
.item .wiki .wb p { margin: 0; font: 400 .95rem/1.55 var(--body); overflow-wrap: anywhere; }
.item .wiki .wb p + p { margin-top: .8em; }
.item .wiki .wb p[role="status"], .item .wiki .wb .wstate { color: var(--soft); }
.item .wiki .wb .bx { margin-top: 8px; padding: 0 14px; }
.item .wiki .wb:focus { outline: none; }
.item .wiki .wc { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2px 10px; margin: 10px 0 0; padding-bottom: 10px;
  font: 400 .82rem/1.4 var(--body); color: var(--soft); }
.item .wiki .wa { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin: -10px 0; color: var(--ink); font-weight: 500;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); }
.item .wiki .wa:hover { text-decoration-color: var(--ink); }

/* ---------- the set (R-D2..R-D4): pictures 3 / 4 / 6 columns, videos 2 / 3 ---------- */
.item > .set { margin-top: 16px; padding-bottom: 8px; }
.item .set .grid-sec + .grid-sec { margin-top: 22px; }
.item .set .sh { margin: 0 0 8px; font: 600 1rem/1.2 var(--body); letter-spacing: 0; }
.item .grid { display: grid; min-width: 0; }
.item .pgrid, .item .rgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.item .pgrid { gap: 4px; }
.item .rgrid { gap: 12px 8px; }
.item .vgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 8px; }
@container (min-width: 500px) { .item .pgrid, .item .rgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@container (min-width: 600px) { .item .vgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@container (min-width: 700px) { .item .pgrid, .item .rgrid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.item .tile { min-width: 0; color: var(--ink); text-decoration: none; }
.item .tile:focus-visible { outline-offset: 3px; }
/* A picture tile is a square on the picture background; the letter shows under the picture and after it fails. */
.item .ptile { position: relative; display: block; aspect-ratio: 1; overflow: hidden; background: var(--line); }
.item .ptile .ini, .item .tpic .ini { position: absolute; inset: 0; display: grid; place-items: center; font: 800 1.4rem/1 var(--display); color: var(--soft); letter-spacing: .02em; }
.item .ptile img, .item .tpic img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
/* A video tile: the 16:9 still, the play row under it (never on it). */
.item .vtile { display: grid; grid-template-rows: auto auto; align-content: start; }
.item .vtile .vth { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; background: var(--line); }
.item .vtile .vth img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.item .vtile .prow { display: grid; grid-template-columns: 36px minmax(0, 1fr); gap: 8px; align-items: center; min-height: 44px; padding-top: 6px; }
.item .vtile .pb { width: 36px; height: 36px; border-radius: 50%; background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); display: grid; place-items: center; }
.item .vtile .pb svg { width: 22px; height: 22px; fill: currentColor; stroke: none; margin-left: 1px; }
.item .vtile .vt { font: 500 .88rem/1.25 var(--body); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
@media (hover: hover) { .item .vtile:hover .pb { background: var(--red); color: var(--white); box-shadow: inset 0 0 0 1.5px var(--red); } }
/* "Show all N …" / "Show fewer …": centred under its grid. */
.item .showall { display: flex; width: 100%; max-width: 320px; margin: 12px auto 0; padding: 0 14px; }

/* ---------- related items (R-E1..R-E3): group headings span the grid's row ---------- */
.item > .rel { margin-top: 24px; padding-bottom: 8px; }
.item .rgrid .gh { grid-column: 1 / -1; margin: 6px 0 -4px; font: 600 1rem/1.2 var(--body); }
.item .rgrid .gh:first-child { margin-top: 0; }
.item .rtile { display: grid; gap: 6px; align-content: start; }
.item .tpic { position: relative; display: block; aspect-ratio: 1; overflow: hidden; background: var(--line); }
.item .tpic .ini { font-size: 1.6rem; }
.item .rtile .tn { font: 500 .88rem/1.25 var(--body); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.item .rtile:hover .tn { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- the lists it is in (R-E4, R-E5): 16:10 covers ---------- */
.item > .inlists { margin-top: 24px; padding-bottom: 16px; }
.item .lgrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 8px; }
@container (min-width: 600px) { .item .lgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@container (min-width: 800px) { .item .lgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.item .ltile { display: grid; gap: 6px; align-content: start; min-width: 0; color: var(--ink); text-decoration: none; }
.item .ltile:focus-visible { outline-offset: 3px; }
.item .ltile .cover { position: relative; display: grid; place-items: center; aspect-ratio: 16 / 10; overflow: hidden; background: var(--line); }
.item .ltile .cname { padding: 8px 10px; font: 800 1.3rem/1 var(--display); color: var(--soft); text-align: center; overflow-wrap: anywhere; }
.item .ltile .cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.item .ltile .ln { font: 600 .92rem/1.25 var(--body); overflow-wrap: anywhere; }
.item .ltile .lc { display: block; margin-top: -4px; color: var(--soft); font: 400 .85rem/1.4 var(--body); }
.item .ltile:hover .ln { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- wide: the frame (320px) beside the description and Wikipedia; the rest full width ---------- */
@media (min-width: 700px) {
  .item { display: grid; grid-template-columns: 320px minmax(0, 1fr); column-gap: 16px; align-items: start; padding-left: 16px; padding-right: 16px; }
  .item > * { grid-column: 1 / -1; min-width: 0; }
  .item > .hd, .item > .desc, .item > .set, .item > .rel, .item > .inlists { padding-left: 0; padding-right: 0; }
  .item > .hd { padding-top: 20px; }
  .item .nm { font-size: 4rem; }
  .item > .media { grid-area: auto; grid-column: 1; grid-row: span 2; }
  .item > .media ~ .desc, .item > .media ~ .wiki { grid-column: 2; }
  .item > .wiki { margin-left: 0; margin-right: 0; }
  .item > .media ~ .wiki { margin-top: 22px; }
  .item > .media + .wiki { margin-top: 10px; }
}

/* ---------- the viewer (R-D5): the whole screen; the stage is the screen minus the bar, so the bar is always on it ---------- */
.viewer { --vbar: calc(64px + env(safe-area-inset-bottom)); position: fixed; inset: 0; z-index: 40; height: 100vh; height: 100dvh;
  display: flex; flex-direction: column; background: var(--black); color: var(--white); }
.viewer .vstage { order: -1; position: relative; flex: none; height: calc(100vh - var(--vbar)); height: calc(100dvh - var(--vbar));
  display: flex; align-items: center; justify-content: center; overflow: hidden; touch-action: pan-y pinch-zoom; }
.viewer .vstage img { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.viewer .vstage iframe { display: block; width: min(100%, calc((100dvh - var(--vbar)) * 16 / 9)); aspect-ratio: 16 / 9; height: auto; border: 0; }
.viewer .vbar { flex: none; height: var(--vbar); display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px 44px;
  grid-template-areas: "prev pos next close" "prev from next close"; grid-template-rows: 1fr 1fr; align-items: center; column-gap: 8px;
  padding: 0 12px env(safe-area-inset-bottom); border-top: 1px solid var(--edge); }
.viewer .vpos, .viewer .vfrom { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 400 .82rem/1.35 var(--body); }
.viewer .vpos { grid-area: pos; align-self: end; color: var(--white); font-weight: 600; }
.viewer .vfrom { grid-area: from; align-self: start; color: var(--grey); }
.viewer .vbar button { width: 44px; height: 44px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 2px; background: transparent; color: var(--white); cursor: pointer; }
.viewer .vbar [data-act="v-prev"] { grid-area: prev; }
.viewer .vbar [data-act="v-next"] { grid-area: next; }
.viewer .vbar [data-act="v-close"] { grid-area: close; }
@media (hover: hover) { .viewer .vbar button:hover { background: var(--raise); } }
.viewer :focus-visible { outline-color: var(--white); }
.viewer .vbar svg { width: 22px; height: 22px; stroke-width: 2; }

/* ---------- JavaScript off: the icons and Show all are not shown (R-F2); with JS on the script owns them ---------- */
html.no-js .js { display: none !important; }

/* ================= FEAT-032: the home feed =================
   The feed CSS of the approved design (pm/resources/designs/home-page-v1.html, "the page" … "the foot of the feed"), scoped
   under the feed section (.hfeed) because the list page already owns .media, .scr, .ds, .foot, .bx and .empty. Two
   adaptations for server markup: the parts are placed in document order (the server renders them in the design's order), so
   an absent part (no tags, no text) leaves no empty grid row; and the boxes of a collage take their area by position, not
   by an inline style. A phone shows every picture edge to edge (R-A4). */
.hfeed .feed { list-style: none; margin: 0; padding: 0; container-name: hfeed; container-type: inline-size; }
/* Locked S7: a band of the page ground between entries. */
.hfeed .entry { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 14px 12px 10px; background: var(--card);
  border-bottom: 8px solid var(--ground); min-width: 0; }
.hfeed .entry > * { min-width: 0; }
.hfeed .ev { margin: 0; font: 400 .82rem/1.4 var(--body); color: var(--soft); }
.hfeed .ev b { font-weight: 600; color: var(--ink); }
.hfeed .ev.ic { display: flex; flex-wrap: wrap; align-items: center; gap: 0 6px; }
.hfeed .ev.ic svg { width: 15px; height: 15px; stroke-width: 2; color: var(--soft); }
.hfeed .hl { margin: 0; font: 600 1.15rem/1.3 var(--body); overflow-wrap: anywhere; }
.hfeed .hl a { display: block; color: var(--ink); text-decoration: none; padding: 10px 0; margin: -10px 0; }
.hfeed .hl a:hover { text-decoration: underline; text-underline-offset: 3px; }
.hfeed .out { display: inline-block; width: .62em; height: .62em; vertical-align: 0; margin-left: .22em; stroke-width: 2.6; }
.hfeed .tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.hfeed .tag { display: inline-flex; align-items: center; min-height: 24px; padding: 0 8px; background: var(--line); border-radius: 2px; color: var(--ink);
  font: 600 .8rem/1.2 var(--body); overflow-wrap: anywhere; }
.hfeed .ds { margin: 0; font: 400 .95rem/1.55 var(--body); max-width: 62ch; overflow-wrap: anywhere; }
.hfeed .media { grid-area: auto; min-width: 0; margin: 0 -12px; } /* not the list row's named area */
.hfeed .rm { justify-self: start; margin: -8px 0 -6px; display: inline-flex; align-items: center; gap: .3em; min-height: 44px; color: var(--ink);
  font: 500 .9rem var(--body); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line);
  overflow-wrap: anywhere; }
.hfeed .rm:hover { text-decoration-color: var(--ink); }
.hfeed .rm svg { width: 14px; height: 14px; stroke-width: 2.2; }
/* ----- the article (A4): the event line, a bolder headline, the picture, the text, the tags, the way out ----- */
.hfeed .A4 { padding: 14px 12px; }
.hfeed .A4 .by { display: flex; flex-wrap: wrap; align-items: center; gap: 0 10px; min-width: 0; }
.hfeed .A4 .hl { font: 700 1.3rem/1.25 var(--body); letter-spacing: -.005em; }
/* A news photo (3:2 to 2:1) is cut to 16:9 edge to edge; any other shape is shown whole (the script decides, after load). */
.hfeed .A4 .scr.cut { aspect-ratio: 16 / 9; }
.hfeed .A4 .scr.cut img { object-fit: cover; }
/* The way out: a full-width box at the end, "Read more on <host>" with the open-in-new icon, centred. */
.hfeed .go { display: flex; align-items: center; justify-content: center; gap: .4em; min-height: 44px; margin-top: 4px; padding: 0 14px;
  border: 1px solid var(--btn-line); border-radius: 2px; color: var(--ink); font: 600 .92rem var(--body); text-decoration: none; min-width: 0; }
.hfeed .go .gt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hfeed .go .gl { font-weight: 500; }
.hfeed .go .out { width: 1em; height: 1em; margin: 0; flex: none; color: var(--soft); }
.hfeed .go:hover { border-color: var(--ink); }
.hfeed .go:hover .out { color: var(--ink); }
/* ----- the item's picture: its own shape in a thin frame (whole), the credit under it ----- */
.hfeed .frame { border: 1px solid var(--line); border-left: 0; border-right: 0; padding-bottom: 6px; }
.hfeed .scr { --r: 1.5; aspect-ratio: clamp(.8, var(--r), 1.78); background: var(--line); position: relative; overflow: hidden; display: grid; place-items: center; }
.hfeed .scr img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.hfeed .scr .ini { font: 800 2rem var(--display); color: var(--soft); }
.hfeed .scr.still { aspect-ratio: 16 / 9; }
.hfeed .scr.still img { object-fit: cover; }
.hfeed .src { padding: 6px 12px 0; }
/* The list page's media icons under the frame (R-C7): centred, the P4 row's 56px icons. The frame is an inline-size
   container so a playing video takes the list row's playing height: 4:5 on a phone, the 16:9 picture plus YouTube's
   bands (256px) beside the text (FEAT-030 R-C14). While it plays it covers the picture or still and the letter. */
.hfeed .frame { container-type: inline-size; }
.hfeed .sill { justify-content: center; gap: 0 10px; padding: 0 12px; }
.hfeed .tabs button { width: 56px; justify-content: center; }
.hfeed .tabs svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.hfeed .tabs button[aria-pressed="true"] { text-decoration: none; }
.hfeed .tabs button[aria-pressed="true"] svg { stroke-width: 2.6; }
.hfeed .entry.playing .scr { aspect-ratio: auto; height: 125cqw; }
.hfeed .entry.playing .scr > :not(iframe) { display: none; }
@container hfeed (min-width: 700px) { .hfeed .entry.playing .scr { height: calc(56.25cqw + 256px); } }
/* FEAT-040 R-D3: below 360px wide the still's 4:5 frame leaves less than YouTube's 128px bottom band (and, the picture
   centred, as much above it; the top band stacks to 100px there), so the fullscreen control lands on the picture. There
   the playing frame of every surface that shares R-C14's height (list and reader list rows, the item frame, home entries)
   grows to the 16:9 picture plus 256px, never shorter than the still's frame; the row moves back on stop
   (ASSUMPTION-04). From 360px up nothing changes. */
@media (max-width: 359.98px) {
  .row.P4.playing .scr, .item .frame.playing, .hfeed .entry.playing .scr { height: max(125cqw, calc(56.25cqw + 256px)); }
}
/* ----- the text (R-C11): the list page's full-row cut, three lines with a fade, at every width; "Continue reading"
   under it. The script hides the button (and the fade) where the lines hold all the text. ----- */
.hfeed .body { grid-area: auto; min-width: 0; }
.hfeed .clamp { display: block; max-height: var(--cut, calc(1.55em * 3)); -webkit-mask-image: linear-gradient(#000 35%, transparent); mask-image: linear-gradient(#000 35%, transparent); }
.hfeed .clamp.fits { -webkit-mask-image: none; mask-image: none; }
.no-js .hfeed .clamp { max-height: none; -webkit-mask-image: none; mask-image: none; }
.hfeed .ft { grid-area: auto; justify-content: flex-start; margin: -8px 0 -6px; }
.hfeed .ft .dt { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); }
@media (hover: hover) { .hfeed .ft .dt:hover { text-decoration-color: var(--ink); } }
/* ----- the list: inzion's collage, a grid of square boxes, each picture cropped to its box; a dead one leaves the
   member's initial on the ground (layouts per count: designs/web/pages/home/list-collage.html) ----- */
.hfeed .media > a { display: block; color: inherit; text-decoration: none; }
.hfeed .media > a:focus-visible { outline-offset: 3px; }
.hfeed .collage { display: grid; gap: 3px; grid-template-columns: repeat(var(--c, 4), minmax(0, 1fr)); grid-template-rows: repeat(var(--r, 4), minmax(0, 1fr));
  aspect-ratio: var(--c, 4) / var(--r, 4); }
.hfeed .cell { position: relative; background: var(--line); overflow: hidden; display: grid; place-items: center; min-width: 0; min-height: 0; }
.hfeed .cell img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hfeed .cell .ini { font: 800 1.2rem var(--display); color: var(--soft); }
.hfeed .cell:nth-child(1) { grid-area: a; } .hfeed .cell:nth-child(2) { grid-area: b; } .hfeed .cell:nth-child(3) { grid-area: c; }
.hfeed .cell:nth-child(4) { grid-area: d; } .hfeed .cell:nth-child(5) { grid-area: e; } .hfeed .cell:nth-child(6) { grid-area: f; }
.hfeed .cell:nth-child(7) { grid-area: g; } .hfeed .cell:nth-child(8) { grid-area: h; } .hfeed .cell:nth-child(9) { grid-area: i; }
.hfeed .cell:nth-child(10) { grid-area: j; } .hfeed .cell:nth-child(11) { grid-area: k; } .hfeed .cell:nth-child(12) { grid-area: l; }
.hfeed .collage.n1 { --c: 1; --r: 1; aspect-ratio: auto; grid-template-areas: "a"; }
.hfeed .collage.n1 .cell { aspect-ratio: clamp(.8, var(--s, 1), 1.78); }
.hfeed .collage.n1 .cell img { object-fit: contain; }
.hfeed .collage.n2 { --c: 2; --r: 1; grid-template-areas: "a b"; }
.hfeed .collage.n3 { --c: 3; --r: 2; grid-template-areas: "a a b" "a a c"; }
.hfeed .collage.n4 { --c: 4; --r: 2; grid-template-areas: "a a b b" "a a c d"; }
.hfeed .collage.n5 { --c: 4; --r: 3; grid-template-areas: "a a b c" "a a d c" "a a d e"; }
.hfeed .collage.n6 { --c: 4; --r: 3; grid-template-areas: "a a b c" "a a d c" "e e f f"; }
.hfeed .collage.n7 { --c: 4; --r: 3; grid-template-areas: "a a b c" "a a f c" "d e f g"; }
.hfeed .collage.n8 { --c: 4; --r: 4; grid-template-areas: "a a b c" "a a f c" "d e f h" "d g f h"; }
.hfeed .collage.n9 { --c: 4; --r: 4; grid-template-areas: "a a b c" "a a f c" "d e f h" "d g f i"; }
.hfeed .collage.n10 { --c: 4; --r: 4; grid-template-areas: "a a b c" "a a d e" "f g h e" "f i j j"; }
.hfeed .collage.n11 { --c: 4; --r: 4; grid-template-areas: "a a b c" "a a d c" "e f g h" "i i j k"; }
.hfeed .collage.n12 { --c: 4; --r: 4; grid-template-areas: "a a b c" "a a d e" "f g h i" "j k l l"; }
/* ----- wide: the media beside the text (design: the feed's container at 700 px) ----- */
@container (min-width: 700px) {
  .hfeed .entry { grid-template-columns: minmax(0, 1fr) 320px; column-gap: 20px; row-gap: 8px; padding: 16px 16px 12px; align-content: start; }
  .hfeed .entry > * { grid-column: 1; }
  .hfeed .entry > .media { grid-column: 2; grid-row: 1 / span 7; align-self: start; margin: 0; }
  .hfeed .entry.nomedia { grid-template-columns: minmax(0, 1fr); }
  .hfeed .frame { border-left: 1px solid var(--line); border-right: 1px solid var(--line); }
  .hfeed .A4 { padding: 18px 16px 16px; grid-template-columns: minmax(0, 1fr) 360px; column-gap: 24px; }
  .hfeed .A4.nomedia { grid-template-columns: minmax(0, 1fr); }
  .hfeed .A4 .hl { font-size: 1.5rem; }
}
/* ----- the foot (loading, the end, Show more, the failure line) and the empty feed ----- */
.hfeed .foot .bx { padding: 0 16px; }
.hfeed .foot .bx + p, .hfeed .foot p + .bx { margin-top: 4px; }
.hfeed .empty { padding: 48px 12px; border-top: 0; text-align: center; color: var(--ink); }
.hfeed .empty h2 { margin: 0 0 6px; font: 800 1.8rem/1 var(--display); }
.hfeed .empty p { margin: 0; color: var(--soft); font: 400 .95rem/1.5 var(--body); }
.hfeed .empty a { color: var(--ink); }

/* ===== FEAT-036 the voting duel =====
   The locked design (pm/resources/designs/duel-page-v1.html, "the list excerpt" and "the duel page") ported onto the
   server's markup. The list row's states are the row's own (`.row`); every duel rule is scoped under `.duel` (the
   duel's `<main>`), because the list page already owns `.row`, `.rk`, `.media`, `.tabs`, `.busy` and `.lnk`. */

/* ---------- the list row: the static "my N" (the script upgrades it to the menu button), the busy ring, the line ---------- */
.mine-s { min-width: 44px; min-height: 44px; margin: -7px 0; display: inline-flex; align-items: center; justify-content: center; }
.act .up .ptext { margin-right: 8px; white-space: nowrap; }
.act .up[aria-busy="true"] { cursor: progress; }
/* A full row with no text (no description, so no "Continue reading" either): no empty tracks, and no gaps for them, under
   the media; the landing (R-E3) then fits a picture row in a 640px-high screen. The wide layout is the container's own. */
@container (max-width: 699.98px) { .row.full.P4:not(:has(> .body)) { grid-template-areas: "rk tx act" "media media media"; } }
/* The line under the row, once (a first vote, nothing to compare, a failure): the whole width, after the row's parts. */
.row > .ul { grid-column: 1 / -1; }
.ul { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0 10px; padding-top: 6px; border-top: 1px solid var(--line);
  font: 400 .9rem/1.3 var(--body); color: var(--soft); overflow-wrap: anywhere; }
.ul.first { min-height: 44px; padding-top: 4px; }
.ul.err { padding-bottom: 0; }
.ul span { min-width: 0; }

/* ---------- JavaScript off: the duel's stage, foot and dots need the script (R-H1) ---------- */
.no-js .duel .stage, .no-js .duel .acts, .no-js .duel .prog, .no-js .duel .prog + .vh { display: none !important; }

/* ---------- the duel page: one screen (bar, the duel, dock) ---------- */
body.one { height: 100vh; height: 100dvh; display: flex; flex-direction: column; }
body.one > #live-slot > .bar, body.one > .bar { flex: none; }
main.page.duel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; width: 100%; max-width: 920px; margin: 0 auto; padding: 0; }
.duel .head { flex: none; padding: 0 12px; }
.duel .top { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-width: 0; }
.duel .back { display: inline-flex; align-items: center; gap: 4px; min-height: 44px; margin-left: -6px; padding: 0 6px; color: var(--ink); font: 500 .92rem var(--body);
  text-decoration: none; min-width: 0; }
.duel .back span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.duel .back svg { width: 16px; height: 16px; stroke-width: 2.2; }
.duel .back:hover span { text-decoration: underline; text-underline-offset: 3px; }
/* Progress (D-4): a dot per comparison, filled as they are made; the row grows when phase 2 adds its own. */
.duel .prog { display: flex; flex: 0 1 auto; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 4px 8px; min-width: 0; margin: 0; padding: 0; list-style: none; }
.duel .prog li { width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--ink); background: transparent; transition: background .2s; }
.duel .prog li.on { background: var(--ink); }
.duel .prog li.new { animation: pop .3s cubic-bezier(.2, .9, .3, 1.2) both; }
@keyframes pop { from { transform: scale(0); } }
.duel .q { margin: 0; font: 800 clamp(1.5rem, 5vw, 2rem)/1 var(--display); letter-spacing: -.005em; }
/* The h1 takes focus on arrival and after a swap (a place to start from, not a control): no ring. */
.duel .q:focus, .duel .q:focus-visible { outline: none; }
.duel .conf { margin: 4px 0 0; font: 400 .85rem/1.35 var(--body); color: var(--soft); overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* In this line it is the name that gives way: one line with an ellipsis, so "is now #9 in your ranking" always shows. */
.duel .conf b { font-weight: 600; color: var(--ink); display: inline-block; max-width: 58%; vertical-align: bottom; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The phase line (D-8) and the notice line (a stale pick, a failed request) share one quiet shape: a small icon and a sentence. */
.duel .ph, .duel .nt { margin: 4px 0 0; font: 400 .85rem/1.35 var(--body); color: var(--ink); display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px; align-items: start; }
.duel .ph svg, .duel .nt svg { width: 14px; height: 14px; stroke-width: 2; color: var(--soft); margin-top: .2em; }
.duel .nt svg { color: var(--red-ink); }
.duel .nt span { overflow-wrap: anywhere; }
/* Try again runs on in the sentence; its 44px box overlaps the lines above and below, so the line stays one line tall. */
.duel .nt .lnk { display: inline-flex; vertical-align: baseline; min-height: 44px; margin: -12px 0 -12px 4px; padding: 0 4px; font-size: inherit; }
/* Without the script: the notice in <noscript>, one line in the head's place. */
.duel .nt.nojs { grid-template-columns: minmax(0, 1fr); margin: 8px 12px 0; }
/* The foot: Undo at the left, Skip the rest at the right, one 44px row with room around them. */
.duel .acts { flex: none; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0 18px; padding: 8px 12px 10px; }
.duel .lnk { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin-left: -6px; padding: 0 6px; background: none; border: 0; color: var(--ink);
  font: 500 .9rem var(--body); cursor: pointer; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); }
.duel .lnk:hover { text-decoration-color: var(--ink); }
.duel .lnk:disabled { color: var(--soft); text-decoration-color: var(--line); cursor: default; }
.duel .lnk svg { width: 16px; height: 16px; stroke-width: 2.2; }
.duel .acts .lnk { margin-left: 0; padding: 0 10px; }
.duel .acts [data-undo] { margin-left: -10px; }
.duel .acts [data-stop] { margin-left: auto; margin-right: -10px; }
/* A closed duel: no pair to show; one paragraph where the pair was, and the way back. */
.duel .closed { flex: none; margin-top: 8px; padding: 16px 12px; background: var(--card); display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.duel .closed p { margin: 0; max-width: 46ch; font: 400 1rem/1.5 var(--body); overflow-wrap: anywhere; }
.duel .closed b { font-weight: 600; }
.duel .closed .back { margin-left: -6px; }

/* ----- the stage: two halves, the whole height that is left; --a is the upper half's share (the squeeze moves it) ----- */
@property --a { syntax: '<percentage>'; inherits: true; initial-value: 50%; }
.duel .stage { flex: 1 1 auto; min-height: 0; display: grid; grid-template-rows: var(--a, 50%) minmax(0, 1fr); position: relative; margin-top: 8px;
  background: var(--line); touch-action: none; user-select: none; -webkit-user-select: none; }
.duel .stage.snap, .duel .stage.cast { transition: grid-template-rows .22s cubic-bezier(.3, .8, .3, 1); }
.duel .stage.snap .half, .duel .stage.cast .half { transition: opacity .22s; }
.duel .stage.busy { cursor: progress; }
.duel .stage.busy svg { animation: none; } /* not the ring's busy arrow */
/* The idle cue: after a few seconds without input the split bobs down and up and two chevrons show at the join, once per
   pair (the script adds `cue` for 1.5 s). Not while a video plays; off with data-duel-cue="off"; none under reduced motion. */
.duel .cuehint { position: absolute; left: 50%; top: var(--a, 50%); z-index: 3; width: 44px; height: 44px; margin: -22px 0 0 -22px; display: grid; place-items: center;
  border-radius: 50%; background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); opacity: 0; transition: opacity .25s; pointer-events: none; }
.duel .cuehint svg { width: 22px; height: 22px; stroke-width: 2.2; }
.duel .stage.cue .cuehint { opacity: 1; }
.duel .stage.cue { animation: bob 1.5s ease-in-out both; }
@keyframes bob { 0%, 100% { --a: 50%; } 25% { --a: 57%; } 75% { --a: 43%; } }
.duel .half { position: relative; display: flex; flex-direction: column; min-height: 0; min-width: 0; background: var(--card); overflow: hidden; }
.duel .half.a { box-shadow: inset 3px 0 0 var(--red); }
.duel .half:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
/* PRD rev 6 (ASSUMPTION-13): the half's role, focus and name sit on an empty pick button laid over the half; the row
   (name link, media buttons) above it, the Play ring and a playing video above it too. The look is the half's:
   transparent, and the focused half's ring drawn on the half. */
.duel .half > .pick { position: absolute; inset: 0; z-index: 1; margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent;
  cursor: pointer; -webkit-tap-highlight-color: transparent; }
.duel .half > .pick:focus-visible { outline: none; }
.duel .half:has(> .pick:focus-visible) { outline: 3px solid var(--focus); outline-offset: -3px; }
.duel .half > .media { position: static; }
.duel .half > .row { position: relative; z-index: 2; }
.duel .slide iframe { z-index: 3; }
/* The rail: the item's media side by side, one per screen, snapping; it pans sideways only. */
.duel .media { grid-area: auto; flex: 1 1 auto; min-height: 0; min-width: 0; position: relative; display: flex; }
.duel .rail { flex: 1 1 auto; min-height: 0; min-width: 0; display: flex; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; scrollbar-width: none;
  touch-action: none; background: var(--line); } /* the script pans it (one medium per swipe, snapped at once) */
.duel .rail::-webkit-scrollbar { display: none; }
.duel .rail.dragging { scroll-snap-type: none; cursor: grabbing; }
.duel .slide { flex: none; width: 100%; height: 100%; scroll-snap-align: start; scroll-snap-stop: always; position: relative; display: grid; place-items: center; }
.duel .slide img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; -webkit-user-drag: none; }
.duel .slide iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.duel .slide .ini { font: 800 3rem var(--display); color: var(--soft); }
/* A picture that does not load: the initial, and the words under it. */
.duel .slide .na { position: absolute; left: 8px; right: 8px; bottom: 8px; text-align: center; font: 500 .8rem/1.3 var(--body); color: var(--soft); }
/* Play: in the middle of the still (the owner's exception to "no buttons over pictures"), the item page's ink ring. */
.duel .ov { position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; margin: -22px 0 0 -22px; display: grid; place-items: center; padding: 0; border: 0;
  background: transparent; cursor: pointer; z-index: 3; }
.duel .ov .pb { width: 36px; height: 36px; border-radius: 50%; background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); display: grid; place-items: center; }
.duel .ov .pb svg { width: 22px; height: 22px; fill: currentColor; stroke: none; margin-left: 1px; }
@media (hover: hover) { .duel .ov:hover .pb { background: var(--red); color: var(--white); box-shadow: inset 0 0 0 1.5px var(--red); } }
.duel .ov:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 50%; }
.duel .slide:has(iframe) .ov { display: none; }
/* The row under the media: the rank and the name at the left (the name links to the item), the media buttons at the right.
   Not the list's `.row` grid. */
.duel .half > .row { position: static; flex: none; display: flex; align-items: center; gap: 4px; min-height: 44px; padding: 0 2px 0 10px; grid-template-areas: none;
  grid-template-columns: none; background: none; border-bottom: 0; border-top: 1px solid var(--line); }
.duel .half.a > .row { padding-left: 13px; border-bottom: 1px solid var(--line); }
.duel .row .tabs { display: inline-flex; flex: none; }
.duel .row .tabs button { min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; background: none; border: 0;
  color: var(--soft); cursor: pointer; }
.duel .row .tabs svg { width: 18px; height: 18px; stroke-width: 1.6; }
.duel .row .tabs button[aria-current="true"] { color: var(--ink); }
.duel .row .tabs button[aria-current="true"] svg { stroke-width: 2.6; }
.duel .row .tabs button b { font: 600 .74rem var(--mono); margin-left: 3px; color: inherit; }
.duel .row .tabs button .cur { display: none; }
.duel .row .tabs button[aria-current="true"] .cur { display: inline; }
.duel .row .tabs button[aria-current="true"] .n { display: none; }
/* Previous and Next for pointers that hover (touch swipes instead). */
.duel .step { display: none; flex: none; }
.duel .step button { min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; background: none; border: 0;
  color: var(--soft); cursor: pointer; }
.duel .step svg { width: 16px; height: 16px; stroke-width: 2.2; }
@media (hover: hover) and (pointer: fine) { .duel .half.many .step { display: inline-flex; } .duel .step button:hover { color: var(--ink); } }
/* The rank in front of the name ("#5"); an item not placed yet says "New" in green. A long name shrinks to 12.5px and, when
   two lines still do not hold it, is cut with an ellipsis at the end of the second line (the script's fit adds `cut`); the
   full name stays the link's text, and is in the half's label and the link's title. */
.duel .nm { flex: 1 1 auto; min-width: 0; margin: 0; line-height: 1.2; display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; gap: 6px; text-align: left; }
.duel .nm .rk { grid-area: auto; position: static; display: inline; gap: 0; font: 700 1rem/1 var(--display); color: var(--ink); font-style: normal; letter-spacing: .01em; }
.duel .nm .rk.new { color: #1A7F37; font: 700 .8rem/1 var(--body); } /* the movement green darkened to 4.9:1 on the light card */
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .duel .nm .rk.new { color: var(--up); } }
[data-theme="dark"] .duel .nm .rk.new { color: var(--up); }
.duel .nm b { min-width: 0; font: 600 var(--fs, .95rem)/1.2 var(--body); overflow-wrap: anywhere; }
/* FEAT-040 R-B1: the link is inline, so it covers the name's text only, on its one or two lines; the rest of the title line
   is the half's pick target (R-B2). A cut name is the one box of its two lines, clamped, so its focus ring encloses what shows;
   that box spans the column, so it takes no taps itself and only the name's text inside it does (code review v1 RC-01). */
.duel .nm b .t { color: inherit; text-decoration: none; -webkit-user-drag: none; }
.duel .nm b .t.cut { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; pointer-events: none; }
.duel .nm b .t.cut > span { pointer-events: auto; }
@media (hover: hover) { .duel .nm b .t:hover { text-decoration: underline; text-underline-offset: .14em; } }
.duel .nm b .t:focus-visible { outline-offset: 2px; }
@media (min-width: 600px) {
  main.page.duel { padding: 0 12px; }
  .duel .head, .duel .acts { padding-left: 0; padding-right: 0; }
  .duel .stage, .duel .acts, .duel .closed { max-width: 680px; width: 100%; margin-left: auto; margin-right: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .duel .stage.cue, .duel .prog li.new, .lbl.land { animation: none !important; }
}

/* ===== FEAT-037 the reader's list page (/u/{user}/{root}), the gate, the nav's "My list" face =====
   The design (pm/resources/designs/my-list-page-v1.html, its header, bar, rank pair, empty and gate rules) ported onto
   the server's markup. Scoped to the page's own parts (`.owner`, `.tb`, `ol[data-clist]`, the clist/gate blocks), because
   the list page keeps its `.lh`, `.rk`, `.pl` and `p.empty` as they are. */

/* ---------- the header: "List by", the switch, the lock line ---------- */
.lh .owner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 12px; margin: 0 0 6px; min-height: 44px; }
.lh .by { display: flex; align-items: center; gap: 7px; min-width: 0; font: 400 .95rem/1.25 var(--body); color: var(--soft); }
.lh .by .un { min-width: 0; overflow-wrap: anywhere; font-weight: 600; color: var(--ink); }
.lh .by .av { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--btn); color: var(--on-btn);
  font: 700 .75rem var(--body); flex: none; }
.visform { display: contents; }
/* The visibility switch: black, grey and white like every control. On = public. The label names the state. */
.vis { min-height: 44px; display: inline-flex; align-items: center; gap: 10px; padding: 0; background: none; border: 0; color: var(--ink);
  font: 600 .9rem var(--body); cursor: pointer; flex: none; -webkit-tap-highlight-color: transparent; }
.vis .tr { position: relative; width: 40px; height: 24px; border-radius: 12px; background: var(--line); box-shadow: inset 0 0 0 1px var(--btn-line); transition: background .18s; }
.vis .tr::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--card);
  box-shadow: 0 0 0 1px var(--btn-line); transition: transform .18s, background .18s; }
.vis[data-on="true"] .tr { background: var(--btn); box-shadow: none; }
.vis[data-on="true"] .tr::after { transform: translateX(16px); background: var(--on-btn); box-shadow: none; }
.vis:focus-visible { outline: none; }
.vis:focus-visible .tr { outline: 3px solid var(--focus); outline-offset: 2px; }
/* Under the "List by" line while the list is private. */
.lh .priv { display: flex; align-items: center; gap: 6px; margin: -4px 0 8px; font: 400 .88rem/1.4 var(--body); color: var(--soft); }
.lh .priv svg { width: 15px; height: 15px; stroke-width: 2; }

/* ---------- the bar: as wide as the rows, with their padding, so its edges and the view switch line up with them ---------- */
.tb { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; padding: 6px 12px;
  background: var(--card); border-bottom: 8px solid var(--ground); }
@media (min-width: 600px) { .tb { padding: 8px 16px; } }
.tb .facts { display: flex; flex-wrap: wrap; align-items: center; gap: 0 14px; min-width: 0; }

/* ---------- the rank pair: the big numeral is the reader's rank, the plate under it the global place ---------- */
ol[data-clist] .rk .pl { --mw: 3.9em; }
ol[data-clist] .rk > .pl { margin: -4px 0 0; }
ol[data-clist] .rk .g { white-space: nowrap; }
/* The owner's big numeral opens the same menu as the plate. It looks like the plain numeral at rest; hovering or opening
   either one tints the plate, so the pair reads as one control. */
.mynum { min-width: 44px; min-height: 44px; margin: -4px 0 -6px; padding: 0; display: grid; place-items: center; background: none; border: 0;
  color: var(--ink); cursor: pointer; font: inherit; -webkit-tap-highlight-color: transparent; }
.mynum:focus-visible { outline-offset: -1px; }
.rk:has(.mynum[aria-expanded="true"]) .pl { --plate: color-mix(in srgb, var(--line) 76%, var(--ink)); }
@media (hover: hover) { .rk:has(.mynum:hover) .pl { --plate: color-mix(in srgb, var(--line) 76%, var(--ink)); } }
/* A row with its menu open sits above the rows after it (each row is its own layer in a view transition). */
.row:has(.mynum[aria-expanded="true"]) { z-index: 10; }
/* The menu stays inside a 320 px screen, clear of the sticky bar and the dock when it is scrolled into view. */
ol[data-clist] .rk .menu { max-width: min(17rem, calc(100vw - 32px)); scroll-margin: 76px 0 12px; }
@media (max-width: 759px) { ol[data-clist] .rk .menu { scroll-margin-bottom: 76px; } }
/* Coming back from a duel: the big numeral lands (the design's `land` keyframes). */
.rk .g.land { animation: land .35s cubic-bezier(.2, .9, .3, 1.2) both; }
/* "Placing…" while Change my rank stands in for the duel: in the row's right-hand slot (no ring on this page). */
ol[data-clist] .act .ptext { white-space: nowrap; }
ol[data-clist] .act .roll.busy { display: inline-flex; }

/* ---------- empty, the gate: a card with a heading, a line and one solid button ---------- */
div.empty[data-testid="clist-empty"], div.empty.gate { margin: 0; padding: 28px 20px 32px; background: var(--card); text-align: left;
  font: 400 1rem/1.5 var(--body); color: var(--ink); border-top: 0; }
div.empty[data-testid="clist-empty"] h2, div.empty.gate h2 { font: 800 1.8rem/1 var(--display); margin: 0 0 8px; color: var(--ink); }
div.empty[data-testid="clist-empty"] p, div.empty.gate p { margin: 0 0 18px; max-width: 46ch; color: var(--soft); }
div.empty[data-testid="clist-empty"] .bx, div.empty.gate .bx { padding: 0 16px; font-size: .9rem; }
.bx.solid { background: var(--btn); color: var(--on-btn); border-color: var(--btn); }
@media (hover: hover) { .bx.solid:hover { border-color: var(--btn); } }

/* ---------- the nav's "My list" face: the letter under the picture, so a picture that fails leaves the letter ---------- */
.top-th { position: relative; }
.top-th img { position: absolute; inset: 0; }

/* ---------- reduced motion: no land, no fold, no knob slide ---------- */
@media (prefers-reduced-motion: reduce) {
  .rk .g.land { animation: none !important; }
  .vis .tr, .vis .tr::after { transition: none !important; }
}

/* ================= FEAT-038: search (design pm/resources/designs/search-v1.html, 02b "the field on top") ================= */
/* The page dims while search is open; a click on it closes search. The bar (and below 760px the dock) stay above it. */
.scrim { position: fixed; inset: 0; z-index: 15; background: rgb(0 0 0 / .55); }
/* The results hang from the bar on the page's own card. The design's class names are short and shared with other pages
   (.nm, .gh, .th, .more), so every rule of the panel is scoped to .sres. */
.sres { position: absolute; left: 0; right: 0; z-index: 2; background: var(--card); color: var(--ink); }
.sres :focus-visible { outline-color: var(--focus); }
.bar .sres { top: 100%; border-bottom: 1px solid var(--line); }
.sres .in { display: block; height: auto; max-width: 1280px; margin: 0 auto; padding: 0 16px; } /* UAT v1 M-01: not the roll's inline-flex .in */
.sres .box { max-height: calc(100dvh - var(--sr-off, 160px)); overflow-y: auto; overscroll-behavior: contain; padding: 0 0 12px; }
.sres .cols { display: grid; gap: 0 40px; align-items: start; }
@media (min-width: 960px) { .sres .cols.two { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } .sres .cols.two > .wide { grid-column: 1 / -1; } }
.sres .grp { list-style: none; margin: 0; padding: 0; min-width: 0; }
.sres .gh { font: 800 1.4rem/1 var(--display); padding: 18px 0 8px; border-bottom: 1px solid var(--btn-line); }
.sres .opt { display: grid; grid-template-columns: 48px minmax(0, 1fr); align-items: center; column-gap: 12px; min-height: 64px; padding: 8px 8px 8px 6px;
  border-bottom: 1px solid var(--line); cursor: pointer; }
.sres .opt.here { grid-template-columns: var(--rk, minmax(2.9rem, max-content)) 48px minmax(0, 1fr); } /* --rk: the group's widest rank (script, UAT v1 m-01) */
.sres .opt.on { background: color-mix(in srgb, var(--ink) 7%, var(--card)); box-shadow: inset 3px 0 0 var(--red); }
@media (hover: hover) { .sres .opt:hover { background: color-mix(in srgb, var(--ink) 5%, var(--card)); } }
.sres .rn { align-self: stretch; display: flex; align-items: center; justify-content: center; padding-right: 10px; border-right: 1px solid var(--line);
  font: 800 1.9rem/1 var(--display); letter-spacing: -.01em; }
.sres .th { width: 48px; height: 48px; background: var(--line); display: grid; place-items: center; overflow: hidden; position: relative; }
.sres .th img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.sres .th .ini { font: 800 1.3rem var(--display); color: var(--soft); }
.sres .tt { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.sres .nm { font: 600 1rem/1.3 var(--body); overflow-wrap: anywhere; }
.sres .nm mark { background: color-mix(in srgb, var(--red) 20%, transparent); color: inherit; border-radius: 1px; box-shadow: 0 0 0 1px color-mix(in srgb, var(--red) 20%, transparent); }
.sres .kd { font: 400 .84rem/1.35 var(--body); color: var(--soft); overflow-wrap: anywhere; }
.sres .opt.more { display: flex; align-items: center; justify-content: center; min-height: 48px; padding-left: 8px; font: 600 .9rem var(--body); text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: 4px; text-decoration-color: var(--btn-line); border-bottom: 0; }
.sres .opt.more.busy { color: var(--soft); text-decoration: none; cursor: progress; }
/* Waiting, nothing found, failed. */
.sres .msg { padding: 18px 0 8px; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.sres .msg p { margin: 0; font: 400 1rem/1.4 var(--body); overflow-wrap: anywhere; }
.sres .msg p.soft { color: var(--soft); font-size: .92rem; }
/* FEAT-041 R-A4: on a list page, "Add “q” as an item" right under the nothing-found line (a link to the list's add page). */
.sres .msg .offer { display: inline-flex; align-items: center; min-height: 44px; margin-top: -10px; color: var(--ink); font: 600 .94rem/1.35 var(--body);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--btn-line); overflow-wrap: anywhere; max-width: 100%; }
@media (hover: hover) { .sres .msg .offer:hover { text-decoration-color: var(--ink); } }
.sres .wbtn { min-height: 44px; display: inline-flex; align-items: center; gap: 8px; padding: 0 14px; background: var(--btn); color: var(--on-btn); border: 0; border-radius: 2px;
  font: 600 .94rem var(--body); cursor: pointer; text-decoration: none; max-width: 100%; overflow-wrap: anywhere; text-align: left; }
.sres .wbtn svg { width: 18px; height: 18px; stroke-width: 2.2; }
.sres .bz { height: 2px; overflow: hidden; position: relative; }
.sres.busy .bz::after { content: ""; position: absolute; top: 0; bottom: 0; width: 30%; background: var(--red); animation: bz 1s linear infinite; }
@keyframes bz { from { left: -30%; } to { left: 100%; } }
.sres.busy .cols { opacity: .55; }
@media (prefers-reduced-motion: reduce) { .sres.busy .bz::after { left: 0; width: 100%; opacity: .6; } }
/* A row reached from search (R-C3): a red edge and a tint that fade over two seconds; reduced motion, the edge only. */
.row.found { animation: found 2.4s ease-out both; }
@keyframes found { 0%, 35% { box-shadow: inset 4px 0 0 var(--red); background: color-mix(in srgb, var(--red) 9%, var(--card)); } 100% { box-shadow: inset 4px 0 0 transparent; background: var(--card); } }
@media (prefers-reduced-motion: reduce) { .row.found { animation: none !important; box-shadow: inset 4px 0 0 var(--red); } }

/* ================= FEAT-039: My lists (/u/{user}/lists) and the sublist / timed-list page =================
   The design (pm/resources/designs/my-lists-page-v1.html, option 02a3 "big hand"; the Private label is treatment C)
   ported onto the server's markup. Scoped to `.mh`, `ul[data-ml]` and the empty block, because the design's short names
   (.act, .pl, .win, .tl, .cnt, .meta, .empty, .who) already mean something on the list pages and in the nav panel.
   The cards' pictures carry no `--i` (the design's script set it), so the stacking is by `:nth-child`. */

/* ---------- the header: "Lists by (avatar) name", said once ---------- */
.mh { padding: 18px 12px; }
.mh h1 { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; font: 800 2.5rem/1 var(--display); letter-spacing: -.005em; min-width: 0; }
.mh .pre { font: 400 1rem/1.2 var(--body); color: var(--soft); flex-basis: 100%; }
.mh .who { display: inline-flex; align-items: center; gap: 10px; min-width: 0; max-width: 100%; margin: 0; }
.mh .un { min-width: 0; overflow-wrap: anywhere; }
.mh .av { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; background: var(--btn); color: var(--on-btn); font: 700 1.05rem var(--body); flex: none; }
@media (min-width: 760px) { .mh { padding: 24px 16px 22px; } .mh h1 { font-size: 3rem; } }

/* ---------- the cards: one rounded card per ranking, the hand held up out of its top ---------- */
ul[data-ml] { list-style: none; margin: 0; padding: 36px 12px 0; display: grid; gap: 40px; min-width: 0; }
/* From 760px the rankings sit further apart, so a raised hand clears the card above (owner, 2026-10-11). */
@media (min-width: 760px) { ul[data-ml] { padding: 54px 16px 0; gap: 76px; } }
[data-ml] .pi { position: relative; min-width: 0; background: var(--card); border-radius: 18px; scroll-margin-top: 76px; }
[data-ml] .pi.open { box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--ink) 30%, var(--card)); }
[data-ml] .tab { display: none; }
/* On a phone the name sits under the hand, full width; from 600px beside it. */
[data-ml] .rr { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "fan act" "txt txt";
  column-gap: 16px; row-gap: 6px; align-items: center; padding: 0 14px 16px; }
@media (min-width: 600px) {
  [data-ml] .rr { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "fan txt act"; padding: 0 22px 20px; }
}

/* ---------- the hand: up to three pictures fanned from one point, #1 (first in the markup) in front ---------- */
[data-ml] .fan { grid-area: fan; position: relative; display: block; flex: none; }
[data-ml] .rr .fan { width: 150px; height: 128px; margin-top: -34px; }
[data-ml] .cd { position: absolute; display: block; width: 70px; height: 102px; left: 40px; top: 8px; border-radius: 10px; transform-origin: 50% 130%;
  box-shadow: 0 0 0 2px var(--card), 0 4px 10px rgb(0 0 0 / .22); transition: transform .45s cubic-bezier(.34, 1.45, .55, 1); }
[data-ml] .cd:nth-child(1) { z-index: 3; }
[data-ml] .cd:nth-child(2) { z-index: 2; transform: rotate(-12deg); }
[data-ml] .cd:nth-child(3) { z-index: 1; transform: rotate(12deg); }
/* Opening a card (or the pile) spreads its hand a frame later (the script adds .spread; never under reduced motion). */
[data-ml] .spread > .rr .cd:nth-child(2), [data-ml] .spread > .kr .cd:nth-child(2) { transform: rotate(-22deg) translateX(-3px); }
[data-ml] .spread > .rr .cd:nth-child(3), [data-ml] .spread > .kr .cd:nth-child(3) { transform: rotate(22deg) translateX(3px); }
@media (min-width: 600px) {
  [data-ml] .rr .fan { width: 190px; height: 150px; margin-top: -44px; }
  [data-ml] .rr .cd { width: 84px; height: 122px; left: 53px; }
}
/* A picture: the item's own picture or its video's still over its first letter; a picture that fails is removed, so the
   letter shows. */
[data-ml] .ph { position: absolute; inset: 0; display: grid; place-items: center; overflow: hidden; border-radius: inherit; background: var(--line); }
[data-ml] .ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
[data-ml] .ph .ini { font: 800 1.15rem var(--display); color: var(--soft); }

/* ---------- the name, the count, the Private label ---------- */
[data-ml] .txt { grid-area: txt; min-width: 0; }
[data-ml] .rr .txt { align-self: start; }
[data-ml] .rr h2 { margin: 0; font: 800 2rem/1.02 var(--display); overflow-wrap: anywhere; }
@media (min-width: 600px) {
  [data-ml] .rr .txt { align-self: end; padding-bottom: 6px; }
  [data-ml] .rr h2 { font-size: 2.3rem; }
}
[data-ml] .nm { color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
/* The name's link covers its row (the hand too); the buttons sit above it. */
[data-ml] .nm::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
@media (hover: hover) { [data-ml] .nm:hover { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; } }
[data-ml] .nm:focus-visible { outline: none; }
[data-ml] .rr:has(> .txt .nm:focus-visible), [data-ml] .kr:has(.nm:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 14px; }
[data-ml] .meta { margin: 5px 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 12px; font: 400 .9rem/1.35 var(--body); }
[data-ml] .cnt { color: var(--soft); font: 400 .9rem/1.4 var(--body); white-space: nowrap; }
[data-ml] .win { display: inline; overflow: visible; color: var(--ink); font: 600 .86rem/1.3 var(--body); overflow-wrap: anywhere; }
/* Private, treatment C: a red tint with red text and the lock. The dark theme's red is lifted a little so the label
   keeps AA contrast on its tint (4.4:1 → 5:1). */
[data-ml] .lock { --lock-ink: var(--red-ink); display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px 3px 8px; border-radius: 999px; white-space: nowrap;
  font: 700 .82rem/1.2 var(--body); color: var(--lock-ink); background: color-mix(in srgb, var(--red-ink) 13%, var(--card)); }
[data-ml] .lock svg { width: 14px; height: 14px; stroke-width: 2.2; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) [data-ml] .lock { --lock-ink: color-mix(in srgb, var(--red-ink) 82%, var(--white)); }
}
[data-theme="dark"] [data-ml] .lock { --lock-ink: color-mix(in srgb, var(--red-ink) 82%, var(--white)); }

/* ---------- the "N lists" pill and the pile's Show/Hide: a small pill drawn inside a 44px tap area ---------- */
[data-ml] .act { grid-area: act; position: relative; z-index: 1; display: block; min-height: 0; }
[data-ml] .rr .act { justify-self: end; align-self: center; margin: 0; }
[data-ml] .tog { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; margin: 0; padding: 0;
  background: none; border: 0; color: var(--ink); font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
[data-ml] .tog .pl { display: inline-flex; align-items: center; gap: 3px; height: 30px; margin: 0; padding: 0 7px 0 11px; border-radius: 999px; white-space: nowrap;
  background: none; border: 1px solid color-mix(in srgb, var(--ink) 18%, var(--card)); font: 600 .84rem var(--body); transition: background .15s, border-color .15s; }
[data-ml] .tog .chev { width: 16px; height: 16px; stroke-width: 2.2; transition: transform .2s; }
[data-ml] .tog[aria-expanded="true"] .chev { transform: rotate(180deg); }
[data-ml] .tog[aria-expanded="true"] .pl { background: color-mix(in srgb, var(--ink) 8%, var(--card)); border-color: transparent; }
@media (hover: hover) { [data-ml] .tog:hover .pl { border-color: color-mix(in srgb, var(--ink) 45%, var(--card)); } }
[data-ml] .tog:focus-visible { outline: none; }
[data-ml] .tog:focus-visible .pl { outline: 3px solid var(--focus); outline-offset: 2px; }

/* ---------- the lists inside: indented rows on rounded connector lines; the "By date" pile one step further in ---------- */
[data-ml] .kids { list-style: none; margin: 4px 0 0 56px; padding: 0 14px 16px 0; position: relative; min-width: 0; }
[data-ml] .kids[hidden] { display: none; }
@media (min-width: 600px) { [data-ml] .kids { margin-left: 104px; } }
[data-ml] .kids .kids { margin: -4px 0 0 30px; padding: 0 0 4px; }
[data-ml] .kl { position: relative; min-width: 0; margin: 0; padding-left: 24px; font: inherit; } /* `.tl` is also the nav panel's label */
[data-ml] .kl::before { content: ""; position: absolute; left: 0; top: 0; width: 16px; height: 40px; border-left: 1.5px solid var(--btn-line);
  border-bottom: 1.5px solid var(--btn-line); border-bottom-left-radius: 12px; }
[data-ml] .kl:not(:last-child)::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; border-left: 1.5px solid var(--btn-line); }
[data-ml] .kr { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "fan txt" "fan act";
  column-gap: 12px; align-items: center; padding: 8px 0; }
@media (min-width: 600px) { [data-ml] .kr { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "fan txt act"; } }
[data-ml] .kr .fan { width: 42px; height: 64px; align-self: start; }
[data-ml] .kr .fan.one .cd { width: 42px; height: 64px; left: 0; top: 0; border-radius: 7px; transform: none; box-shadow: 0 3px 8px rgb(0 0 0 / .18); }
[data-ml] .kr .fan.three { width: 84px; height: 70px; }
[data-ml] .kr .fan.three .cd { width: 38px; height: 56px; left: 23px; top: 6px; border-radius: 7px; }
[data-ml] .kr .fan .ph .ini { font-size: 1rem; }
[data-ml] .kr h3 { margin: 0; font: 600 1rem/1.3 var(--body); overflow-wrap: anywhere; }
[data-ml] .kr h3.tl3 { font: 800 1.3rem/1.05 var(--display); }
[data-ml] .kr .meta { margin-top: 2px; font-size: .86rem; }
[data-ml] .kr .act { justify-self: start; margin-top: 4px; }
@media (min-width: 600px) { [data-ml] .kr .act { justify-self: end; margin: 0; } }

/* ---------- the owner with nothing ranked: "Nothing ranked yet" and "Find a list" ---------- */
div.empty[data-testid="ml-empty"] { margin: 0 12px; padding: 28px 20px 32px; background: var(--card); border-top: 0; border-radius: 18px; text-align: left;
  font: 400 1rem/1.5 var(--body); color: var(--ink); }
div.empty[data-testid="ml-empty"] h2 { font: 800 1.8rem/1 var(--display); margin: 0 0 8px; color: var(--ink); overflow-wrap: anywhere; }
div.empty[data-testid="ml-empty"] p { margin: 0 0 18px; max-width: 46ch; color: var(--soft); }
div.empty[data-testid="ml-empty"] .bx { padding: 0 16px; font-size: .9rem; }
@media (min-width: 760px) { div.empty[data-testid="ml-empty"] { margin: 0 16px; } }

/* ---------- the sublist / timed-list page: the window label under the h1, the root's switch read-only ----------
   PRD v5 R-D3: the same switch, its track drawn unavailable, and a tooltip under it (right-aligned with the switch, so it
   stays inside the page at 320 px; the script re-places it inside the 16 px gutters when the switch wraps). Hover shows it here; focus, a tap and Escape are the script's (.tip-on / .tip-off);
   without the script, keyboard focus on the switch or the link shows it too. A hovering pointer's .tip-hov (the
   script's) keeps it shown over the tooltip and the bridge across its 4 px gap (WCAG 1.4.13). v7: the root's name in it
   is a link, so the tooltip takes taps (no tap-through). */
.lh .win { display: block; overflow: visible; margin: 6px 0 0; font: 600 1rem/1.3 var(--body); color: var(--ink); overflow-wrap: anywhere; }
.visro { position: relative; display: inline-flex; flex: none; }
.visro .vis { cursor: default; }
.visro .vis .tr { opacity: .45; }
/* UAT v2 T-2: off, the live switch is already pale, so dimming alone barely shows; the read-only one is hollow, its
   knob a flat grey dot (computed colours differ from the live switch's in both themes). The label keeps full ink. */
.visro .vis[data-on="false"] .tr { background: transparent; }
.visro .vis[data-on="false"] .tr::after { background: var(--btn-line); box-shadow: none; }
.visro .tip { display: none; position: absolute; top: 100%; right: 0; z-index: 6; width: max-content; max-width: min(18rem, calc(100vw - 32px));
  margin-top: 4px; padding: 8px 10px; border-radius: 6px; background: var(--btn); color: var(--on-btn);
  font: 400 .85rem/1.35 var(--body); overflow-wrap: anywhere; box-shadow: 0 2px 8px rgba(0, 0, 0, .18); cursor: default; }
.visro .tip a { color: inherit; font-weight: 600; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; cursor: pointer; }
.visro .tip a:focus-visible { outline: 2px solid var(--on-btn); outline-offset: 2px; border-radius: 2px; }
.visro .tip::before { content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: 4px; }
@media (hover: hover) { .visro:hover .tip { display: block; } }
.no-js .visro:focus-within .tip, .visro.tip-on .tip { display: block; }
.visro.tip-hov .tip { display: block; }
.visro.tip-off .tip { display: none; }

/* ---------- reduced motion: no spread, no swing ---------- */
@media (prefers-reduced-motion: reduce) {
  [data-ml] .cd, [data-ml] .tog .chev, [data-ml] .tog .pl { transition: none !important; }
}

/* ================= FEAT-041: the add page (/list/{slug}/add) =================
   The design's "add item 02 · a card for the hand" (pm/resources/designs/add-item-v1.html), on the server's markup
   (add_item.tmpl) and the island's (public.js): the head is the list as a hand of its top three with an empty dashed
   place; the signed-in section is one grid that draws the finding card (a ::before behind the label, the field, the
   reading and echo lines and the results) and, from 960 px, the stage beside it; below 960 px the stage follows the
   finding card and a search pick folds the results away. Tokens are the locked palette's. */
.page.add-page, .page:has(> .add-page) { max-width: 1120px; }
.add-page { --lift: 0 1px 0 rgb(0 0 0 / .04), 0 16px 32px -10px rgb(0 0 0 / .30); min-width: 0; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .add-page { --lift: 0 0 0 1px #2E2E2E, 0 18px 36px -10px rgb(0 0 0 / .7); } }
[data-theme="dark"] .add-page { --lift: 0 0 0 1px #2E2E2E, 0 18px 36px -10px rgb(0 0 0 / .7); }

/* The way back to the list this page adds to. */
.add-page .back { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; max-width: calc(100% - 24px); padding: 0 12px; margin-top: 6px;
  color: var(--ink); font: 600 .92rem var(--body); text-decoration: none; }
.add-page .back svg { width: 18px; height: 18px; stroke-width: 2.2; }
@media (hover: hover) { .add-page .back:hover span, .add-page .back:hover:not(:has(span)) { text-decoration: underline; text-underline-offset: 4px; } }

/* ---------- the head: the hand held up out of its card, "Add to", the name, the tags and the count ---------- */
.add-head { margin: 46px 12px 0; background: var(--card); border-radius: 22px; padding: 0 18px 20px; display: grid;
  grid-template-columns: minmax(0, max-content) minmax(7.5em, 1fr); column-gap: 12px; align-items: center; min-width: 0; }
.add-head > * { grid-column: 1 / -1; min-width: 0; }
.add-head .hand { position: relative; width: 224px; height: 150px; margin: -42px 0 8px; }
.add-head .pre { margin: 0; font: 500 1rem/1.2 var(--body); color: var(--soft); }
.add-head h1 { margin: 2px 0 0; font: 800 2.4rem/.98 var(--display); letter-spacing: -.005em; overflow-wrap: anywhere; }
.add-head .ftags, .add-head .tags { grid-column: 1; margin: 10px 0 0; }
.add-head .tags { display: flex; flex-wrap: wrap; gap: 6px; padding: 0; list-style: none; }
.add-head .tags li { display: inline-flex; align-items: center; min-height: 24px; padding: 0 8px; background: var(--line); border-radius: 2px;
  color: var(--ink); font: 600 .8rem/1.2 var(--body); overflow-wrap: anywhere; }
.add-head .count { grid-column: 2; margin: 10px 0 0; color: var(--soft); font: 400 .9rem/1.4 var(--body); }
.add-head h1 + .count, .add-head .tags:empty + .count, .add-head .ftags:empty + .count { grid-column: 1 / -1; }
/* The hand (My lists' fan, FEAT-039): up to three pictures, the letter under each, and the empty place last. */
.add-head .hand .ml-ph { position: absolute; left: 62px; top: 12px; width: 74px; height: 108px; border-radius: 11px; transform-origin: 50% 140%; overflow: hidden;
  background: var(--line); box-shadow: 0 0 0 2px var(--card), 0 5px 12px rgb(0 0 0 / .22); display: grid; place-items: center; }
.add-head .hand .ml-ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.add-head .hand .ml-ph .ini { font: 800 1.5rem var(--display); color: var(--soft); }
.add-head .hand .ml-ph:not(.slot):nth-child(1) { z-index: 4; transform: rotate(-4deg); }
.add-head .hand .ml-ph:not(.slot):nth-child(2) { z-index: 3; transform: rotate(-19deg); }
.add-head .hand .ml-ph:not(.slot):nth-child(3) { z-index: 2; transform: rotate(11deg); }
.add-head .hand .ml-ph.slot { z-index: 1; transform: rotate(25deg); background: transparent; box-shadow: none; border: 2px dashed var(--btn-line); color: var(--soft);
  transition: border-color .2s, color .2s; }
.add-head .hand .ml-ph.slot:not(.filled)::before, .add-head .hand .ml-ph.slot:not(.filled)::after { content: ""; position: absolute; left: calc(50% - 10px); top: calc(50% - 1px);
  width: 20px; height: 2px; border-radius: 1px; background: currentColor; transform: rotate(-25deg); }
.add-head .hand .ml-ph.slot:not(.filled)::after { transform: rotate(65deg); }
.add-head .hand.ready .ml-ph.slot { border-color: var(--ink); color: var(--ink); }
.add-head .hand .ml-ph.slot.filled { border: 0; background: var(--line); box-shadow: 0 0 0 2px var(--card), 0 5px 12px rgb(0 0 0 / .22); }
.add-head .hand .ml-ph.slot.filled .ini { transform: rotate(-25deg); }
.add-head .hand .ml-ph.slot.filled.yt img { object-fit: contain; background: #000; }
@media (min-width: 600px) {
  .add-head { grid-template-columns: auto minmax(0, max-content) minmax(7.5em, 1fr); grid-template-rows: 1fr auto auto auto; column-gap: 12px; padding: 0 26px 22px; }
  .add-head > * { grid-column: 2 / -1; }
  .add-head .hand { grid-column: 1; grid-row: 1 / 5; align-self: end; width: 250px; height: 170px; margin: -48px 10px 0 0; }
  .add-head .hand .ml-ph { left: 70px; width: 86px; height: 124px; }
  .add-head .pre { grid-row: 2; padding-top: 12px; }
  .add-head h1 { grid-row: 3; }
  .add-head .ftags, .add-head .tags { grid-column: 2; grid-row: 4; margin-bottom: 4px; }
  .add-head .count { grid-column: 3; grid-row: 4; margin-bottom: 4px; }
  .add-head h1 + .count, .add-head .tags:empty + .count, .add-head .ftags:empty + .count { grid-column: 2 / -1; }
}
@media (min-width: 760px) { .add-page .back { padding: 0 16px; } .add-head { margin: 54px 16px 0; } .add-head h1 { font-size: 3rem; } }

/* ---------- signed out: sign in before the field (D-6) ---------- */
.add-page .add-gate { margin: 18px 12px 0; background: var(--card); border-radius: 22px; padding: 22px 18px 24px; text-align: left; }
.add-page .add-gate h2 { margin: 0; font: 800 1.9rem/1 var(--display); color: var(--ink); overflow-wrap: anywhere; }
.add-page .add-gate p { margin: 8px 0 18px; max-width: 46ch; color: var(--soft); font: 400 1rem/1.5 var(--body); }
.add-page .add-gate form { margin: 0; }
.add-page .add-gate .pbtn.google { display: inline-flex; width: auto; max-width: 100%; min-height: 48px; margin: 0; padding: 0 22px; border-radius: 999px; font: 500 .96rem var(--body); }
@media (min-width: 760px) { .add-page .add-gate { margin: 22px 16px 0; padding: 26px 26px 28px; } }

/* ---------- the field's section: the finding card (grid rows 1-8, its card a ::before) and the stage ---------- */
.add-field { position: relative; margin: 18px 12px 0; min-width: 0; display: grid;
  grid-template-columns: 16px minmax(0, 1fr) 16px; grid-template-rows: 18px repeat(6, auto) 14px auto; }
.add-field::before { content: ""; grid-column: 1 / 4; grid-row: 1 / 9; background: var(--card); border-radius: 22px; }
.add-field > * { grid-column: 2; min-width: 0; }
.add-field > label { grid-row: 2; display: block; margin: 0 0 12px; font: 800 1.65rem/1 var(--display); color: var(--ink); overflow-wrap: anywhere; }
.add-field > input { grid-row: 3; width: 100%; min-width: 0; min-height: 56px; margin: 0; padding: 0 52px 0 44px; border-radius: 16px; background: var(--ground);
  border: 1.5px solid var(--line); color: var(--ink); font: 500 1.05rem var(--body); outline: none; appearance: none; -webkit-appearance: none; text-overflow: ellipsis; }
.add-field > input:focus { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.add-field > input::placeholder { color: var(--soft); opacity: 1; }
.no-js .add-field > input { padding-left: 16px; padding-right: 16px; }
.add-field > .fic { grid-row: 3; z-index: 1; align-self: center; justify-self: start; margin-left: 16px; display: grid; color: var(--soft); pointer-events: none; }
.add-field > input:focus ~ .fic { color: var(--ink); }
.add-field .fic svg { width: 18px; height: 18px; stroke-width: 2.4; }
.add-field > .clr { grid-row: 3; z-index: 1; align-self: center; justify-self: end; margin-right: 4px; min-width: 48px; min-height: 48px; padding: 0; border: 0; border-radius: 12px;
  background: transparent; color: var(--ink); display: grid; place-items: center; cursor: pointer; font: inherit; }
.add-field > .clr svg { width: 18px; height: 18px; stroke-width: 2.4; }
/* How the field reads the input (R-B2), and a pasted address in full, wrapping. */
.add-field > .reading { grid-row: 4; display: flex; align-items: center; gap: 8px; margin: 12px 2px 0; font: 600 .92rem/1.35 var(--body); color: var(--ink); overflow-wrap: anywhere; }
.add-field > .reading svg { width: 17px; height: 17px; stroke-width: 2.2; flex: none; }
.add-field > .reading span { min-width: 0; }
.add-field > .reading.bad { align-items: flex-start; font-weight: 500; }
.add-field > .reading.bad svg { color: var(--red-ink); margin-top: 1px; }
.add-field > .echo { grid-row: 5; margin: 3px 2px 0 27px; font: 400 .86rem/1.45 var(--body); color: var(--soft); overflow-wrap: anywhere; word-break: break-word; }
.add-field > .nojs { grid-row: 6; margin: 12px 2px 0; font: 400 .92rem/1.45 var(--body); color: var(--soft); }
html:not(.no-js) .add-field > .nojs { display: none; }
.add-field > .add-body { display: contents; }
.add-field > .live { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- the results area: Wikipedia's answer as a listbox of rounded rows, or what happened and what next ---------- */
.add-field .res { grid-column: 2; grid-row: 7; margin-top: 10px; min-width: 0; }
.add-field .res .bz { height: 3px; border-radius: 3px; overflow: hidden; position: relative; margin: 0 2px; }
.add-field .res.busy .bz::after { content: ""; position: absolute; top: 0; bottom: 0; width: 30%; border-radius: 3px; background: var(--red); animation: bz 1s linear infinite; }
.add-field .res.busy .opts { opacity: .5; }
.add-field .opts { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 2px; }
.add-field .opt { display: grid; grid-template-columns: 52px minmax(0, 1fr) auto; align-items: center; column-gap: 12px; min-height: 68px; padding: 8px 10px 8px 8px;
  border-radius: 14px; cursor: pointer; min-width: 0; }
.add-field .opt.on { background: color-mix(in srgb, var(--ink) 7%, var(--card)); }
@media (hover: hover) { .add-field .opt:hover { background: color-mix(in srgb, var(--ink) 5%, var(--card)); } }
.add-field .opt.picked { box-shadow: inset 0 0 0 1.5px var(--ink); }
.add-field .opt .tk { width: 22px; height: 22px; stroke-width: 2.4; display: none; }
.add-field .opt.picked .tk { display: block; }
.add-field .th { width: 52px; height: 52px; border-radius: 10px; background: var(--line); display: grid; place-items: center; overflow: hidden; position: relative; }
.add-field .th img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; background: var(--line); }
.add-field .th .ini { font: 800 1.35rem var(--display); color: var(--soft); }
.add-field .ot { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.add-field .on1 { font: 600 1rem/1.3 var(--body); color: var(--ink); overflow-wrap: anywhere; }
.add-field .od { font: 400 .86rem/1.35 var(--body); color: var(--soft); overflow-wrap: anywhere; }
.add-field .credit { margin: 10px 2px 0; font: 400 .82rem/1.4 var(--body); color: var(--soft); }
.add-field .msg { margin: 14px 2px 4px; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.add-field .msg p { margin: 0; font: 400 1rem/1.45 var(--body); color: var(--ink); overflow-wrap: anywhere; }
.add-field .msg.soft p { color: var(--soft); font-size: .92rem; }
.add-field .wbtn { min-height: 44px; display: inline-flex; align-items: center; gap: 8px; padding: 0 16px; background: transparent; color: var(--ink); border: 1px solid var(--btn-line);
  border-radius: 2px; font: 600 .9rem var(--body); cursor: pointer; }
.add-field .wbtn svg { width: 17px; height: 17px; stroke-width: 2; }
@media (hover: hover) { .add-field .wbtn:hover { border-color: var(--ink); } }

/* ---------- the stage: the empty place, a link being read, the big upright card with its source on a tab ---------- */
.add-field .stage { grid-column: 1 / -1; grid-row: 9; display: grid; justify-items: center; gap: 18px; padding: 30px 0 4px; min-width: 0; }
.add-field .pick { display: grid; justify-items: center; gap: 18px; width: 100%; min-width: 0; }
.add-page .big { position: relative; width: min(100%, 330px); border-radius: 22px; background: var(--card); box-shadow: var(--lift); text-align: left; }
.add-page .big .tab { position: absolute; bottom: calc(100% - 6px); right: 22px; max-width: calc(100% - 64px); display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px 10px; border-radius: 12px 12px 0 0; background: var(--card); color: var(--ink); font: 700 .8rem/1.2 var(--body); overflow-wrap: anywhere;
  box-shadow: 0 -6px 12px -8px rgb(0 0 0 / .35); }
.add-page .big .tab svg { width: 15px; height: 15px; stroke-width: 2.2; flex: none; }
.add-page .face { position: relative; margin: 10px 10px 0; border-radius: 15px; aspect-ratio: 1; overflow: hidden; display: grid; place-items: center;
  background: color-mix(in srgb, var(--ink) 8%, var(--card)); }
.add-page .face img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; background: color-mix(in srgb, var(--ink) 8%, var(--card)); }
.add-page .face.yt { background: #000; aspect-ratio: 4 / 3; }
.add-page .face.yt img { background: #000; }
.add-page .face .ini { font: 800 5.5rem/1 var(--display); color: var(--soft); }
.add-page .face.yt .ini { color: #B3B3B3; }
.add-page .cb { padding: 14px 18px 18px; min-width: 0; }
.add-page .cb h2 { margin: 0; font: 800 1.9rem/1.02 var(--display); color: var(--ink); overflow-wrap: anywhere; }
.add-page .cb h2:focus { outline: none; }
.add-page .cb h2:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.add-page .cb .ds { margin: 6px 0 0; color: var(--soft); font: 400 .92rem/1.4 var(--body); overflow-wrap: anywhere; }
.add-page .cb .ex { margin: 10px 0 0; color: var(--ink); font: 400 .92rem/1.5 var(--body); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; line-clamp: 4;
  -webkit-box-orient: vertical; overflow: hidden; }
.add-page .cb .np { margin: 10px 0 0; font: 400 .88rem/1.45 var(--body); color: var(--soft); }
/* Nothing picked yet (960 px and up): the place the card will take. */
.add-page .big.empty { background: transparent; box-shadow: none; border: 2px dashed var(--btn-line); }
.add-page .big.empty .face { background: transparent; color: var(--soft); aspect-ratio: 4 / 3; }
.add-page .big.empty .face svg { width: 34px; height: 34px; stroke-width: 1.8; }
.add-page .big.empty .cb p { margin: 0; color: var(--soft); font: 400 .92rem/1.45 var(--body); }
/* A link being read: the card waits with what is known (the source), its face shimmering. */
.add-page .big.wait .face { aspect-ratio: 4 / 3; }
.add-page .big.wait .face::after { content: ""; position: absolute; inset: 0; background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--card) 55%, transparent) 50%, transparent 70%);
  background-size: 220% 100%; animation: add-sh 1.3s linear infinite; }
@keyframes add-sh { from { background-position: 120% 0; } to { background-position: -120% 0; } }
.add-page .big.wait .cb { display: grid; gap: 10px; }
.add-page .big.wait .ln { display: block; height: 14px; border-radius: 7px; background: color-mix(in srgb, var(--ink) 8%, var(--card)); }
.add-page .big.wait .ln.short { width: 60%; }
/* The card on its way into the hand (a clone; reduced motion: none). */
.add-page .big.flying { position: fixed; z-index: 50; margin: 0; transform-origin: 0 0; pointer-events: none; }
.add-page .big.gone { visibility: hidden; }
.add-field .acts { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; width: min(100%, 360px); }
.add-field .go { flex: 1 1 auto; min-height: 44px; max-width: 100%; padding: 0 16px; background: transparent; color: var(--ink); border: 1px solid var(--btn-line); border-radius: 2px;
  font: 600 .9rem var(--body); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 7px; white-space: nowrap; }
.add-field .go svg { width: 17px; height: 17px; stroke-width: 2; }
@media (hover: hover) { .add-field .go:hover { border-color: var(--ink); } }
.add-field .go[aria-disabled="true"] { cursor: progress; opacity: .75; }
/* The send's outcome: a refusal or a failure under the card (the design's failure style), the added line in its place. */
.add-field .err { width: min(100%, 360px); margin: 0; display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: 14px; color: var(--ink);
  background: color-mix(in srgb, var(--red-ink) 10%, var(--card)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--red-ink) 40%, var(--card)); font: 400 .92rem/1.45 var(--body); }
.add-field .err svg { width: 18px; height: 18px; stroke-width: 2.2; flex: none; color: var(--red-ink); margin-top: 1px; }
.add-field .err span { min-width: 0; overflow-wrap: anywhere; }
.add-field .sent { width: min(100%, 360px); padding: 20px 20px 18px; border-radius: 22px; background: var(--card); text-align: left; }
.add-field .sent .line { margin: 0; font: 600 1.05rem/1.4 var(--body); color: var(--ink); overflow-wrap: anywhere; }
.add-field .sent .bz { height: 3px; border-radius: 3px; overflow: hidden; position: relative; margin: 14px 0 0; }
.add-field .sent .bz::after { content: ""; position: absolute; top: 0; bottom: 0; width: 30%; border-radius: 3px; background: var(--red); animation: bz 1s linear infinite; }
@media (max-width: 959px) {
  .add-field .stage.idle { display: none; }
  .add-field.picked .res { display: none; }
}
@media (min-width: 760px) {
  .add-field { margin: 22px 16px 0; grid-template-columns: 22px minmax(0, 1fr) 22px; grid-template-rows: 22px repeat(6, auto) 16px auto; }
}
/* From 960 px the card stands beside the results; the stage spans every row (a last flexible row takes its height). */
@media (min-width: 960px) {
  .add-field { grid-template-columns: 22px minmax(0, 1fr) 22px 28px minmax(0, 380px); grid-template-rows: 22px repeat(6, auto) 16px 1fr; }
  .add-field .stage { grid-column: 5; grid-row: 1 / 10; align-self: start; position: sticky; top: 84px; padding-top: 30px; }
}
@media (prefers-reduced-motion: reduce) {
  .add-page *, .add-page *::before, .add-page *::after { animation: none !important; transition: none !important; }
  .add-field .res.busy .bz::after, .add-field .sent .bz::after { left: 0; width: 100%; opacity: .6; }
}

/* ---------- FEAT-041 R-C4: the list page's one-shot notice (FEAT-036's notice look: a red mark, then the line) ---------- */
.flash { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; align-items: start; margin: 10px 12px 0; padding: 10px 12px; background: var(--card);
  border-radius: 2px; box-shadow: inset 3px 0 0 var(--red-ink); color: var(--ink); font: 400 .9rem/1.4 var(--body); overflow-wrap: anywhere; }
.flash::before { content: "!"; display: grid; place-items: center; width: 16px; height: 16px; margin-top: .1em; border: 2px solid var(--red-ink); border-radius: 50%;
  color: var(--red-ink); font: 700 .65rem/1 var(--body); }
@media (min-width: 760px) { .flash { margin: 12px 16px 0; } }

/* ================= FEAT-042: the site footer, the long-text pages, the HTML sitemap =================
   Appended to public.css as written. Existing tokens only (colours and the three families); sizes and spaces are the
   steps the stylesheet already uses (4 · 8 · 12 · 16 · 24 · 32 · 40). Class names are component-prefixed:
   .site-footer__*, .doc__* / .doc-table__*, .sitemap__*. Plain, unlayered rules like the rest of the file. */

/* ---------- the site footer (R-B1–R-B3): the page's contentinfo, black like the bar and the dock in both themes ---------- */
.site-footer { background: var(--black); color: var(--white); border-top: 1px solid var(--edge); }
/* Never the scroll anchor: when a batch of rows lands above the footer the viewport must stay where it is, as it did
   before the footer existed, else the browser keeps the footer in view, scrolls onto the next sentinel and chains batches. */
.site-footer { overflow-anchor: none; }
/* On a page shorter than the screen the black runs on under the footer, so the footer never floats mid-screen. */
html:has(> body > .site-footer) { background: var(--black); }
.site-footer__wrap { max-width: 1280px; margin: 0 auto; padding: 32px 16px 16px; }
.site-footer__nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px 16px; }
.site-footer__group { min-width: 0; }
.site-footer__group--topics { grid-column: 1 / -1; }
.site-footer__heading { margin: 0 0 4px; font: 800 1.5rem/1 var(--display); letter-spacing: -.005em; color: var(--white); }
/* The first group's heading is the wordmark: its accessible name stays "hitimes". */
.site-footer__hi { color: var(--red); }
.site-footer__links { list-style: none; margin: 0; padding: 0; }
.site-footer__link { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 4px 0; color: var(--grey);
  font: 500 .94rem/1.3 var(--body); text-decoration: none; overflow-wrap: anywhere; }
.site-footer__link:hover { color: var(--white); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.site-footer__link:focus-visible { outline-color: var(--white); outline-offset: 2px; }
/* The page you are on: white, with the nav's red mark standing on its left edge. */
.site-footer__link[aria-current="page"] { color: var(--white); }
.site-footer__link[aria-current="page"]::before { content: ""; flex: none; align-self: stretch; width: 3px; margin: 8px 0; background: var(--red); }
.site-footer__link--all { color: var(--white); font-weight: 600; }
.site-footer__icon { width: 16px; height: 16px; stroke-width: 2; }
.site-footer__base { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 24px;
  margin-top: 24px; padding-top: 4px; border-top: 1px solid var(--edge); }
.site-footer__copy { margin: 0; min-height: 44px; display: flex; align-items: center; font: 400 .86rem/1.4 var(--body); color: var(--grey); }
@media (min-width: 520px) {
  .site-footer__links--topics { columns: 2; column-gap: 24px; }
  .site-footer__item { break-inside: avoid; }
}
@media (min-width: 760px) {
  .site-footer__wrap { padding-top: 40px; }
  .site-footer__nav { column-gap: 32px; }
  .site-footer__links--topics { columns: 3; column-gap: 32px; }
}
@media (min-width: 1100px) {
  .site-footer__nav { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 3fr); }
  .site-footer__group--topics { grid-column: auto; }
}
/* Below 760px the dock is fixed to the bottom of the screen and the body keeps 64px for it. The footer reaches into
   that space, so the black runs to the end of the page, and its own padding holds the last line clear of the dock. */
@media (max-width: 759px) {
  .site-footer { margin-bottom: -64px; }
  .site-footer__wrap { padding-bottom: calc(64px + 16px + env(safe-area-inset-bottom)); }
}

/* ---------- the long-text pages (R-A2): About, How it works, Contact and the four legal pages ---------- */
.doc { padding: 22px 12px 8px; }
.doc__head, .doc__body { max-width: 37rem; }
.doc__head { padding-bottom: 16px; border-bottom: 2px solid var(--ink); }
.doc__head--plain { max-width: none; border-bottom: 0; padding-bottom: 0; }
.doc__title { margin: 0; font: 800 2.5rem/.98 var(--display); letter-spacing: -.005em; overflow-wrap: anywhere; }
.doc__updated { margin: 12px 0 0; font: 400 .9rem/1.4 var(--body); color: var(--soft); }
.doc__body { container: doc / inline-size; padding-top: 8px; }
.doc__h2 { margin: 32px 0 8px; font: 800 1.75rem/1.05 var(--display); letter-spacing: -.005em; scroll-margin-top: 80px; }
.doc__h3 { margin: 24px 0 4px; font: 700 1.06rem/1.35 var(--body); scroll-margin-top: 80px; }
.doc__p { margin: 0 0 16px; font: 400 1rem/1.65 var(--body); overflow-wrap: break-word; }
.doc__lead { font-size: 1.25rem; line-height: 1.45; font-weight: 500; }
.doc__list { margin: 0 0 16px; padding: 0 0 0 20px; list-style: square; }
.doc__item { margin: 0 0 8px; padding-left: 4px; font: 400 1rem/1.6 var(--body); overflow-wrap: break-word; }
.doc__item::marker { color: var(--soft); }
.doc__link { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: var(--btn-line); }
.doc__link:hover { text-decoration-color: var(--ink); text-decoration-thickness: 2px; }
/* The contact address: the lead line's link, a full 44px target. */
.doc__link--mail { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; overflow-wrap: anywhere; }
.doc__code { font: 500 .86em/1.2 var(--mono); padding: 1px 5px; background: var(--line); border-radius: 2px; overflow-wrap: anywhere; }
.doc__address { margin: 24px 0 16px; font: 400 .94rem/1.6 var(--body); font-style: normal; color: var(--soft); }
@media (min-width: 760px) { .doc { padding-left: 16px; padding-right: 16px; } }

/* ---------- the policy tables (R-A6): a table from 560px of text column; below, one block per row ---------- */
.doc-table { width: 100%; margin: 4px 0 24px; border-collapse: collapse; font: 400 .94rem/1.5 var(--body); }
.doc-table__th { padding: 0 12px 8px 0; text-align: left; vertical-align: bottom; font: 600 .86rem/1.3 var(--body); color: var(--soft); border-bottom: 2px solid var(--ink); }
.doc-table__name, .doc-table__cell { padding: 12px 12px 12px 0; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.doc-table__name { font-weight: 400; }
.doc-table__name .doc__code { white-space: nowrap; }
.doc-table__th:last-child, .doc-table__cell:last-child { padding-right: 0; }
@container doc (max-width: 559px) {
  .doc-table, .doc-table__body, .doc-table__row, .doc-table__name, .doc-table__cell { display: block; }
  .doc-table__head { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .doc-table { border-top: 2px solid var(--ink); }
  .doc-table__row { padding: 12px 0; border-bottom: 1px solid var(--line); }
  .doc-table__name, .doc-table__cell { padding: 0; border: 0; }
  .doc-table__name { margin-bottom: 4px; }
  .doc-table__name .doc__code { white-space: normal; }
  .doc-table__cell + .doc-table__cell { margin-top: 2px; }
  /* The column's name, shown before its value; screen readers already hear it from the header, so it is hidden from them. */
  .doc-table__cell[data-label]::before { content: attr(data-label) ": "; content: attr(data-label) ": " / ""; font-weight: 600; color: var(--soft); }
}

/* ---------- the HTML sitemap (R-E1, R-E2): Pages, then Lists by topic, two columns from 760px ---------- */
.sitemap__group { margin-top: 32px; }
.sitemap__heading { margin: 0 0 4px; padding-bottom: 8px; font: 800 1.75rem/1.05 var(--display); letter-spacing: -.005em; border-bottom: 2px solid var(--ink); }
.sitemap__pages { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr)); column-gap: 24px; }
.sitemap__link { display: flex; align-items: center; min-height: 44px; padding: 4px 0; color: var(--ink); font: 500 .94rem/1.3 var(--body);
  text-decoration: none; overflow-wrap: anywhere; }
.sitemap__link:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.sitemap__topics { margin: 0; }
.sitemap__topic { break-inside: avoid; padding: 12px 0 8px; border-bottom: 1px solid var(--line); }
/* The lists whose topic is not public: one flat block, free to run across the columns. */
.sitemap__topic--rest { break-inside: auto; }
.sitemap__topic-name { margin: 0; font: 800 1.4rem/1.05 var(--display); letter-spacing: -.005em; overflow-wrap: anywhere; }
.sitemap__topic-link { display: flex; align-items: center; min-height: 44px; color: var(--ink);
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 5px; text-decoration-color: var(--btn-line); }
.sitemap__topic-link:hover { text-decoration-color: var(--ink); }
/* A topic that is not itself on the sitemap: its name as a plain heading, soft, no underline. */
.sitemap__topic-name--plain { display: flex; align-items: center; min-height: 44px; color: var(--soft); }
.sitemap__lists { list-style: none; margin: 0 0 4px; padding: 0 0 0 16px; border-left: 1px solid var(--line); }
.sitemap__lists--timed { margin: 0 0 4px; }
@media (min-width: 760px) {
  .sitemap__topics { columns: 2; column-gap: 40px; }
}

/* ================= FEAT-050: the neighbourhood view (the gap, the landed row) =================
   Appended to public.css as written. Existing tokens only (--ground, --card, --ink, --soft, --btn-line, --red); the
   sizes are the stylesheet's existing steps (the foot's 20px/12px padding, the .bx 44px control, the .g numeral). */

/* ----- the landed row (R-C1): the site's "you are here" mark, a red bar on the row's left edge, for as long as the
   page is open. No other row has the bar, so the mark is a shape and not only a colour (NFR Accessibility; 4.8:1 on the
   light card, 3.4:1 on the dark one). It is drawn over the row's parts, because a phone's picture frame runs edge to
   edge. aria-current="true" names it for assistive technology and is the one hook for the script and the tests. */
.list > .row[aria-current="true"]::before { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 4px; background: var(--red);
  z-index: 1; pointer-events: none; }
/* Reached from search (FEAT-038 R-C3): the tint still fades over two seconds; the edge is the mark's, so it stays. */
.row[aria-current="true"].found { animation-name: found-landed; }
@keyframes found-landed { 0%, 35% { background: color-mix(in srgb, var(--red) 9%, var(--card)); } 100% { background: var(--card); } }

/* ----- the gap (R-B1): one group, named by its count, with an action at each edge. "Show more" sits under the top
   part and adds rows downward from it; "Show earlier" sits over the neighbourhood and adds rows upward from it. Each
   action is next to the rows it extends, and its arrow points the way the new rows open. Between them, the count, set
   like a row's numeral, between two folds: thin strips of the row card on the page ground, the rows folded away. */
.gap { display: flex; flex-direction: column; align-items: center; padding: 20px 12px; text-align: center; }
.gap .bx { width: 100%; max-width: 320px; }
.gap__fold { display: block; align-self: stretch; height: 20px; margin: 16px -12px;
  background: linear-gradient(var(--card), var(--card)) 0 0 / 100% 6px no-repeat, linear-gradient(var(--card), var(--card)) 0 10px / 100% 4px no-repeat,
    linear-gradient(var(--card), var(--card)) 0 18px / 100% 2px no-repeat; }
/* The strips thin toward the count from both sides, so the rows read as pressed together there. */
.gap__count ~ .gap__fold { transform: scaleY(-1); }
.gap__count { margin: 0; min-height: 44px; display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: 0 8px;
  font: 400 .92rem/1.5 var(--body); color: var(--soft); }
.gap__num { font: 800 2.2rem/1 var(--display); letter-spacing: -.01em; color: var(--ink); }
/* In flight (R-B5): the action stays where it was and keeps focus; it says it is loading and takes no second click
   (aria-disabled; the script ignores it). The search panel's red bar runs along its bottom edge. */
.gap .bx[aria-disabled="true"] { position: relative; overflow: hidden; color: var(--soft); cursor: progress; }
.gap .bx[aria-disabled="true"]::after { content: ""; position: absolute; bottom: 0; left: 0; width: 30%; height: 2px; background: var(--red);
  animation: bz 1s linear infinite; }
@media (hover: hover) { .gap .bx[aria-disabled="true"]:hover { border-color: var(--btn-line); } }
@media (prefers-reduced-motion: reduce) { .gap .bx[aria-disabled="true"]::after { width: 100%; opacity: .6; animation: none; } }
/* Failed (R-B5): the foot's failure line and its Try again, at the end that failed; the count and the other end stay. */
.gap__fail { margin: 0; min-height: 44px; display: grid; place-items: center; font: 400 .92rem/1.5 var(--body); color: var(--soft); }
.gap__fail + .bx { margin-top: 4px; }

/* The landed row is the address's fragment target (R-A1, R-C5): with JavaScript off the browser's own jump puts it at
   the very top, under the sticky bar (65px); this margin leaves its top just under the bar (mockups rev 2, the value the
   row menu uses for the same job). The script's landing sets its own position. */
.list > .row[aria-current="true"] { scroll-margin-top: 76px; }
