/* The Quality Club — shared stylesheet.
   Three colors, fixed roles. No fourth swatch, no gradients as brand color. */

/* ---------- Fonts ----------
   Served from src/fonts/ rather than fonts.googleapis.com. The Google
   stylesheet was the slowest thing on the page: a third-party CSS file that
   blocked the first paint and only then revealed which .woff2 to fetch, so the
   type could not arrive until two round trips to two other hosts had finished.
   Self-hosted, they are same-origin and the browser learns about them from a
   file it is already reading.

   The three romans are VARIABLE fonts spanning a whole weight axis — Google
   serves the identical file for 400 and 700, which halved the file count — so
   the range in each font-weight is the axis the file really carries (read off
   its fvar table, not guessed). Declaring the range lets the browser instance
   the weight it needs instead of synthesising a fake bold. The italic is the
   exception: it ships as a static 400 and is declared as one.

   Split latin / latin-ext with the unicode-range Google itself publishes: an
   Italian page almost never leaves U+0000-00FF, so latin-ext is declared but
   in practice never fetched.

   font-display: swap — the text is readable in a fallback serif immediately
   and re-renders when the real face lands. Never invisible. */

@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/cormorant-garamond-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/cormorant-garamond-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "EB Garamond";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/eb-garamond-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "EB Garamond";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/eb-garamond-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* The one italic on the site: <em> in the manifesto and on stemma.html.
   Without a real italic the browser would slant the roman itself. */
@font-face {
  font-family: "EB Garamond";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/eb-garamond-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "EB Garamond";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/eb-garamond-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --void-black: #0E0B08;
  --crest-gold: #D8AB5E;
  --wax-seal-red: #7A1E1E;
  /* The same red lightened for type: #7A1E1E is a seal color, and at text size
     on black it reads as veiled rather than red. Identical hue, raised
     lightness only — still the wax seal, not a fourth color.
     The lightness is set by contrast, not by eye: the seal is 1.90:1 on the
     void and the old #8F2323 only reached 2.27, both under the 3:1 that large
     text needs. #B82D2D is 3.23:1 — hue 0deg and saturation 0.605 unchanged
     from the seal, lightness raised from 0.30 to 0.45 and no further. */
  --wax-seal-red-ink: #B82D2D;

  /* Gold at reduced opacity is still gold, not a new color.
     0.55 came out at 3.47:1, under AA for the caption-sized type that uses it
     — poster captions, dates, the search count. 0.70 clears it at 4.96:1 and
     still sits a visible step below --gold-body, so secondary text still reads
     as secondary rather than being promoted to the same voice as the body. */
  --gold-body: rgba(216, 171, 94, 0.78);
  --gold-muted: rgba(216, 171, 94, 0.7);
  --gold-faint: rgba(216, 171, 94, 0.16);

  --font-display: "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --font-body: "EB Garamond", Georgia, "Times New Roman", serif;
  --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --measure: 56rem;      /* ~896px */
  --page-max: 76rem;
}

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

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

body {
  margin: 0;
  background: var(--void-black);
  color: var(--crest-gold);
  font-family: var(--font-body);
  /* EB Garamond has a small x-height, so it reads a size or two smaller than
     its nominal value. These numbers are set for how it actually looks. */
  font-size: clamp(1.664rem, 2.3vw, 1.966rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--crest-gold);
  outline-offset: 3px;
}

/* ---------- Hero ---------- */

/* Every page opens with the hero — there is no bar above it — so it carries
   its own top spacing. */
.hero {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: clamp(3.5rem, 11vw, 7rem) clamp(1rem, 4vw, 2.5rem) clamp(2.5rem, 6vw, 4rem);
  text-align: center;
}

/* The crest links home from the inner pages. On the home page it is not a
   link, since you are already there. */
.hero__home {
  display: block;
  width: fit-content;
  margin: 0 auto;
  border-radius: 4px;
}

/* One size on every page: each opens with the same crest-and-title header, so
   a smaller crest on the inner pages would read as a different site.
   The crest ships as WebP with the PNG behind it, so the centring lives on the
   <picture> that actually sits in the flow. */
.hero__crest-wrap {
  display: block;
  margin: 0 auto clamp(1.5rem, 4vw, 2.25rem);
  width: fit-content;
}

.hero__crest {
  display: block;
  width: clamp(14rem, 34vw, 22rem);
  height: auto;
}

.hero__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.75rem, 8vw, 5rem);
  line-height: 1.05;
  letter-spacing: 0.01em;
  margin: 0 0 0.5rem;
}

/* Phone: 8vw falls under the 2.75rem floor, leaving the page title smaller
   than the stamped tier headings below it. It has to lead them, so it sits a
   step above the 3rem those take here. */
@media (max-width: 39.99rem) {
  .hero__title {
    font-size: 3.4rem;
  }
}

/* The home page's only navigation: a horizontal row under the crest. */
.hero__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1.25rem, 4vw, 2.5rem);
  margin-top: clamp(1.85rem, 4.4vw, 2.6rem);
  font-family: var(--font-ui);
  font-size: clamp(1.43rem, 1.65vw, 1.6225rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.hero__nav a {
  color: var(--crest-gold);
  text-decoration: underline;
  text-underline-offset: 0.35em;
  text-decoration-thickness: 1px;
}

.hero__nav a:hover { text-decoration-thickness: 2px; }

/* The page you are on stays in the row but is not a link: no underline,
   and dimmed so the three you can still go to lead the eye.
   0.55 put it at 3.47:1 on the black, under the 4.5:1 that body-sized text
   needs; 0.7 reads as the same quiet step back and clears it at 4.96:1. */
.hero__nav-current {
  color: var(--crest-gold);
  opacity: 0.7;
}

/* ---------- Section headers ---------- */

.tier {
  --tier-pad-b: clamp(2.5rem, 7vw, 5rem);
  padding: clamp(2.5rem, 7vw, 5rem) clamp(1rem, 4vw, 2.5rem) var(--tier-pad-b);
  scroll-margin-top: 1rem;
}

html { scroll-behavior: smooth; }
.tier__inner { max-width: var(--page-max); margin: 0 auto; }

.tier__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2rem, 5.5vw, 3.25rem);
  line-height: 1.1;
  margin: 0 0 0.35rem;
}

/* Stamped heading: the stamp sits to the left of the word and is sized off the
   font, so the medal and the capital stay the same height as the type scales.
   A fifth larger than a plain tier heading — the medal is the point here, and
   sizing it through the font keeps word and stamp locked to each other. */
.tier__title--stamped {
  display: flex;
  align-items: center;
  gap: 0.4em;
  font-size: clamp(2.4rem, 6.6vw, 3.9rem);
  margin-bottom: 2rem;
}

/* Sized off the heading font so the two scale together, but deliberately
   larger than the cap height beside it: the medal reads as a seal next to the
   word, not as a matching capital.
   The medal ships as WebP with a PNG fallback, so <picture> — not the image —
   is the flex item beside the word, and the size has to live on both. */
.tier__title--stamped picture {
  display: block;
  flex: none;
}

.tier__stamp {
  width: 1.51em;
  height: 1.51em;
  flex: none;
}

/* Phone: the clamp bottoms out at 2.4rem, which reads small above a row of
   three posters. Push the heading up so the seal still leads the section. */
@media (max-width: 39.99rem) {
  .tier__title--stamped {
    font-size: 3rem;
  }
}

.tier__note {
  font-family: var(--font-ui);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-muted);
  margin: 0 0 2rem;
}

/* Red is used only for rejection. The seal color itself is for marks and
   rules; set as type it needs the ink variant to be legible on the void. */
.tier--shit .tier__title { color: var(--wax-seal-red-ink); }

/* "La Fossa" carries no stamp, so it can't take the stamped class without the
   flex row and spacing built around the medal. It still has to read at the
   same weight as the two headings above it: same type size, nothing else. */
.tier--shit .tier__title {
  font-size: clamp(2.4rem, 6.6vw, 3.9rem);
  margin-bottom: 2rem;
}

@media (max-width: 39.99rem) {
  .tier--shit .tier__title {
    font-size: 3rem;
  }
}

/* ---------- Poster grids ---------- */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: clamp(1rem, 2.5vw, 1.75rem);
}

/* Oro and argento are a single row of the most recent titles: five columns,
   never wrapping to a second line. Fixed tracks rather than auto-fill, so the
   count is the design and not a consequence of how wide the window happens to
   be. build.py ships at most five posters to match.

   An empty tier still holds the row's height, so the page keeps the shape it
   will have once titles land there. The placeholder is a single grid cell with
   the poster's own 2/3 ratio: it sizes itself off the real column width, which
   a min-height in percent could not do — percentages there resolve against the
   container's height, not its width. */
.tier--perfection .grid,
.tier--almost .grid {
  grid-template-columns: repeat(5, 1fr);
}

.grid__placeholder { aspect-ratio: 2 / 3; }

/* Phone: five posters across would be slivers, so the row is three. The two
   extra posters the page ships are hidden rather than reflowed — wrapping them
   onto a second line is exactly what this row must never do. */
@media (max-width: 46.99rem) {
  .tier--perfection .grid,
  .tier--almost .grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .tier--perfection .poster-item:nth-child(n + 4),
  .tier--almost .poster-item:nth-child(n + 4) {
    display: none;
  }
}

.poster {
  position: relative;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  border: 1px solid var(--gold-faint);
  background: #17120c;
}

.poster img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.86);
  transition: filter 0.35s ease;
}

.poster:hover img { filter: brightness(1.05); }

/* Specificity note: `.poster img` above is (0,1,1) and would otherwise stretch
   the stamp to the full poster, so this needs the element selector too. */
.poster img.poster__stamp {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  width: 3.25rem;
  height: 3.25rem;
  pointer-events: none;
}

.poster__caption {
  font-family: var(--font-ui);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--gold-muted);
  margin-top: 0.5rem;
  line-height: 1.4;
}

.poster-item { margin: 0; }

/* ---------- Manifesto ---------- */

.essay {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(0.5rem, 2vw, 1.25rem) clamp(1.25rem, 3vw, 1.75rem) clamp(4rem, 10vw, 7rem);
}

.essay h2 {
  font-family: var(--font-ui);
  font-size: clamp(1.74rem, 2.64vw, 2.16rem);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--wax-seal-red-ink);
  margin: 3.9rem 0 0.6rem;
}

.essay h2:first-of-type { margin-top: 0; }

.essay p {
  color: var(--gold-body);
  margin: 0 0 1.5rem;
}

/* Inline, bold, no background box. */
.key {
  color: var(--wax-seal-red-ink);
  font-weight: 700;
}

/* ---------- Home ---------- */

/* The home page is only the door, so the header is the whole page: centre it
   in the viewport instead of letting it sit against the top edge. */
.hero--door {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: clamp(2rem, 6vw, 4rem);
  padding-bottom: clamp(2rem, 6vw, 4rem);
}

.hero__motto {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(2.25rem, 4.4vw, 3rem);
  color: var(--gold-muted);
  margin: 0.25rem 0 0;
}

/* Present to screen readers, absent on screen: used for labels whose visible
   text is carried by a placeholder, and for the live-region result count. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Search ---------- */

/* The archive reads better a fifth larger than the rest of the site, so the
   search field and the rows below it are zoomed as one block. It has to be
   zoom rather than a bigger font-size: at any usual window width the poster,
   the title and the number are all pinned to the vw term of their clamp(),
   which is tied to the viewport and would not follow the text up. zoom scales
   the boxes and their contents together, and — unlike transform: scale() — it
   reflows, so the column keeps its centring and the page keeps its true
   height. The zoomed column is 44rem * 1.2 = 52.8rem wide, still inside the
   page gutter on a laptop and narrower than .tier__inner's max-width.

   Only from 60rem up. On a phone the column already fills the screen edge to
   edge, so zooming it pushes ~20px off the side and squeezes the titles into
   tall ragged stacks; there the rows are meant to be read at 1. */
.entries-zoom { zoom: 1; }

@media (min-width: 60rem) {
  .entries-zoom { zoom: 1.2; }
}

.search {
  /* Same column as .entries, so the field and the rows share an edge. */
  max-width: 44rem;
  margin: 0 auto clamp(2.5rem, 6vw, 4rem);
}

/* A ruled box, still unfilled: the border draws it, the void shows through. */
.search__input {
  width: 100%;
  background: transparent;
  border: 1px solid var(--gold-faint);
  color: var(--crest-gold);
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4vw, 2.25rem);
  /* Side padding now that there are sides to keep the text off. */
  padding: 0.35em 0.5em;
  transition: border-color 0.3s ease;
}

/* The placeholder is the field's only visible label, so it has to be readable
   rather than a hint: --gold-faint is a border colour and set as type it came
   out at 1.30:1, close to invisible. --gold-muted is the site's quiet-text
   colour and clears AA at 4.96:1. */
.search__input::placeholder { color: var(--gold-muted); }
.search__input:focus { outline: none; border-color: var(--crest-gold); }

.search__input::-webkit-search-cancel-button { filter: invert(1) sepia(1); }

.search__status {
  font-family: var(--font-ui);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-muted);
  margin: 0.75rem 0 0;
  min-height: 1.2em;
}

/* ---------- Chronological entries ---------- */

.entries {
  list-style: none;
  /* Only as wide as the rows need, centred in the page: at full width the
     thumbnail and its three lines were adrift against a very long rule. */
  max-width: 44rem;
  margin: 0 auto;
  padding: 0;
}

/* Poster left, everything else right, stacked. The rule between rows is the
   only divider — no cards, no boxes. The row is deliberately tight: this is a
   list you scan, not a gallery you browse, so the poster is a thumbnail and
   the height is whatever the three stacked lines need. */
/* display on a class beats the hidden attribute's own display:none, so any
   element styled this way has to opt back out explicitly. Without this the
   filter sets [hidden] and nothing disappears. */
.entry[hidden] { display: none; }

.entry {
  display: grid;
  grid-template-columns: auto auto 1fr;
  gap: clamp(1.25rem, 3vw, 2rem);
  align-items: start;
  padding: clamp(0.9rem, 1.8vw, 1.25rem) 0;
  border-bottom: 1px solid var(--gold-faint);
}

.entry:first-child { border-top: 1px solid var(--gold-faint); }


/* The order of entry, 1 being the first title ever added. Centred against the
   poster rather than the row: the body column is taller than the poster, and
   the number belongs to the thumbnail it sits beside. */
.entry__number {
  align-self: center;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.7vw, 2rem);
  /* 600 is the heaviest Cormorant weight the pages load: asking for 700 would
     make the browser synthesise a fake bold. */
  font-weight: 600;
  color: var(--gold-muted);
  font-variant-numeric: tabular-nums;
  /* Room for four digits, so the posters stay in one line however far the
     archive grows. */
  min-width: 3ch;
  text-align: right;
}

.entry__poster {
  /* Same size as a poster in the cinema.html grid (11rem ≈ 177px wide there),
     so a title looks the same on both pages. Set by width, with the height
     following the ratio: unlike the grid, the row has no column to fill. */
  width: clamp(7rem, 13.8vw, 11rem);
  aspect-ratio: 2 / 3;
  overflow: hidden;
  border: 1px solid var(--gold-faint);
  background: #17120c;
}

.entry__poster img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.86);
  transition: filter 0.35s ease;
}

.entry:hover .entry__poster img { filter: brightness(1.05); }

/* Title, then the mark date, then the stamp: one column, left-aligned. */
.entry__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
  padding-top: 0.15rem;
  /* Full poster height, so the stamp has somewhere to be pushed down to. */
  min-height: clamp(10.5rem, 20.7vw, 16.5rem);
}

.entry__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.5rem, 3vw, 2.125rem);
  line-height: 1.15;
  margin: 0;
}

.entry__year {
  color: var(--gold-muted);
  font-weight: 400;
}

.entry__year::before { content: "· "; }

.entry__added {
  font-family: var(--font-ui);
  font-size: 1rem;
  letter-spacing: 0.08em;
  color: var(--gold-muted);
  margin: 0;
}

/* Sits at the bottom of the row, level with the foot of the poster: the title
   is what a film is called, the stamp is what happened to it, and the two
   belong at opposite ends.
   A medal comes wrapped in <picture> (WebP, PNG behind it) and Pure Shit comes
   bare, so whichever of the two is the flex item has to carry the push-down. */
.entry__body > picture {
  display: block;
  margin-top: auto;
}

.entry__stamp {
  width: clamp(5.175rem, 9.2vw, 7.475rem);
  height: clamp(5.175rem, 9.2vw, 7.475rem);
  margin-top: auto;
}

.entries__empty {
  max-width: 44rem;
  margin-inline: auto;
  color: var(--gold-muted);
  padding: clamp(2rem, 6vw, 3.5rem) 0;
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
