/* Moviography — the interface.
 *
 * UX.md, "what done means": calm, obvious, trustworthy, fast. Attractive is not
 * the target and is not a substitute.
 *
 * The design brief in one line: this should read like a well-made book, not
 * like a dashboard. An archive is looked at slowly, often years after it was
 * written, sometimes by somebody who did not write it. Everything below serves
 * that — a serif for anything that carries meaning, a sans for the machinery
 * around it, and enough quiet that the memories are the loudest thing on the
 * page.
 *
 * No web fonts. The archive works offline, ships no dependency it does not
 * need, and a font that fails to load must never be the reason somebody cannot
 * read their own life.
 */

/* --- typefaces ------------------------------------------------------------
 *
 * Bundled as files in static/fonts/, not pulled from a CDN. The rule was "no
 * web fonts" and its reasoning was about third parties — a CDN is a dependency,
 * a tracker, and a thing that breaks offline. A font committed to the
 * repository is none of those. The correct rule is "no *remote* fonts".
 *
 * **Fraunces** for display. The previous pick was Bodoni Moda, a didone whose
 * hairlines are its whole character — and at heading sizes on a dark ground
 * those hairlines thin out until the word is a shape rather than a word. Josh
 * called the headers unreadable and was right. Fraunces carries its weight in
 * the strokes instead of in the contrast between them, so it stays legible
 * while still looking like a poster rather than a UI.
 *
 * **Newsreader** for text. Drawn for editorial body copy — a face for reading
 * paragraphs, which is what a memory is.
 *
 * Both are the opposite of a neutral grotesque, which is what every dark film
 * site is set in and what kept this one looking like one.
 */

@font-face { font-family:"Fraunces"; font-weight:600; font-style:normal;
  font-display:swap; src:url("fonts/fraunces-600.woff2") format("woff2"); }
@font-face { font-family:"Fraunces"; font-weight:700; font-style:normal;
  font-display:swap; src:url("fonts/fraunces-700.woff2") format("woff2"); }
@font-face { font-family:"Newsreader"; font-weight:400; font-style:normal;
  font-display:swap; src:url("fonts/newsreader-400.woff2") format("woff2"); }
@font-face { font-family:"Newsreader"; font-weight:400; font-style:italic;
  font-display:swap; src:url("fonts/newsreader-400i.woff2") format("woff2"); }
@font-face { font-family:"Newsreader"; font-weight:600; font-style:normal;
  font-display:swap; src:url("fonts/newsreader-600.woff2") format("woff2"); }

/* The palette: a warm dark room.
 *
 * The base was a cold blue-grey, which is exactly what Letterboxd is built on
 * (#14181c) and is why the resemblance survived two font changes. The colour of
 * the room was doing more work than the typography.
 *
 * So: warm dark. Espresso and oxblood rather than blue-black — a picture palace
 * with velvet in it, not a screen in an office. Cream text on a warm ground,
 * with one deliberately cool accent so the scheme has tension rather than being
 * uniformly nostalgic.
 *
 * Four roles, each with exactly one job. Nothing is coloured to look nice:
 *
 *   brass    the archive's own voice — actions, links, its own count
 *   screen   things from outside you — evidence, documents, imports
 *   curtain  disagreement, and nothing else
 *   velvet   a surface, not an accent: the masthead and the prompt sit on it
 *
 * Spending the alarm colour on buttons leaves nothing to raise a voice with
 * when two accounts genuinely conflict, which is the loudest thing this
 * software ever has to say.
 */

:root {
  --paper:      #16110e;   /* the room: espresso, not blue-black */
  --paper-deep: #0e0a08;
  --velvet:     #1f1310;   /* a surface with red in it */
  --card:       #221a15;
  --ink:        #f4ebdd;   /* cream, warm against a warm ground */
  --ink-soft:   #b3a692;
  --ink-faint:  #8e8271;
  --rule:       #372c24;
  --rule-soft:  #2a201a;

  --accent:      #e8a33d;   /* brass */
  --accent-soft: #b47f2c;
  --screen:      #5fc9c2;   /* the one cool note */
  --flag:        #e2645c;   /* curtain */
  --on-accent:   #1a1109;

  --display: "Fraunces", ui-serif, Georgia, serif;
  --serif:   "Newsreader", ui-serif, Georgia, serif;
  --sans:    "Newsreader", ui-serif, Georgia, serif;

  /* Two widths, and the difference between them is the whole rule.
     --page is the column. --prose is running text, and it is deliberately the
     same value: prose fills the column, so every paragraph ends where the
     headings, the timeline and the indexes end. One right edge.

     46rem until 2026-08-16, when Josh said the content was not filling its
     container. He was right, and the cause was not the column: the masthead
     was full-bleed inside and out, so a 46rem column sat in a 90rem window
     with nothing to line up against. The band now holds its contents in this
     same column — and at 46rem the nav wrapped onto a second line, which is
     what set the new value. 54rem is the width at which the header fits on one
     line and the page has a left edge that means something. The prose measure
     goes to about 77 characters, which is the top of the comfortable range and
     not past it.
     --measure is narrower and belongs to controls only — a date input or a
     select 43rem wide is worse, not better. Text that stops short of the page
     for no reason reads as a rendering fault, which is exactly how it was read
     before this was fixed. */
  /* The masthead is a band, not the top of the page.
     It was sitting at 1.03:1 against the background in the warm dark, and
     1.05:1 in projection and nitrate — a difference no display actually
     renders, so the top of every screen dissolved into the room behind it.
     Measured, not guessed: the numbers are in the report.

     --band-lift raises the masthead toward the palette's *own* ink, which is
     why one number serves all five. Warm cream lifts the warm rooms, cool
     white lifts the cold ones, and each palette keeps its hue instead of
     drifting grey.

     Set to 5% by eye, on the real screens, after 10% was tried and judged too
     strong. That puts the palettes between 1.16 and 1.23 against their page —
     under the ~1.2 rule of thumb for a difference most displays render
     reliably, so this is nearer the floor than the middle. It is a deliberate
     call and not an oversight: the number that reads right on the display the
     archive is actually used on beats the number that reads right in a table.
     If the band ever goes faint again on a different monitor, this is the
     first thing to raise.

     Past about 14% the nav links fall under 4.5:1 in the warm palettes, so
     that is the ceiling. */
  --band-lift: 5%;

  --measure: 34rem;
  --prose:   54rem;
  --page:    54rem;
  --radius:  7px;
  --grain-opacity: .26;

  --beam: radial-gradient(120% 55% at 50% -8%,
          rgba(232, 163, 61, .10) 0%, transparent 62%);
}

/* The lobby, arrived at by default rather than chosen: warm paper, brass
   signage, the same four roles re-tuned to hold contrast on a light ground. A
   second design, not a darkened fallback.

   "Match my system" is the absence of a choice, so this is scoped to
   :not([data-palette]) — an explicit room always beats the operating system,
   which is the entire point of having picked one. The same values are named
   `lobby` at the foot of this file, for choosing on purpose. */
@media (prefers-color-scheme: light) {
  :root:not([data-palette]) {
    color-scheme: light;
    --paper: #f7f0e1; --paper-deep: #efe5d1; --velvet: #f0e2d6;
    --card: #fffbf2; --ink: #1c1611; --ink-soft: #5a4e3f;
    --ink-faint: #6b5d48; --rule: #e3d6bd; --rule-soft: #ede3d0;
    --accent: #864f08; --accent-soft: #a97c2a; --screen: #0d6b66;
    --flag: #ab2f2a; --on-accent: #fffbf2; --grain-opacity: .14;
    --beam: radial-gradient(120% 55% at 50% -8%,
            rgba(175, 120, 30, .12) 0%, transparent 62%);
  }
}

/* VELVET — the warm dark above, addressable by name.
   The :root block already holds these values, but only as the default you get
   when you have not chosen and your system is dark. Somebody on a light
   desktop who wants the picture palace could not ask for it. A design that
   exists but cannot be requested is not on the menu, so it is here too.

   The pair of data-theme blocks this replaces set the same colours through a
   light/dark flag that nothing sets any more. One axis, not two: see THE ROOMS
   at the foot of this file. */
:root[data-palette="velvet"] {
  color-scheme: dark;
  --paper: #16110e; --paper-deep: #0e0a08; --velvet: #1f1310;
  --card: #221a15; --ink: #f4ebdd; --ink-soft: #b3a692;
  --ink-faint: #8e8271; --rule: #372c24; --rule-soft: #2a201a;
  --accent: #e8a33d; --accent-soft: #b47f2c; --screen: #5fc9c2;
  --flag: #e2645c; --on-accent: #1a1109; --grain-opacity: .26;
  --beam: radial-gradient(120% 55% at 50% -8%,
          rgba(232, 163, 61, .10) 0%, transparent 62%);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  background-image: var(--beam);
  background-attachment: fixed;
  background-repeat: no-repeat;
  color: var(--ink);
  font: 17px/1.66 var(--serif);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

main { max-width: var(--page); margin: 0 auto; padding: 0 1.5rem 6rem; }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--accent); color: var(--on-accent); padding: .7rem 1.1rem;
  border-radius: 0 0 var(--radius) 0; z-index: 10;
}
.skip:focus { left: 0; }

/* --- masthead ------------------------------------------------------------ */

/* The band runs the full width of the window; its *contents* do not. They sit
   in the same column as the page, so the wordmark starts where the headings
   start and the nav ends where the text ends. Before this the band was
   full-bleed inside and out — wordmark hard left, nav hard right, a 46rem
   column of content stranded in the middle with nothing to line up against.
   That is what "the content doesn't fill the container" was describing: not a
   column that is too narrow, but a header that ignored it. */
.masthead {
  background: var(--velvet);   /* if color-mix is unavailable, the old band */
  background: color-mix(in srgb, var(--velvet), var(--ink) var(--band-lift));
  max-width: none; margin: 0 auto;
}
.masthead .inner {
  max-width: var(--page); margin: 0 auto;
  /* Symmetric, and it was not: 1.9rem above against 1.4rem below put every
     item in the band 4px lower than its centre — measured, not guessed, on the
     rendered page. `align-items: center` was doing its job the whole time,
     centring the wordmark against the nav; both of them were sitting in a box
     that was not centred itself. 1.65rem is the average of the two, so the
     band is exactly the height it was and only its contents moved. */
  padding: 1.65rem 1.5rem;
  /* center, not baseline. Baseline is right when everything on the row is
     text; the nav holds a button and a lens, and aligning a padded box by the
     baseline of the text inside it puts the box wherever its padding says. */
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
}

.wordmark {
  font-family: var(--display);
  font-size: 1.22rem; font-weight: 600; letter-spacing: -.01em;
  color: var(--ink); text-decoration: none;
}
.wordmark:hover { color: var(--accent); }

/* align-items: center, and its absence was the bug.
   Without it a flex row defaults to `stretch`, so the text links grew to the
   height of the padded button and their text sat at the TOP of the stretched
   box while the button's label sat in the middle of its own. The button read as
   lower than everything beside it. Setting align-self on the button did nothing
   about it, because the button is the tallest item and was already the height
   it wanted -- the links were the ones being stretched. */
.masthead nav {
  margin-left: auto; display: flex; gap: 1.15rem; flex-wrap: wrap;
  align-items: center;
}
/* One step up in ink, because the band came up to meet it. On the old
   near-invisible masthead --ink-faint held 4.8:1; on the band at the current
   5% lift it falls to 4.30:1 in the warm dark and 4.52:1 in nitrate, and
   these are .875rem links — under AA, or close enough to it not to spend.
   --ink-soft puts every palette between 5.8 and 7.7:1 instead, so the band
   got clearer and so did the nav. */
/* padding-top balances the underline. The hover rule needs 2px of padding and
   a 1px border below the text; with `align-items: center` the *box* is what
   gets centred, so those 3px pushed every nav link 2.1px above the wordmark and
   the button — measured on the rendered page, which is the only way a two-pixel
   error is ever going to be found. Matching padding above makes the box
   symmetrical about its own text, and the row lines up. */
.masthead nav a {
  color: var(--ink-soft); text-decoration: none; font-size: .875rem;
  padding-top: 3px; padding-bottom: 2px; border-bottom: 1px solid transparent;
}
.masthead nav a:hover { color: var(--accent); border-bottom-color: var(--accent); }
.masthead nav a[aria-current] { color: var(--ink); border-bottom-color: var(--rule); }

/* --- type ---------------------------------------------------------------- */

h1, h3 { font-family: var(--display); font-weight: 600; letter-spacing: -.012em; }
h1 { font-size: 2rem; line-height: 1.2; margin: .75rem 0 .6rem; }
h2 {
  font-size: 1.02rem; margin: 3rem 0 .8rem; letter-spacing: .02em;
  text-transform: uppercase; font-family: var(--serif); font-weight: 600;
  color: var(--ink-faint);
}
h3 { font-size: 1.05rem; margin: 1.6rem 0 .4rem; }

.lede {
  font-family: var(--serif); font-size: 1.2rem; line-height: 1.55;
  color: var(--ink-soft); max-width: var(--prose); margin: 0 0 1.2rem;
}
.quiet { color: var(--ink-faint); font-size: .875rem; }

.prose {
  font-family: var(--serif); font-size: 1.12rem; line-height: 1.72;
  max-width: var(--prose); white-space: pre-wrap; color: var(--ink);
}

a { color: var(--accent); text-underline-offset: 2px; }

/* --- landing ------------------------------------------------------------- */
/* The public face. Restrained on purpose: this is an archive, and a page that
   shouts undermines the thing it is selling. */

.hero { padding: 4.5rem 0 3rem; max-width: none; }
.hero .kicker {
  font-size: .78rem; letter-spacing: .13em; text-transform: uppercase;
  color: var(--accent); margin: 0 0 1.4rem; font-weight: 600;
}
.hero h1 {
  font-family: var(--display);
  font-size: clamp(2.2rem, 6.4vw, 3.2rem); line-height: 1.1;
  letter-spacing: -.022em; margin: 0 0 1.3rem;
}
.hero p {
  font-family: var(--serif); font-size: 1.22rem; line-height: 1.55;
  color: var(--ink-soft); margin: 0 0 1rem;
}

.rule { border: 0; border-top: 1px solid var(--rule); margin: 4rem 0; }

.pitch { max-width: none; margin: 0 0 3rem; }
.pitch h3 { font-size: 1.18rem; margin: 0 0 .35rem; }
.pitch p { color: var(--ink-soft); margin: 0; }

.contrast {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--rule); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden; margin: 2.5rem 0;
}
.contrast > div { background: var(--card); padding: 1.4rem 1.5rem; }
.contrast .label {
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 .6rem;
}
.contrast .said {
  font-family: var(--serif); font-size: 1.16rem; line-height: 1.4;
  margin: 0; color: var(--ink);
}
.contrast .ours .said { color: var(--accent); }
@media (max-width: 34rem) { .contrast { grid-template-columns: 1fr; } }

/* --- the one question ---------------------------------------------------- */

.begin { padding: 4.5rem 0 3rem; max-width: var(--prose); }
.begin h1 { font-size: clamp(1.8rem, 5vw, 2.35rem); line-height: 1.24; }
.begin p { color: var(--ink-soft); }

/* --- timeline ------------------------------------------------------------ */
/* The signature view. A spine with entries hanging off it, so a life reads as
   continuous rather than as a list of rows. Structure through spacing and rule
   before explanatory text (UX.md 6). */

.timeline { position: relative; margin-top: .5rem; }
.timeline::before {
  content: ""; position: absolute; left: 8.25rem; top: .25rem; bottom: .25rem;
  width: 1px; margin-left: 0; background: var(--rule);
}

.entry {
  display: grid; grid-template-columns: 7.5rem 1fr; gap: 2.25rem;
  padding: 1.5rem 0; position: relative;
}
.entry::before {
  content: ""; position: absolute; left: 8.25rem; top: 2rem; z-index: 1;
  width: 9px; height: 9px; margin-left: -4px; border-radius: 50%;
  background: var(--paper); border: 1.5px solid var(--accent);
}
.entry.undated::before { border-style: dashed; border-color: var(--ink-faint); }

.entry .when {
  color: var(--ink-faint); font-size: .82rem; padding-top: .28rem;
  text-align: right; font-variant-numeric: tabular-nums;
}
.entry .when .chapter { display: block; margin-top: .15rem; opacity: .8; }

/* The headline is a remembered experience, not a film title, and it is sized
   as the thing the row is about. It went up from 1.16 to 1.28 and the detail
   line under it went down from .9 to .85: the gap between the two is the
   hierarchy, and closing it is what made the page read as a movie log with
   annotations. */
.entry .what a.film {
  font-family: var(--serif); font-size: 1.28rem; font-weight: 600;
  line-height: 1.3; color: var(--ink); text-decoration: none;
}
.entry .what a.film:hover { color: var(--accent); }
.entry .year { color: var(--ink-faint); font-size: .9rem; font-weight: 400; }
.entry .detail {
  color: var(--ink-faint); font-size: .85rem; margin-top: .25rem;
}
/* The memory is the point of the entry, so it is set as prose in the archive's
   own ink rather than as a greyed-out preview of itself. It was --ink-soft,
   which put the thing somebody wrote at the same weight as the medium it was
   watched on. */
.entry .excerpt {
  font-family: var(--serif); color: var(--ink);
  margin-top: .5rem; font-size: 1.02rem; line-height: 1.6;
}

@media (max-width: 40rem) {
  .timeline::before { left: 3px; }
  .entry { grid-template-columns: 1fr; gap: .3rem; padding-left: 1.5rem; }
  .entry::before { left: 3px; top: 1.85rem; }
  .entry .when { text-align: left; padding-top: 0; }
}

/* --- cards, panels, notices ---------------------------------------------- */

.card {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.2rem 1.4rem; margin: 1.1rem 0;
}

.flash {
  max-width: var(--page); margin: 0 auto 1.25rem; padding: .8rem 1.5rem;
  background: var(--paper-deep); border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule); color: var(--ink-soft);
  font-size: .92rem;
}

/* The thesis, directly under the Movie Life heading. Serif and in the archive's
   own ink because it is the product speaking, not a caption: seven words that
   say what all of this is for before the first entry is read. */
.thesis {
  font-family: var(--serif); font-size: 1.18rem; line-height: 1.5;
  color: var(--ink-soft); margin: 0 0 1.1rem; max-width: var(--prose);
}

/* The memory hook on a list row: the films that make a person a relationship
   or a building a place. Serif, because it is content rather than metadata —
   the line above it is the counting, this is the answer to "why is this here". */
.index .hook {
  font-family: var(--serif); color: var(--ink-soft); font-size: .95rem;
  margin-top: .15rem;
}

.stat-line {
  color: var(--ink-faint); font-size: .9rem; margin: 0 0 1.75rem;
  font-variant-numeric: tabular-nums;
}

/* --- provenance ---------------------------------------------------------- */
/* Not an audit log. An archive that cannot say why it believes something is
   asking to be trusted rather than earning it. */

.source-list { list-style: none; padding: 0; margin: 0; }
.source-list li {
  padding: .8rem 0; border-top: 1px solid var(--rule-soft); font-size: .92rem;
  display: flex; gap: .8rem; align-items: baseline; flex-wrap: wrap;
}
.source-list li:first-child { border-top: none; }
.source-list .value { font-weight: 600; font-family: var(--serif); font-size: 1.02rem; }
.source-list .from { color: var(--ink-soft); }
.source-list .superseded .value { text-decoration: line-through; opacity: .6; }

/* Set aside is quieted, never struck through. A withdrawn account was not
   wrong and was not a mistake somebody made — it is usually a document
   answering a different question than the one asked of it. Struck-through
   would say "this was an error", which is precisely the tone D19.4 spends its
   length refusing for superseded prose, and the reason applies here too. */
.source-list .set-aside .value { opacity: .55; }
.source-list .set-aside .from { opacity: .7; }

/* The two acts sit on their own line so the entry above still reads as a
   sentence. flex-basis:100% breaks the row inside the parent's wrap. */
.settle {
  flex-basis: 100%; display: flex; gap: .5rem; flex-wrap: wrap;
  align-items: center; margin-top: .15rem;
}
.settle form { display: flex; gap: .4rem; align-items: center; margin: 0; }
.settle input[type="text"] {
  font-size: .82rem; padding: .25rem .5rem; min-width: 20rem; max-width: 100%;
}
.settle button { font-size: .78rem; padding: .3rem .7rem; }
@media (max-width: 34rem) {
  .settle, .settle form { flex-direction: column; align-items: stretch; }
  .settle input[type="text"] { min-width: 0; }
}

.tag {
  font-size: .68rem; letter-spacing: .06em; text-transform: uppercase;
  padding: .12rem .45rem; border-radius: 3px; border: 1px solid var(--rule);
  color: var(--ink-faint); white-space: nowrap; font-weight: 600;
}
.tag.disputed { color: var(--flag); border-color: var(--flag); }
.entry:has(.tag.disputed)::before { border-color: var(--flag); }

.disagreement {
  border-left: 2px solid var(--flag); padding: .35rem 0 .35rem 1rem;
  margin: 1.4rem 0; color: var(--ink-soft); font-size: .95rem;
  max-width: var(--prose);
}

/* --- forms --------------------------------------------------------------- */

.field { margin: 1.6rem 0; max-width: var(--measure); }

/* A field you write prose into is prose, not a control. The story box is the
   most important surface in the archive and it was being cropped to the width
   of a date input — you wrote into a column narrower than the one you would
   later read the memory in. */
.field:has(textarea) { max-width: var(--prose); }

.field label {
  display: block; font-weight: 600; font-size: .95rem; margin-bottom: .1rem;
}
.field .hint {
  display: block; color: var(--ink-faint); font-size: .84rem;
  margin-bottom: .45rem; line-height: 1.5;
}

input[type=text], input[type=number], input[type=file], select, textarea {
  width: 100%; padding: .7rem .8rem; font: inherit; color: var(--ink);
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius);
}
input[type=file] { border-style: dashed; color: var(--ink-soft); }
textarea {
  min-height: 10rem; resize: vertical;
  font-family: var(--serif); font-size: 1.08rem; line-height: 1.7;
}
input:focus-visible, select:focus-visible, textarea:focus-visible, a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
::placeholder { color: var(--ink-faint); opacity: .8; }

button, .button {
  font: inherit; font-family: var(--sans); font-weight: 600; font-size: .95rem;
  padding: .72rem 1.5rem; border-radius: var(--radius);
  border: 1px solid transparent; background: var(--accent); color: var(--on-accent);
  cursor: pointer; text-decoration: none; display: inline-block;
  transition: filter .12s ease;
}
button:hover, .button:hover { filter: brightness(1.09); }
.button.secondary {
  background: transparent; color: var(--ink-soft); border-color: var(--rule);
}
.button.secondary:hover { color: var(--accent); border-color: var(--accent); filter: none; }
.button.large { font-size: 1.02rem; padding: .85rem 1.9rem; }

.hero .actions { justify-content: center; }
.actions {
  margin-top: 2.2rem; display: flex; gap: .8rem; align-items: center;
  flex-wrap: wrap;
}

/* --- lists --------------------------------------------------------------- */

.index { list-style: none; padding: 0; margin: 0; }
.index li { padding: .95rem 0; border-top: 1px solid var(--rule-soft); }
.index li:first-child { border-top: none; }
.index a {
  font-family: var(--serif); font-size: 1.1rem; font-weight: 600;
  color: var(--ink); text-decoration: none;
}
.index a:hover { color: var(--accent); }
.index .meta { color: var(--ink-faint); font-size: .86rem; margin-top: .1rem; }

.empty {
  color: var(--ink-faint); font-family: var(--serif); font-size: 1.06rem;
  padding: 1.5rem 0; max-width: var(--prose);
}

/* --- evidence ------------------------------------------------------------ */

.artefact {
  max-width: 100%; height: auto; border-radius: var(--radius);
  border: 1px solid var(--rule);
}

.evidence-strip { display: flex; gap: .7rem; flex-wrap: wrap; margin: .5rem 0 0; }
.evidence-strip a {
  display: block; width: 6rem; height: 6rem; overflow: hidden;
  border-radius: var(--radius); border: 1px solid var(--rule);
  background: var(--card);
}
.evidence-strip a:hover { border-color: var(--screen); }
.evidence-strip img { width: 100%; height: 100%; object-fit: cover; display: block; }
.evidence-strip .file {
  display: flex; align-items: center; justify-content: center; height: 100%;
  font-size: .72rem; color: var(--ink-faint); text-align: center; padding: .4rem;
}

/* Evidence that lives somewhere else. The player keeps a 16:9 box whatever the
   width, so the page does not reflow as each iframe loads — and so the caption
   below it stays where the eye already put it. */
.elsewhere { margin: 1rem 0 0; }

/* `.player` and not `.elsewhere .player`: the artefact's own page shows the
   same embed outside a <figure>, and under the old selector it got none of
   this — a 300x150 iframe in the corner, which is the browser's default and
   nobody's decision. */
.player {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--rule); background: #000;
}
.player iframe {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
  z-index: 1;
}

/* The card behind the player (templates/_player.html). Underneath the iframe,
   so a player that loads hides it completely and a player that never loads
   leaves words instead of a black rectangle.

   It fades in after a delay rather than appearing at once: in the gap before
   YouTube paints, an instant card would flash "they aren't showing it" at
   somebody whose connection is merely slow. The delay costs a reader with a
   genuinely dead embed two seconds and costs everybody else nothing. */
.player-out {
  position: absolute; inset: 0; z-index: 0;
  display: flex; flex-direction: column; justify-content: center;
  gap: .55rem; padding: 1.1rem 1.4rem; text-align: center;
  background: #101010; color: #d9d3c7;
  font-size: .9rem; line-height: 1.5;
  opacity: 0; animation: player-out .45s ease 2.2s forwards;
}
.player-out p { margin: 0; }
.player-out strong { color: #f2ede2; }
.player-out a { color: #fff; }
@keyframes player-out { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .player-out { animation-duration: .01s; }
}
.elsewhere figcaption {
  margin-top: .5rem; font-size: .88rem; color: var(--ink-faint);
  display: flex; gap: .5rem; flex-wrap: wrap; align-items: baseline;
}
.elsewhere figcaption .what { color: var(--ink); }

code {
  font-size: .86em; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--paper-deep); padding: .12rem .35rem; border-radius: 3px;
}

/* --- footer -------------------------------------------------------------- */

footer {
  border-top: 1px solid var(--rule); margin-top: 5rem;
  background: var(--paper-deep);
}
footer .inner {
  max-width: var(--page); margin: 0 auto; padding: 2rem 1.5rem 3rem;
  color: var(--ink-faint); font-size: .85rem;
  display: flex; gap: 1.2rem; flex-wrap: wrap; align-items: baseline;
}
footer a { color: var(--ink-faint); text-decoration: none; }
footer a:hover { color: var(--accent); }
footer .note { margin-left: auto; font-style: italic; }
@media (max-width: 34rem) { footer .note { margin-left: 0; } }

/* --- capture ------------------------------------------------------------- */
/* "I just remembered something." One field, no decisions (D23). The memory has
   a short half life; everything between having it and keeping it is a reason it
   never gets written down. */

.capture {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.25rem 1.35rem; margin: 0 0 1rem;
}
.capture label {
  display: block; font-family: var(--serif); font-size: 1.12rem;
  font-weight: 600; margin-bottom: .55rem;
}
.capture textarea { min-height: 5rem; font-size: 1.04rem; }
.capture-actions {
  margin-top: .85rem; display: flex; gap: .7rem; align-items: center;
  flex-wrap: wrap;
}
.capture-actions .button.secondary { border-color: transparent; padding-left: .4rem; }

.masthead nav a.remembered {
  color: var(--accent); font-weight: 600;
}
.masthead nav a.remembered:hover { border-bottom-color: var(--accent); }

/* A note is an entry in its own right, not a lesser one. Marked with a hollow
   square rather than a dot so the timeline reads honestly at a glance. */
.entry.note::before { border-radius: 1px; border-style: solid; }
.entry.note .what a.note-body {
  font-family: var(--serif); font-size: 1.06rem; line-height: 1.6;
  color: var(--ink-soft); text-decoration: none; display: block;
}
.entry.note .what a.note-body:hover { color: var(--accent); }

/* --- the working --------------------------------------------------------- */
/* Showing where 3,000 comes from.
 *
 * This is the landing page practising what the archive preaches: assumptions
 * stated, arithmetic visible, answer given as a range. A page that opened with
 * a confident 3,000 and no method would be doing exactly what D3 forbids. */

.hero .count {
  font-family: var(--serif); font-size: clamp(1.4rem, 4vw, 1.9rem);
  color: var(--accent); font-weight: 600; letter-spacing: -.015em;
  margin: -.4rem 0 0;
}
.hero.after { padding-top: 1rem; }

.working {
  border-left: 2px solid var(--rule); padding: .25rem 0 .25rem 1.5rem;
  margin: 2.5rem 0 3rem; max-width: none;
}
.working-head {
  font-size: .72rem; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-faint); font-family: var(--sans); font-weight: 600;
  margin: 0 0 1rem;
}

.assumptions { list-style: none; padding: 0; margin: 0 0 1.1rem; }
.assumptions li {
  display: flex; gap: .6rem; align-items: baseline; justify-content: space-between;
  padding: .42rem 0; border-bottom: 1px dotted var(--rule);
  color: var(--ink-soft); font-size: .95rem;
}
.assumptions li span { flex: 1 1 auto; }
/* The cue list on /welcome has no right-hand value — it is three ways in, not
   four assumptions with answers — so the row is just its sentence. */
.assumptions.cues li { justify-content: flex-start; }
.assumptions li b {
  font-family: var(--serif); color: var(--ink); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.sum {
  font-family: var(--serif); font-size: 1.22rem; color: var(--ink);
  margin: 0 0 1.2rem; font-variant-numeric: tabular-nums;
}
.sum b { color: var(--accent); }

.working-note {
  color: var(--ink-soft); font-size: .95rem; margin: 0 0 .9rem;
  max-width: var(--prose);
}
.working-note.aside {
  font-family: var(--serif); font-size: 1.04rem; color: var(--ink-faint);
  margin-top: 1.3rem;
}
.working-note.aside em { color: var(--ink-soft); font-style: italic; }

@media (max-width: 30rem) {
  .assumptions li { flex-direction: column; gap: .1rem; }
}

/* --- letterbox ----------------------------------------------------------- */
/* The hero sits inside a frame with the proportions of a widescreen print.
   Two hairlines, nothing more: the shape is the idea, and a picture of a film
   reel would be the cheesy version of the same thought. */

.hero.framed { padding: 3.5rem 0 2rem; margin-top: .5rem; }

/* The Shelf, at the foot of the timeline. A rule and a line of text, because
   it is a standing fact about the archive rather than something outstanding —
   the card it used to be sat above the timeline and read as a task. */
.shelf-foot {
  border-top: 1px solid var(--rule-soft); margin: 2.5rem 0 0;
  padding-top: 1.1rem; color: var(--ink-faint); font-size: .9rem;
  max-width: var(--prose);
}
.shelf-foot strong { color: var(--ink-soft); font-weight: 600; }
.shelf-foot .jog { color: var(--accent); text-decoration: none; white-space: nowrap; }
.shelf-foot .jog:hover { text-decoration: underline; }


/* --- building the shelf --------------------------------------------------- */
/* An import becoming a collection. The bar is the only progress indicator in
   the archive and it is allowed here for the reason D23 forbids it elsewhere:
   this is a task with an end, not a life with a completion percentage. */

.build { margin: 2rem 0 0; max-width: var(--prose); }

.build-bar {
  height: 3px; background: var(--rule-soft); border-radius: 2px;
  overflow: hidden; margin-bottom: .7rem;
}
.build-fill {
  display: block; height: 100%; width: 0; background: var(--accent);
  transition: width .3s ease;
}
@media (prefers-reduced-motion: reduce) { .build-fill { transition: none; } }

.build-count {
  font-variant-numeric: tabular-nums; color: var(--ink-soft);
  font-size: .9rem; margin: 0 0 1.4rem;
}

.build form { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }

/* The titles going past. Eight of them, newest first — enough to see it
   working and not so many that it becomes a wall to read. */
.build-log {
  list-style: none; padding: 0; margin: 1.8rem 0 0;
  border-top: 1px solid var(--rule-soft);
}
.build-log li {
  display: flex; gap: 1rem; align-items: baseline; justify-content: space-between;
  padding: .5rem 0; border-bottom: 1px solid var(--rule-soft);
  font-size: .92rem; color: var(--ink);
}
.build-log li.missed { color: var(--ink-faint); }
.build-what {
  font-size: .72rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-faint); white-space: nowrap;
}

/* The ending. Given room, because it is the moment the shelf becomes yours. */
.built { padding: 3.5rem 0 2rem; max-width: var(--prose); }
.built h1 { font-size: clamp(1.9rem, 5vw, 2.5rem); line-height: 1.2; margin-bottom: .2rem; }
.built .lede { color: var(--accent); font-size: 1.35rem; margin-bottom: 1.6rem; }
.built .actions { margin-top: 2rem; }


/* --- FAQ ----------------------------------------------------------------- */

.faq { max-width: var(--prose); }
.faq dt {
  font-family: var(--serif); font-size: 1.16rem; font-weight: 600;
  margin: 2rem 0 .4rem; color: var(--ink);
}
.faq dt:first-of-type { margin-top: .5rem; }
.faq dd { margin: 0; color: var(--ink-soft); }
.faq dd + dd { margin-top: .6rem; }
.faq .not-yet {
  display: inline-block; font-size: .68rem; letter-spacing: .06em;
  text-transform: uppercase; font-weight: 600; color: var(--screen);
  border: 1px solid var(--screen); border-radius: 3px; padding: .08rem .4rem;
  vertical-align: middle; margin-left: .4rem;
}

/* Contemporaneous writing sits apart from recollection — teal, because it is a
   record from outside the remembering self, the same job the accent does for
   evidence. */
.card.written { border-left: 2px solid var(--screen); }

/* --- filter -------------------------------------------------------------- */

.filter { display: flex; gap: 1.1rem; margin: -.3rem 0 1rem; font-size: .875rem; }
.filter a { color: var(--ink-faint); text-decoration: none; }
.filter a.on { color: var(--ink); font-weight: 600; }
.filter a:hover { color: var(--accent); }

/* An entry you have written something about carries weight. Six hundred
   imported titles must not bury the four things you actually remember. */
.entry.told::before { background: var(--accent); border-color: var(--accent); }
.entry.told .what a.film { color: var(--ink); }

.capture-note {
  margin: .7rem 0 0; font-size: .8rem; color: var(--ink-faint);
}

/* The same box, asking rather than waiting. On a film's own page the archive
   knows what you are looking at, so the label is a question with the film's
   name in it — and the box sits directly under the title, because a film is a
   retrieval cue and the moment is the instant you see it. */
.capture.invite { margin: 2rem 0 0; border-color: var(--accent-soft); }
.capture.invite label {
  font-family: var(--display); font-size: 1.24rem; line-height: 1.3;
  color: var(--ink); margin-bottom: .7rem;
}

/* --- the prompt surface -------------------------------------------------- */
/* One film, one question, nothing else (UX.md 7). No counter, no progress, no
   streak — D23 gives the archive no finish line, and a queue with a number on
   it is a chore. */

.prompt { max-width: var(--prose); padding: 2.5rem 0 2rem; }
.prompt-lead { color: var(--ink-faint); font-size: .9rem; margin: 0 0 1.5rem; }

.prompt-film {
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  padding: 2rem 0 1.6rem; margin-bottom: 2rem; position: relative;
  text-align: center;
}
.prompt-film h1 {
  font-family: var(--display);
  font-size: clamp(2rem, 6.4vw, 2.9rem); margin: .3rem 0 .5rem; line-height: 1.12;
}
.prompt-meta { color: var(--ink-faint); font-size: .875rem; margin: 0; }

/* A countdown leader: two rings and a sweep, drawn rather than illustrated. */
.leader {
  display: block; width: 2.6rem; height: 2.6rem; margin: 0 auto .6rem;
  border-radius: 50%; border: 1px solid var(--rule); position: relative;
}
.leader::before, .leader::after {
  content: ""; position: absolute; background: var(--accent-soft); opacity: .75;
}
.leader::before { left: 50%; top: 6%; bottom: 6%; width: 1px; margin-left: -.5px; }
.leader::after  { top: 50%; left: 6%; right: 6%; height: 1px; margin-top: -.5px; }

.nudge { border-left: 2px solid var(--accent); font-size: .93rem; }
.nudge p { color: var(--ink-soft); }

/* --- the shelf ----------------------------------------------------------- */

.shelf li.told a { color: var(--ink); }
.shelf .told-mark { color: var(--accent); font-weight: 600; }
.shelf .jog { color: var(--ink-faint); text-decoration: none; }
.shelf .jog:hover { color: var(--accent); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

.filter.decades { flex-wrap: wrap; gap: .85rem; margin-bottom: 1.6rem; }
.filter.decades sup { font-size: .62rem; opacity: .65; margin-left: .1rem; }

/* ==========================================================================
   Ornament — three motifs, used systematically.
   UX.md 13: every element earns its place. The failure mode here is a page
   that looks like a themed restaurant, so these are the only three, they are
   all drawn rather than illustrated, and each has one job.
   ========================================================================== */

/* 1. GRAIN — the thing that makes a dark interface feel filmic rather than
   flat, and the single cheapest way to stop looking like every other dark app.
   An inline SVG turbulence, so it costs no request and works offline. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: var(--grain-opacity, .3);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}
/* The grain sits at z-index 0 and everything else must clear it. But giving
   both the masthead and main the same z-index made them SIBLING stacking
   contexts, which trapped the dropdown inside the masthead's context — its
   z-index: 20 was competing with its own siblings, never with main, so no value
   could have lifted it. The menu going under the page was never a z-index that
   was too low. */
.masthead { position: relative; z-index: 5; }
main, footer, .flash { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) { body::before { opacity: .12; } }

/* 2. MARQUEE BULBS — a row of lights under every section heading, the way a
   cinema front is lit. Gives h2 real character instead of a plain grey label,
   and marks structure without adding a word. */
h2 {
  display: flex; align-items: center; gap: .85rem;
}
h2::after {
  content: ""; flex: 1 1 auto; height: 5px; border-radius: 3px;
  background-image: radial-gradient(circle at center,
      var(--accent-soft) 0 1.6px, transparent 1.9px);
  background-size: 11px 5px; background-repeat: repeat-x;
  opacity: .5;
}
h2.working-head::after, .faq h2::after { opacity: .35; }

/* 3. SPROCKETS — the film-strip edge, already the timeline's spine, promoted
   to a divider. The one motif that is load bearing rather than decorative, so
   it is the one allowed to appear twice. */
/* Dots, and nothing else. The film-strip rule and the framing ticks were two
   more metaphors doing the job the marquee bulbs already do, and three
   ornaments competing is decoration rather than a system (UX.md 13). */
hr.rule {
  border: 0; height: 5px; margin: 4rem 0;
  background-image: radial-gradient(circle at center,
      var(--accent-soft) 0 1.6px, transparent 1.9px);
  background-size: 11px 5px; background-repeat: repeat-x;
  opacity: .45;
}

/* --- theme toggle -------------------------------------------------------- */

/* --- the Fresnel --------------------------------------------------------- */
/* The light switch is a Fresnel lens: the stepped concentric rings of the
   instrument that lights a film set, and of a lighthouse. Drawn entirely in
   gradients — concentric rings, four radial spokes, and a hot centre — because
   an icon file would be a picture of the idea rather than the idea.
   It is lit in the dark, and dark in the light: the lamp is only visible when
   the room isn't. */

.theme-toggle {
  --lens: 1.55rem;
  width: var(--lens); height: var(--lens); padding: 0; border: 0;
  border-radius: 50%; cursor: pointer; background: none; position: relative;
  flex: 0 0 auto; align-self: center;
  transition: transform .25s ease, filter .25s ease;
}
.theme-toggle::before {
  /* The stepped rings. */
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%,
      var(--accent) 0 11%,
      transparent 11% 20%,
      var(--accent-soft) 20% 27%,
      transparent 27% 40%,
      var(--accent-soft) 40% 46%,
      transparent 46% 60%,
      var(--accent-soft) 60% 65%,
      transparent 65% 80%,
      var(--accent-soft) 80% 85%,
      transparent 85%);
  opacity: .95;
}
.theme-toggle::after {
  /* Four spokes, the way a Fresnel's segments read edge-on. */
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background:
    linear-gradient(0deg,   transparent 46%, var(--paper) 46% 54%, transparent 54%),
    linear-gradient(90deg,  transparent 46%, var(--paper) 46% 54%, transparent 54%);
  opacity: .55;
}
.theme-toggle:hover { transform: scale(1.08); }
.theme-toggle:hover::before { filter: brightness(1.25); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Lit in the dark. Keyed off the room rather than off data-theme, which the
   comparison scaffolding used to set and nothing sets now. */
.theme-toggle { filter: drop-shadow(0 0 6px rgba(232, 163, 61, .55)); }

/* Dark in the light — the lamp is off because the room is on. Both ways of
   arriving in the lobby: chosen, or inherited from the system. */
:root[data-palette="lobby"] .theme-toggle { filter: none; opacity: .8; }
@media (prefers-color-scheme: light) {
  :root:not([data-palette]) .theme-toggle { filter: none; opacity: .8; }
}

/* --- visibility ---------------------------------------------------------- */

.visibility { margin: 2rem 0 0; max-width: var(--measure); }
.visibility label {
  display: block; font-size: .78rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-faint); margin-bottom: .35rem;
  font-weight: 600;
}
.visibility select { max-width: 22rem; }

.entry.withheld .film { color: var(--ink-soft); }
.entry.withheld::before { border-style: dashed; border-color: var(--ink-faint); }
.withheld-note { font-style: italic; color: var(--ink-faint); }

.disclosure { border-collapse: collapse; width: 100%; max-width: var(--measure); font-size: .92rem; }
.disclosure th, .disclosure td {
  text-align: left; padding: .55rem .6rem; border-bottom: 1px solid var(--rule-soft);
}
.disclosure th {
  font-size: .72rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-faint);
}
.disclosure td:not(:first-child) { text-align: right; font-variant-numeric: tabular-nums; }
.disclosure td.exposed { color: var(--flag); font-weight: 600; }

/* --- the More menu ------------------------------------------------------- */

.masthead nav .more { position: relative; }
.masthead nav .more > summary {
  list-style: none; cursor: pointer; color: var(--ink-faint);
  font-size: .875rem; padding-bottom: 2px;
  border-bottom: 1px solid transparent;
}
.masthead nav .more > summary::-webkit-details-marker { display: none; }
.masthead nav .more > summary::after { content: " ▾"; font-size: .7em; opacity: .7; }
.masthead nav .more[open] > summary,
.masthead nav .more > summary:hover { color: var(--accent); }

.more-menu {
  position: absolute; right: 0; top: 1.9rem; z-index: 20;
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: .5rem 0; min-width: 12rem;
  box-shadow: 0 12px 28px rgba(0,0,0,.32);
  display: flex; flex-direction: column;
}
.more-menu a {
  padding: .5rem 1rem; font-size: .9rem; color: var(--ink-soft);
  border-bottom: 0 !important;
}
.more-menu a:hover { background: var(--paper-deep); color: var(--accent); }

@media (max-width: 44rem) {
  .masthead nav { gap: .9rem; }
  .masthead nav .remembered { order: -1; }
}

/* --- the two doors ------------------------------------------------------- */

.two-doors {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;
  margin: 2rem 0 1.4rem; max-width: var(--prose);
}
@media (max-width: 38rem) { .two-doors { grid-template-columns: 1fr; } }

.door {
  display: flex; flex-direction: column; gap: .45rem;
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.5rem 1.4rem;
  text-decoration: none; color: var(--ink-soft);
  transition: border-color .15s ease, transform .15s ease;
}
.door:hover { border-color: var(--accent); transform: translateY(-2px); }
.door strong {
  font-family: var(--display); font-size: 1.24rem; font-weight: 600;
  color: var(--ink);
}
.door span:last-child { font-size: .95rem; line-height: 1.55; }
.door-mark {
  width: 2.1rem; height: 2.1rem; border-radius: 50%;
  border: 1px solid var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-size: 1.05rem; margin-bottom: .3rem;
}
.reassure { max-width: var(--prose); }

/* --- posters ------------------------------------------------------------- */
/* 2:3, the shape of every film poster since the sixties. The drawn card is the
   common case rather than the fallback: most of a shelf has no artwork, and an
   interface that only looks right when every row has an image looks broken
   forever. */

.poster {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; overflow: hidden; flex: 0 0 auto;
  border-radius: 3px; border: 1px solid var(--rule);
  background: var(--paper-deep); text-align: center;
}
.poster img { width: 100%; height: 100%; object-fit: cover; display: block; }
.poster-link { display: block; text-decoration: none; flex: 0 0 auto; }
.poster-link:hover .poster { border-color: var(--accent); }

.poster-small { width: 2.6rem; height: 3.9rem; }
.poster-large { width: 7.5rem; height: 11.25rem; }

.poster-drawn { background: var(--ground, var(--paper-deep)); }
.poster-drawn .poster-title {
  font-family: var(--display); font-weight: 600; color: var(--mark, var(--accent));
  line-height: 1.15; padding: .25rem;
}
.poster-large.poster-drawn .poster-title { font-size: 1rem; padding: .7rem; }
.poster-drawn .poster-year {
  font-size: .5rem; color: var(--mark, var(--accent)); opacity: .65; margin-top: .2rem;
}
.poster-large.poster-drawn .poster-year { font-size: .75rem; }

/* The monogram. Sized to be read at a glance rather than to fill the card —
   the title is already beside it, so this only has to make a film recognisable
   on return, which the stable ground colour does most of the work for. The
   .42rem title that used to sit here rendered at 7px. */
.poster-mono {
  font-family: var(--display); font-weight: 700;
  color: var(--mark, var(--accent));
  font-size: 1.15rem; line-height: 1; letter-spacing: .01em;
}
.poster-note {
  font-family: var(--display); color: var(--ink-faint); font-size: 1.1rem;
  line-height: 1;
}

.entry .what.with-poster { display: flex; gap: .9rem; align-items: flex-start; }
.what-text { min-width: 0; }

/* The whole row is one target. The title's link is stretched over the li, so
   the poster, the year and the empty space to the right all go to the film —
   larger target, one link instead of two, and the accessible name is still the
   title (UX.md 8). */
.shelf li { display: flex; gap: .9rem; align-items: flex-start; position: relative; }
.shelf-text { min-width: 0; flex: 1 1 auto; }
.shelf-link::after { content: ""; position: absolute; inset: 0; }
.shelf li:hover .poster { border-color: var(--accent); }
.shelf li:hover .shelf-link { color: var(--accent); }

/* Held back until the row is hovered or something in it takes focus. Kept in
   the layout rather than display:none so nothing shifts when it appears, and
   it stays reachable by keyboard — revealing on :focus-within is what makes
   that honest rather than a trap. */
.jog-wrap { opacity: 0; transition: opacity .12s ease; }
.shelf li:hover .jog-wrap,
.shelf li:focus-within .jog-wrap { opacity: 1; }
@media (hover: none) { .jog-wrap { opacity: 1; } }

/* Above the stretched link, or it would be unclickable. */
.shelf .jog { position: relative; }

.film-head { display: flex; gap: 1.4rem; align-items: flex-start; margin-bottom: 1rem; }
.film-head h1 { margin-top: 0; }
.prompt-film .poster { margin: 0 auto .9rem; }

@media (max-width: 34rem) {
  .film-head { gap: 1rem; }
  .poster-large { width: 5.5rem; height: 8.25rem; }
}

.capture-film { margin: .9rem 0 0; }
.capture-film label { font-size: .85rem; font-weight: 600; }
.optional {
  font-weight: 400; color: var(--ink-faint); font-size: .8rem;
  text-transform: none; letter-spacing: 0;
}
.more-menu hr { border: 0; border-top: 1px solid var(--rule); margin: .45rem 0; }

/* --- inline editors ------------------------------------------------------ */
/* Folded away, because a page about somebody should be about them rather than
   about their fields (UX.md 5, progressive complexity). */

.editor { margin: 2rem 0; max-width: var(--measure); }
.editor > summary {
  cursor: pointer; color: var(--ink-faint); font-size: .875rem;
  list-style: none; display: inline-block;
  border-bottom: 1px dotted var(--rule);
}
.editor > summary::-webkit-details-marker { display: none; }
.editor > summary::before { content: "✎ "; color: var(--accent); }
.editor > summary:hover { color: var(--accent); }
.editor[open] > summary { margin-bottom: .8rem; }

/* --- journeys ------------------------------------------------------------ */

.journeys { list-style: none; padding: 0; margin: 2rem 0; }
.journeys li { margin-bottom: .8rem; }
.journeys a {
  display: flex; flex-direction: column; gap: .3rem;
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.15rem 1.3rem;
  text-decoration: none; transition: border-color .15s ease;
}
.journeys a:hover { border-color: var(--accent); }
.journeys strong {
  font-family: var(--display); font-size: 1.2rem; font-weight: 600; color: var(--ink);
}
.journeys .blurb { color: var(--ink-soft); font-size: .96rem; }
.journeys .meta { color: var(--ink-faint); font-size: .82rem; }

.prompt-film.question { text-align: left; }
.prompt-film.question h1 { font-size: clamp(1.5rem, 4.2vw, 2.1rem); }
.prompt-film.question .leader { margin: 0 0 .9rem; }

.pause { margin-top: 1.6rem; }
.linky {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--ink-faint); font: inherit; font-size: .875rem;
  border-bottom: 1px dotted var(--rule);
}
.linky:hover { color: var(--accent); }
.card.said-earlier { border-left: 2px solid var(--rule); }

/* The capture action reads as a button, not as a sixth destination. */
.masthead nav a.remembered.button {
  padding: .38rem .85rem; font-size: .82rem; border-radius: 999px;
  background: transparent; color: var(--accent);
  border: 1px solid var(--accent-soft);
}
.masthead nav a.remembered.button:hover {
  background: var(--accent); color: var(--on-accent); filter: none;
}

/* --- onboarding ---------------------------------------------------------- */

.onboarding .prompt-film.question h1 { font-size: clamp(1.6rem, 4.6vw, 2.3rem); }
.first-archive { padding: 2rem 0 1rem; }
.first-archive h1 { font-size: clamp(1.9rem, 5vw, 2.6rem); margin-bottom: .5rem; }
.first-archive .timeline { margin: 2rem 0 1rem; }
.first-archive .timeline::before { opacity: .6; }

.three-doors {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;
  margin: 1.6rem 0 2rem;
}
@media (max-width: 44rem) { .three-doors { grid-template-columns: 1fr; } }
.three-doors .door-mark {
  border: 0; font-size: 1.4rem; width: auto; height: auto; margin-bottom: .2rem;
}

/* --- open questions ------------------------------------------------------ */
/* D28: content, not a gap. Marked with the same cool accent used for things
   that came from outside the remembering self — because an unanswered question
   is a fact about the memory rather than a hole in it. */

.holding {
  display: flex; gap: .55rem; align-items: flex-start; margin: 1rem 0 0;
  font-size: .88rem; color: var(--ink-faint); cursor: pointer; max-width: var(--measure);
}
.holding input { width: auto; margin-top: .2rem; flex: 0 0 auto; }
.holding:hover { color: var(--ink-soft); }
.holding-form { margin: 2rem 0 0; }

.entry.wondering::before { border-style: dashed; border-color: var(--screen); }
.open-question {
  border-left: 2px solid var(--screen); padding-left: 1rem;
  color: var(--ink-soft); font-family: var(--serif); font-style: italic;
}

.card.noticed { border-left: 2px solid var(--accent); }
.noticed-lead {
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 .4rem; font-weight: 600;
}
.noticed-text {
  font-family: var(--serif); font-size: 1.1rem; color: var(--ink); margin: 0;
}

/* --- the estimate -------------------------------------------------------- */

.estimate {
  font-family: var(--display); font-size: clamp(1.3rem, 3.6vw, 1.75rem);
  color: var(--accent); margin: .2rem 0 .6rem; font-weight: 600;
}
.estimate-working { list-style: none; padding: 0; margin: 0 0 .8rem; }
.estimate-working li {
  color: var(--ink-soft); font-size: .93rem; padding: .25rem 0 .25rem 1rem;
  border-left: 1px solid var(--rule);
}
.rate-row { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.rate-row label { margin: 0; }
.rate-row input[type=text] { width: 4rem; }
.rate-row select { width: auto; }

/* ==========================================================================
   THE ROOMS. Four of them, and they stay.

   These began as three candidates to be compared in situ and then narrowed to
   one. Josh's call, 2026-08-07: none of them wins, because the choice is not
   the designer's to make. An archive somebody will still be reading in thirty
   years should let them pick the room they read it in.

   So the Fresnel is not scaffolding and not a light switch. It is the control
   for a real preference, and Settings carries the same choice in a form you
   can read before committing to (UX.md 4 — recognition over memory; a cycle
   button alone makes you click blind to find out what you are getting).

   THE LOBBY IS ONE OF THEM. It used to be reachable only through
   `data-theme="light"`, which base.html was pinning to "dark" for the duration
   of the comparison — so making the palettes permanent without this would have
   left the light design stranded behind a flag nobody could reach. One list,
   one control, four rooms.

   Unset means "match my system": the :root defaults below give the warm dark,
   and the prefers-color-scheme block gives the lobby. That block is scoped to
   :not([data-palette]) so an explicit choice always wins over the OS, which is
   the whole point of having chosen.
   ========================================================================== */

/* 1 · PROJECTION — the dark of the auditorium and the light hitting the
   screen. Almost no colour: warm white on cool black, with one cold blue for
   things from outside you. Puts the memories in the light and everything else
   in the dark, which is the product's actual argument. */
:root[data-palette="projection"] {
  color-scheme: dark;
  --paper: #090b0d; --paper-deep: #050607; --velvet: #0f1215; --card: #14181c;
  --ink: #f5f3ee; --ink-soft: #a9b0b6; --ink-faint: #8c9399;
  --rule: #242a30; --rule-soft: #1a1f24;
  --accent: #e7dfcb; --accent-soft: #b0a894; --screen: #8fb8d4; --flag: #e08b6a;
  --on-accent: #12140f; --grain-opacity: .22;
  --beam: radial-gradient(120% 55% at 50% -8%,
          rgba(231,223,203,.10) 0%, transparent 62%);
}

/* 2 · NITRATE — black, cream, and one saturated red held back for the curtain
   and for disagreement. Monochrome with a single loud voice; the most timeless
   of the three, and the least likely to date. */
:root[data-palette="nitrate"] {
  color-scheme: dark;
  --paper: #0c0b0a; --paper-deep: #070606; --velvet: #1a0f0f; --card: #171514;
  --ink: #f1eade; --ink-soft: #a89f92; --ink-faint: #8b8377;
  --rule: #2a2724; --rule-soft: #1f1d1b;
  --accent: #ded3bb; --accent-soft: #a89e8a; --screen: #9aa8ad; --flag: #d9483f;
  --on-accent: #141210; --grain-opacity: .24;
  --beam: radial-gradient(120% 55% at 50% -8%,
          rgba(217,72,63,.07) 0%, transparent 62%);
}

/* 3 · LATE SHOW — a marquee at night rather than a lobby carpet. Deep blue
   black under neon: amber, cyan, magenta. The furthest from what is there now
   and the most fun; also the most likely to feel loud beside a memory. */
:root[data-palette="lateshow"] {
  color-scheme: dark;
  --paper: #090c13; --paper-deep: #05070c; --velvet: #10162200; --velvet: #101622;
  --card: #131a26; --ink: #ecf2f8; --ink-soft: #9fb0c2; --ink-faint: #8496a8;
  --rule: #202b3a; --rule-soft: #17202b;
  --accent: #ffb443; --accent-soft: #c68a33; --screen: #45d9d9; --flag: #ff5f9e;
  --on-accent: #0d1018; --grain-opacity: .20;
  --beam: radial-gradient(120% 55% at 50% -8%,
          rgba(255,180,67,.10) 0%, transparent 62%);
}

/* 4 · THE LOBBY — the light one. Warm paper, brass signage: a second design
   rather than a darkened fallback, which is why it carries its own accent
   values instead of inverting anything. The same colours the system-light
   block below uses; named here so it can be chosen deliberately and not only
   inherited from an operating system. */
:root[data-palette="lobby"] {
  color-scheme: light;
  --paper: #f7f0e1; --paper-deep: #efe5d1; --velvet: #f0e2d6;
  --card: #fffbf2; --ink: #1c1611; --ink-soft: #5a4e3f;
  --ink-faint: #6b5d48; --rule: #e3d6bd; --rule-soft: #ede3d0;
  --accent: #864f08; --accent-soft: #a97c2a; --screen: #0d6b66;
  --flag: #ab2f2a; --on-accent: #fffbf2; --grain-opacity: .14;
  --beam: radial-gradient(120% 55% at 50% -8%,
          rgba(175, 120, 30, .12) 0%, transparent 62%);
}

/* The name of the room you just moved to.
   It used to sit in the masthead permanently, which was right while comparing
   and is chrome once the choice is real — a label that never changes is not
   telling you anything (UX.md 13). Now it appears on the change and fades,
   which is the part that was ever worth saying (UX.md 2: nothing significant
   happens silently). aria-live in the markup carries the same news to a screen
   reader, which has no fade to watch. */
.palette-name {
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft); margin-left: .5rem; align-self: center;
  opacity: 0; transition: opacity .5s ease .9s;
}
.palette-name.said { opacity: 1; transition: opacity .12s ease; }
@media (prefers-reduced-motion: reduce) {
  .palette-name { transition: none; }
}

/* The chooser in Settings. Each swatch is painted in its own room's colours,
   hardcoded rather than drawn from custom properties — the page is already
   wearing one of these, and a swatch that inherits the active palette shows
   you six copies of the room you are standing in. */
.rooms {
  display: grid; grid-template-columns: 1fr 1fr; gap: .6rem;
  max-width: var(--prose); margin: 1.4rem 0 0;
}
@media (max-width: 34rem) { .rooms { grid-template-columns: 1fr; } }

.room {
  display: flex; gap: .85rem; align-items: flex-start; text-align: left;
  background: var(--card); border: 1px solid var(--rule);
  color: var(--ink-soft); padding: .85rem .9rem; font-weight: 400;
  transition: border-color .15s ease;
}
.room:hover { border-color: var(--accent); filter: none; }
.room[aria-pressed="true"] { border-color: var(--accent); }
.room[aria-pressed="true"] strong::after {
  content: " ·"; color: var(--accent);
}
.room-text { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.room-text strong { color: var(--ink); font-size: .98rem; }
.room-note { font-size: .82rem; line-height: 1.45; color: var(--ink-faint); }

/* Paper, the masthead band above it, and the accent. The three decisions that
   make a room recognisable, in the order you meet them. */
.room-swatch {
  width: 2.6rem; height: 2rem; border-radius: 4px; flex: 0 0 auto;
  border: 1px solid rgba(128, 128, 128, .3); position: relative;
  background: linear-gradient(to bottom,
              var(--sw-band) 0 34%, var(--sw-paper) 34%);
}
.room-swatch::after {
  content: ""; position: absolute; right: .28rem; bottom: .28rem;
  width: .45rem; height: .45rem; border-radius: 50%;
  background: var(--sw-accent);
}

/* The band values are the palettes' own velvet at the 5% --band-lift, so the
   swatch shows the masthead you will actually get. */
.room-velvet     { --sw-paper: #16110e; --sw-band: #2a1e1a; --sw-accent: #e8a33d; }
.room-projection { --sw-paper: #090b0d; --sw-band: #1a1d20; --sw-accent: #e7dfcb; }
.room-nitrate    { --sw-paper: #0c0b0a; --sw-band: #251a19; --sw-accent: #ded3bb; }
.room-lateshow   { --sw-paper: #090c13; --sw-band: #1b212d; --sw-accent: #ffb443; }
.room-lobby      { --sw-paper: #f7f0e1; --sw-band: #e5d8cc; --sw-accent: #864f08; }

/* Both at once, because that is what it means. */
.room-system {
  --sw-accent: #e8a33d;
  background: linear-gradient(135deg, #f7f0e1 0 50%, #16110e 50%);
}

/* Cards you can close. Closing is a view preference, not a decision about the
   archive — "Not this" dismisses a subject forever; this just gets it out of
   the way of the timeline, which is the main event. */
.card[data-dismissible] { position: relative; padding-right: 2.4rem; }
.card-close {
  position: absolute; top: .5rem; right: .6rem;
  background: none; border: 0; cursor: pointer; line-height: 1;
  font-size: 1.25rem; color: var(--ink-faint); padding: .2rem .4rem;
  border-radius: 4px;
}
.card-close:hover { color: var(--accent); background: var(--paper-deep); }

/* Who is signed in, inside the More menu. Small, and not in the masthead:
   somebody's own email address is not chrome they need to look at all day. */
.more-who {
  display: block; padding: .35rem 1rem .2rem; font-size: .78rem;
  color: var(--ink-faint); word-break: break-all;
}
.more-menu form { margin: 0; }
.more-menu .linky {
  display: block; width: 100%; text-align: left; padding: .4rem 1rem;
  background: none; border: 0; color: var(--ink-soft); font-size: .875rem;
  cursor: pointer;
}
.more-menu .linky:hover { background: var(--paper-deep); color: var(--accent); }

/* The "when" beside a memory on a film page. Narrower than the prose box on
   purpose: it takes "1994", not a paragraph, and a full-width input invites
   somebody to write the memory in it a second time. */
.capture-when { margin: .9rem 0 0; max-width: 26rem; }
.capture-when label { font-size: .95rem; }

/* --- sorting out a long note ---------------------------------------------- */
/* Everything off until ticked, and every row carrying the sentence it came
   from. A confidence score is a number nobody can check; the sentence is the
   evidence somebody can actually judge. */

.sortout { list-style: none; padding: 0; margin: 1rem 0 0; max-width: var(--prose); }
.sortout li { border-top: 1px solid var(--rule-soft); }
.sortout li:last-child { border-bottom: 1px solid var(--rule-soft); }
.sortout label {
  display: flex; gap: .9rem; align-items: flex-start; cursor: pointer;
  padding: 1rem .4rem; margin: 0;
}
.sortout label:hover { background: var(--paper-deep); }
.sortout input { margin-top: .35rem; flex: 0 0 auto; width: auto; }
.sortout-body { display: flex; flex-direction: column; gap: .35rem; min-width: 0; }
.sortout-head { display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap; }
.sortout-head strong { font-size: 1.08rem; color: var(--ink); }
.sortout-excerpt {
  font-family: var(--serif); color: var(--ink-soft); line-height: 1.6;
  font-size: .98rem;
}
.sortout-why { font-size: .78rem; color: var(--ink-faint); }

/* A longer note that names this film without being about this evening.
   A line, not a card: the card is for the memory of the evening, and giving
   both the same weight is what put a 2,599-character note above the sentence
   that was actually about the film. */
.mentioned {
  border-left: 2px solid var(--rule); padding: .2rem 0 .2rem .9rem;
  margin: 1.1rem 0; color: var(--ink-faint); font-size: .9rem;
  max-width: var(--prose);
}
.mentioned a { color: var(--accent); }

/* Only on an entry with no date. A quiet offer, not a badge: the entry is not
   deficient, it simply has not been placed yet (D12). */
.undated-note a { color: var(--ink-faint); text-decoration: none;
  border-bottom: 1px dotted var(--rule); }
.undated-note a:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* Everything the archive holds and cannot place. Beneath the timeline, named,
   counted — not hidden, and not pretending to have happened after 2026. */
.unplaced { margin: 3.5rem 0 0; max-width: var(--prose); }
.unplaced h2 { margin-bottom: .4rem; }
.unplaced .index li { padding: 1rem 0; }

/* --- what the archive noticed --------------------------------------------- */
/* Arithmetic, read as prose. No cards, no badges, no counts set as numbers to
   be proud of — this is the archive saying something, and the moment it looks
   like a dashboard it has become one. */

.noticed-list { list-style: none; padding: 0; margin: 0 0 1.4rem; max-width: var(--prose); }
.noticed-list li {
  padding: .8rem 0; border-bottom: 1px solid var(--rule-soft);
  display: flex; gap: 1rem; align-items: baseline; justify-content: space-between;
}
.noticed-text { font-family: var(--serif); font-size: 1.06rem; color: var(--ink); }
.noticed-check {
  font-size: .82rem; color: var(--ink-faint); text-decoration: none;
  white-space: nowrap;
}
.noticed-check:hover { color: var(--accent); }

/* An empty section speaks. Quiet, and not styled as a warning. */
.noticed-quiet {
  color: var(--ink-faint); font-size: .95rem; margin: 0 0 1.4rem;
  max-width: var(--prose);
}

/* A film the archive holds only as a prompt (D51). An invitation, not a
   deficiency: the film is not failing a check, there is simply nothing here
   yet but a title somebody once logged. */
.cue-note {
  border-left: 2px solid var(--accent-soft); padding: .4rem 0 .4rem 1rem;
  margin: 1.4rem 0; color: var(--ink-soft); font-size: .95rem;
  max-width: var(--prose);
}

/* (4) The palette name must not move the masthead.
   Announcing the room you just moved to shifted every nav item left, so the
   cursor was no longer over the button it had just pressed. The name is taken
   out of the flow and given a fixed slot: it appears and fades without
   anything around it moving. */
.masthead nav { position: relative; }
.palette-name {
  position: absolute; right: 0; top: 100%; margin: .3rem 0 0;
  white-space: nowrap; pointer-events: none;
}

/* Superseded: align-self on the tallest item in a stretch row does nothing.
   The fix is align-items on the row itself, at .masthead and .masthead nav. */

/* The second door out of the capture box: somebody who arrived holding
   something rather than remembering something. Quiet, because it is the less
   common errand and the box must still read as one field and a button. */
.capture-alt { font-size: .85rem; color: var(--ink-faint); text-decoration: none; }
.capture-alt:hover { color: var(--accent); }

/* --- fixing a film -------------------------------------------------------- */
/* D33 binds an ambiguous title to the most popular candidate and will sometimes
   be confidently wrong. This is the screen that makes that a decision somebody
   can disagree with rather than one they have to live with. */

.fix-link { margin: 1.4rem 0 0; }
.fix-link a { color: var(--ink-faint); }
.fix-link a:hover { color: var(--accent); }

.fix-candidates { list-style: none; padding: 0; margin: 1.2rem 0 0; max-width: var(--prose); }
.fix-candidates li { border-top: 1px solid var(--rule-soft); padding: .9rem 0; }
.fix-candidates form { display: flex; flex-direction: column; gap: .3rem; }
.fix-name { display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap; }
.fix-name strong { font-size: 1.06rem; color: var(--ink); }
.fix-blurb { font-size: .9rem; color: var(--ink-faint); line-height: 1.5; }
.fix-candidates .linky { align-self: flex-start; padding: 0; }

/* Candidate artwork, shown from the catalogue's own server because these are
   candidates rather than archive content. Nothing is copied in until picked. */
.fix-posters {
  list-style: none; padding: 0; margin: 1.2rem 0 0;
  display: flex; gap: .8rem; flex-wrap: wrap;
}
.fix-posters form { margin: 0; }
.fix-poster {
  padding: 0; background: none; border: 1px solid var(--rule);
  border-radius: 4px; overflow: hidden; cursor: pointer; line-height: 0;
}
.fix-poster:hover { border-color: var(--accent); filter: none; }
.fix-poster img { width: 6rem; height: 9rem; object-fit: cover; display: block; }

/* "Where this came from", folded.
   Reassurance rather than reading matter: people want to know they *can* check
   far more often than they check. Open by default it was the longest thing on
   a memory page and pushed the memory itself off the screen. */
.provenance-fold { margin: 2.5rem 0 0; max-width: var(--prose); }
.provenance-fold > summary {
  cursor: pointer; list-style: none; display: inline-block;
  font-size: 1.02rem; letter-spacing: .02em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint);
  border-bottom: 1px dotted var(--rule); padding-bottom: 2px;
}
.provenance-fold > summary::-webkit-details-marker { display: none; }
.provenance-fold > summary::after { content: " ▸"; }
.provenance-fold[open] > summary::after { content: " ▾"; }
.provenance-fold > summary:hover { color: var(--accent); }

/* Deleting is somebody's right and should look like a real action, not a
   trap: the curtain colour, which the archive otherwise spends only on
   disagreement, because this is the one control that cannot be undone. */
button.danger { background: var(--flag); color: var(--on-accent); }

/* (2) Air under the masthead.
   `main` had no top padding, so a film's poster and title began immediately
   below the band — the page read as though the header had landed on it. */
main { padding-top: 2.2rem; }
.hero, .begin, .built { padding-top: 2.5rem; }

/* --- one door per entry ---------------------------------------------------
   The single edit control that replaced six competing ones on a viewing, and
   the fold that replaced the open capture field at the top of the timeline.
   Both read as a quiet line until somebody wants them, which is the point:
   the page is for the life, not for the form. */
.entry-edit, .capture-fold {
  border: 1px solid var(--rule); border-radius: var(--radius);
  margin: 1.5rem 0; background: var(--paper-deep);
}
.entry-edit > summary, .capture-fold > summary {
  cursor: pointer; padding: .75rem 1rem;
  font-family: var(--display); font-size: .95rem; color: var(--ink-soft);
  list-style: none;
}
.entry-edit > summary::-webkit-details-marker,
.capture-fold > summary::-webkit-details-marker { display: none; }
.entry-edit > summary::before, .capture-fold > summary::before {
  content: "＋"; margin-right: .5rem; color: var(--accent);
}
.entry-edit[open] > summary::before, .capture-fold[open] > summary::before {
  content: "−";
}
.entry-edit > summary:hover, .capture-fold > summary:hover { color: var(--accent); }
.entry-edit > form, .entry-edit > .visibility { padding: 0 1rem; }
.entry-edit > form + form { border-top: 1px dotted var(--rule); padding-top: 1rem; }
.entry-edit > *:last-child { padding-bottom: 1rem; }
.capture-fold > form { padding: 0 1rem 1rem; }
