/* ==================================================================
   BORING PARTS  /  site v3  /  THE TUESDAY LIST
   ------------------------------------------------------------------
   This page and nothing else. `css/app.css` is loaded first and is
   UNCHANGED: it supplies the tokens, the reset, the type scale, the
   masthead, the buttons and the ink footer, so this file only has to
   describe the things that are new here.

   Two rules govern everything below.

   1. THE ORANGE DOT IS THE PAGE'S ONE ORANGE THING. Not one per
      screen and then something else on the next screen: one device,
      on the whole page. A dot beside a line means one of our Parts
      already takes that job, and that is the only product claim
      anywhere on this page. Nothing else here is Safety Orange - not
      the masthead (which carries no CTA pill at all), not the filter
      row, not the closing button, which is graphite on ink with the
      same inset rule the homepage's mail button carries. The dot is a
      MARK, 7px, never a surface and never text, which is what the
      colour rule permits.

   2. IT IS A LIST SOMEBODY KEEPS, NOT A MARKETING PAGE. IBM Plex Mono
      for the quoted line, because it is a transcript. Archivo for the
      framing. Spec Paper ground, Graphite type, hairlines in Zinc.
      Nothing on this page loops, floats, or arrives twice.
   ================================================================== */

/* ---------- 1. THE PAGE, AND WHAT IT BORROWS ------------------
   The masthead takes its ground outright here. Nothing on this page
   sets `is-set` (that is the homepage's scroll state machine) and the
   bar is over Spec Paper at every scroll position anyway. */
.tl-page .mast { background: var(--paper); border-bottom-color: var(--zinc); }

/* and it reverses over the closing band, exactly as the homepage's
   bar does over its footer. The specificity is deliberate: the rule
   above is as specific as `.mast.is-rev` in app.css and this file
   loads second, so without a third class the bar would stay paper on
   Ink. js/tuesday.js sets the class off an IntersectionObserver. */
.tl-page .mast.is-rev { background: var(--ink); border-bottom-color: var(--ink-rule); }
/* Steel on Ink measures 3.0, which is not a readable nav. The bar's
   reversed nav takes the same two values the dark hero gives it. */
.tl-page .mast.is-rev .mast__nav a { color: var(--ink-2); }
.tl-page .mast.is-rev .mast__nav a i { color: #4A545C; }
.tl-page .mast.is-rev .mast__nav a:hover { color: var(--paper); }
.tl-page .mast.is-rev .mast__nav a[aria-current="page"] { color: var(--paper); }

/* The nav entry itself is styled in app.css section 7, current-page
   colour included, because the homepage carries the same link. */

.tl-page main { background: var(--paper); }

/* the visually hidden helper, same recipe as the sound toggle's label */
.tl-vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------- 2. THE HEADER ------------------------------------ */
.tl-head { padding: calc(var(--mast-h) + 76px) 0 0; }
.tl-index { margin-bottom: 26px; }
.tl-index span:last-child { color: var(--steel); }

.tl-title {
  font-size: clamp(2.4rem, 5.4vw, 4.5rem);
  line-height: 0.98; letter-spacing: -0.032em;
  font-variation-settings: "wdth" 106, "wght" 800;
  margin-bottom: 28px;
}

.tl-lede { max-width: 40ch; margin-bottom: 14px; text-wrap: balance; }
.tl-sub { max-width: 58ch; color: var(--steel); font-size: 15.5px; line-height: 1.55; text-wrap: pretty; }

/* ---------- 3. THE RULES -------------------------------------
   Above the list rather than behind a link, because this page is the
   thing an opener's promise points at and a promise kept somewhere
   else is not kept. */
.tl-rules { padding: 56px 0 0; }

.tl-blocktitle { color: var(--steel); margin-bottom: 16px; }

.tl-spec { border-top: 1px solid var(--zinc); max-width: 880px; }
.tl-spec > div {
  display: grid; grid-template-columns: 168px 1fr; gap: 20px;
  padding: 14px 0; border-bottom: 1px solid var(--zinc);
}
.tl-spec dt { color: var(--steel); padding-top: 2px; }
.tl-spec dd { font-size: 15.5px; line-height: 1.5; }

.tl-notice {
  margin-top: 20px; max-width: 68ch;
  font-size: 14px; line-height: 1.55; color: var(--steel);
}

/* ---------- 4. THE LIST --------------------------------------
   Every hairline on this page lines up on the same right edge: the
   rules table, the filter row, the legend, the week rules and the
   answers themselves. A list that keeps its own column is a list
   somebody keeps. */
.tl-list { padding: 64px 0 96px; }
.tl-list .wrap > * { max-width: 880px; }

.tl-listhead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; margin-bottom: 16px;
}
.tl-listhead .tl-blocktitle { margin-bottom: 0; }
/* both of these are written from the lines on the page and are empty
   until there is something true to put in them */
.tl-tally { color: var(--graphite); }
.tl-tally:empty { display: none; }

/* --- the filter row ---------------------------------------------
   World B's block grammar, the same as the services section's eight
   business blocks: butted matte blocks, the selected one Graphite.
   No orange, because the dot has it.

   It is `hidden` in the markup and the script un-hides it, so with
   the script off a filter that cannot filter is never drawn and every
   answer is on the page. The script also removes any trade with
   nothing behind it, which is what stops a near-empty page from
   showing a row of zeroes. */
.tl-filter { display: flex; flex-wrap: wrap; margin: 0 0 22px; }
.tl-filter[hidden] { display: none; }
.tl-filter__b {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 10px 14px; margin: 0 -1px -1px 0;
  background: var(--paper-2); color: var(--graphite);
  border: 1px solid var(--zinc);
  font-family: var(--mono); font-size: 11.5px; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
  transition: background-color .22s var(--e-seat), color .22s var(--e-seat);
}
.tl-filter__b:hover { background: #E3DFD5; }
.tl-filter__b[aria-pressed="true"] { background: var(--graphite); color: var(--paper); }
.tl-filter__b[aria-pressed="true"]:hover { background: var(--ink); }
.tl-filter__n { color: var(--steel); font-variant-numeric: tabular-nums; }
.tl-filter__b[aria-pressed="true"] .tl-filter__n { color: var(--ash); }
.tl-filter__n:empty { display: none; }
/* the blocks are butted with a -1px margin, so a focus ring drawn on
   one of them is otherwise painted under its neighbour */
.tl-filter__b:focus-visible { position: relative; z-index: 1; }

/* --- the legend ------------------------------------------------
   The dot carries meaning, so the meaning is written out in text on
   the page rather than left to the colour. */
.tl-legend {
  display: flex; align-items: center; gap: 10px;
  color: var(--steel); margin-bottom: 26px;
  padding-bottom: 18px; border-bottom: 1px solid var(--zinc);
}
.tl-legend[hidden] { display: none; }
.tl-legend__dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--orange); flex: none;
}

.tl-status { color: var(--steel); margin-bottom: 18px; }
.tl-status:empty { display: none; }

/* --- the launch state -------------------------------------------
   Visible by default, because the page opens with nothing in it and
   this is the whole of what a reader sees on day one. It is taken
   away by :has() the moment a single answer is on the page, and by
   the script as well, so a browser too old for :has() cannot show it
   next to a list of answers. */
.tl-empty {
  padding: 40px 0 8px; border-bottom: 1px solid var(--zinc);
  margin-bottom: 8px;
}
.tl-list:has(.tl-entry) .tl-empty { display: none; }
.tl-empty[hidden] { display: none; }
.tl-empty__line {
  font-size: clamp(1.375rem, 2.6vw, 2rem); line-height: 1.1;
  letter-spacing: -0.022em; font-variation-settings: "wdth" 102, "wght" 620;
  margin-bottom: 12px; max-width: 22ch;
}
.tl-empty__sub { color: var(--steel); font-size: 15.5px; max-width: 52ch; }

.tl-nofilter { color: var(--steel); padding: 32px 0 8px; }
.tl-nofilter[hidden] { display: none; }

/* --- the weeks -------------------------------------------------- */
.tl-weeks { display: block; }
.tl-week { padding-top: 34px; }
.tl-week[hidden] { display: none; }
.tl-week__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  padding-bottom: 12px; border-bottom: 1px solid var(--zinc);
}
.tl-week__date {
  font-size: 1.0625rem; line-height: 1.2; letter-spacing: -0.012em;
  font-variation-settings: "wdth" 102, "wght" 650;
}
.tl-week__n { color: var(--steel); }
.tl-week__n:empty { display: none; }

/* --- one answer -------------------------------------------------
   A 7px dot in its own gutter, the trade in mono Steel, and then the
   sentence exactly as it was written. No date on a line, no location
   on a line, no link on a line, and nothing after it. */
.tl-lines { display: block; }
.tl-entry {
  display: grid; grid-template-columns: 18px 148px 1fr; gap: 0 20px;
  align-items: baseline;
  padding: 18px 0; border-bottom: 1px solid var(--zinc);
}
.tl-entry[hidden] { display: none; }
.tl-entry::before {
  content: ""; grid-column: 1;
  width: 7px; height: 7px; border-radius: 50%;
  background: transparent; transform: translateY(-3px);
}
/* THE ONE ORANGE THING ON THE PAGE. A mark, never a surface. */
.tl-entry[data-part]::before { background: var(--orange); }

.tl-entry__trade { grid-column: 2; color: var(--steel); }
.tl-entry__line {
  grid-column: 3;
  font-family: var(--mono); font-weight: 400;
  font-size: 15.5px; line-height: 1.62; letter-spacing: -0.004em;
  color: var(--graphite); max-width: 66ch;
}
/* the page draws the quotation marks so nobody has to type them, and
   so a stray straight quote can never end up on the page */
.tl-entry__line q { quotes: "\201C" "\201D" "\2018" "\2019"; }

/* ---------- 5. THE CLOSING BAND ------------------------------
   IT IS A FRAME, WHICH IS WHY IT HAS A FLOOR ON ITS HEIGHT. Without
   one it is about 760px of ink under a 900px screen, so the last
   thing a desktop reader sees is a sliver of Spec Paper trapped
   between the masthead and the ink, and the bar is left sitting on a
   65px strip of nothing. The floor is the viewport less the bar, so
   at the end of the page the closing band is exactly the screen under
   the masthead and the bar reverses onto it - the same closing frame
   the homepage ends on. On a phone the band is already taller than
   that and the floor does nothing. */
.tl-foot { padding: 104px 0 56px; min-height: calc(100vh - var(--mast-h)); }
.tl-close {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 56px; margin: 36px 0 96px;
}
.tl-close__h {
  font-size: clamp(1.5rem, 2.6vw, 2.125rem); line-height: 1.04;
  letter-spacing: -0.026em; font-variation-settings: "wdth" 104, "wght" 700;
  margin-bottom: 18px;
}
.tl-close__p { max-width: 46ch; color: var(--paper); font-size: 16px; line-height: 1.5; }
/* Safety Orange TEXT on Ink is sanctioned by the design system, but
   the dot already owns the page's orange, so the address is an
   ordinary underlined link in Spec Paper. */
.tl-close__p a {
  text-decoration: underline; text-decoration-color: var(--steel);
  text-underline-offset: 3px;
}
.tl-close__p a:hover { text-decoration-color: var(--paper); }
/* graphite on ink, with the edge every graphite object on Ink gets */
.tl-close__btn {
  margin-top: 26px;
  box-shadow: inset 0 0 0 1px var(--ink-rule);
}
.tl-foot__tag { margin-bottom: 56px; }

/* ---------- 6. THE ARRIVAL -----------------------------------
   One arrival, at the top of the page, and then nothing on this page
   ever moves on its own again. No loop, no ambient float, no reveal
   tied to scroll position: a reader who lands mid-page on an anchor
   sees a finished page. Scoped to `html.js` so the no-script build is
   the finished state outright, and killed under `.rm` by app.css
   section 18, which zeroes every duration on the page. */
html.js:not(.rm) .tl-index,
html.js:not(.rm) .tl-title,
html.js:not(.rm) .tl-lede,
html.js:not(.rm) .tl-sub {
  animation: tlArrive .34s var(--e-reveal) both;
}
html.js:not(.rm) .tl-title { animation-delay: .06s; }
html.js:not(.rm) .tl-lede  { animation-delay: .12s; }
html.js:not(.rm) .tl-sub   { animation-delay: .17s; }
@keyframes tlArrive {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* the filter's result, seating. One 140ms settle on the list as a
   whole rather than a transition per line: nine lines each animating
   out of a filter is a page that fidgets. */
html.js:not(.rm) .tl-weeks.is-settling { animation: tlSeat .14s var(--e-seat) both; }
@keyframes tlSeat { from { opacity: .35; } to { opacity: 1; } }

/* ---------- 7. RESPONSIVE ------------------------------------ */
@media (max-width: 900px) {
  .tl-head { padding-top: calc(var(--mast-h) + 48px); }
  .tl-rules { padding-top: 44px; }
  .tl-list { padding: 48px 0 72px; }
  .tl-spec > div { grid-template-columns: 1fr; gap: 4px; padding: 12px 0; }
  .tl-close { grid-template-columns: 1fr; gap: 44px; }
  .tl-foot { padding-top: 80px; }
}

/* the trade label stops being a column and becomes a line above the
   sentence, with the dot still in its own gutter beside it */
@media (max-width: 720px) {
  .tl-entry {
    grid-template-columns: 18px 1fr; gap: 6px 12px;
    align-items: start;
  }
  .tl-entry::before { transform: translateY(6px); }
  .tl-entry__trade { grid-column: 2; }
  .tl-entry__line { grid-column: 2; }
  .tl-filter__b { padding: 9px 11px; font-size: 11px; }
}

@media (max-width: 374px) {
  .tl-entry { grid-template-columns: 14px 1fr; gap: 6px 10px; }
}
