/* ============================================================================
   Ladybug, the site design system.

   One stylesheet for every page that is not the homepage. The homepage stays
   self contained because it carries a lot of machinery nobody else needs: the
   ascii bug, the shelf, the plates. Everything here is the shared part: the
   paper, the type, the chrome at the top and bottom, and the way a document
   reads in the middle.

   The class names are the ones the pages already used, so converting a page is
   a matter of changing what it links to rather than rewriting its markup. That
   was deliberate: the old pages already shared a system, it was just the old
   one.

   Rules
     Type is Redaction 50 for headings, Redaction 35 for everything else, and
     Space Mono for labels. NOTHING is ever bold: Redaction's bold cut is a
     different typeface, and the browser's default bold on <b> and <strong>
     has to be switched off by hand.

     Corners are 0 to 2px. Structure is drawn with dashed hairlines and small
     registration crosses. Red is used ONCE per screen, on the single primary
     action, and never on anything else.
   ========================================================================= */

:root {
  --paper: #F4F3EF;
  --ink: #121211;
  --accent: #EF282D;
  --muted: rgba(18, 18, 17, 0.58);
  --faint: rgba(18, 18, 17, 0.38);
  --hair: rgba(18, 18, 17, 0.16);
  --nav-ink: rgba(18, 18, 17, 0.86);
  --card-bg: rgba(18, 18, 17, 0.025);
  /* The inverted band the footer stands on, and the same three inks again
     for use against it. */
  --sheet: #1C1B18;
  --sheet-ink: #F4F3EF;
  --sheet-muted: #79766D;
  --sheet-faint: rgba(244, 243, 239, 0.42);
  --sheet-hair: rgba(244, 243, 239, 0.18);
  --veil: rgba(244, 243, 239, 0.9);

  --font-d: "Redaction 50", Georgia, serif;
  --font-b: "Redaction 35", Georgia, serif;
  --font-m: "Space Mono", ui-monospace, monospace;

  --rail: max(16px, calc((100vw - 1240px) / 2));
  --gut: calc(var(--rail) + 24px);
  --r: 2px;
}

:root[data-theme="dark"] {
  --paper: #131211;
  --ink: #F4F3EF;
  --muted: rgba(244, 243, 239, 0.60);
  --faint: rgba(244, 243, 239, 0.40);
  --hair: rgba(244, 243, 239, 0.18);
  /* Cream on charcoal carries further than charcoal on cream, so the same
     alpha is not the same weight. Every dark value sits a little lighter. */
  --nav-ink: rgba(244, 243, 239, 0.82);
  --card-bg: rgba(244, 243, 239, 0.05);
  --sheet: #F4F3EF;
  --sheet-ink: #131211;
  --sheet-muted: rgba(10, 10, 10, 0.62);
  --sheet-faint: rgba(10, 10, 10, 0.42);
  --sheet-hair: rgba(10, 10, 10, 0.16);
  --veil: rgba(19, 18, 17, 0.88);
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-b);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* NEVER bold. Hierarchy comes from the face, the size and the ink. */
h1, h2, h3, h4, h5, h6, b, strong { font-weight: 400; }
h1, h2, h3, h4 {
  font-family: var(--font-d);
  margin: 0;
  line-height: 1.04;
  letter-spacing: -0.012em;
}

a { color: inherit; text-decoration: none; }
p a, li a, .prose a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--hair);
  transition: text-decoration-color .2s;
}
p a:hover, li a:hover, .prose a:hover { text-decoration-color: var(--accent); }

::selection { background: var(--accent); color: #F4F3EF; }

img, svg, video { max-width: 100%; }

/* ---- the sheet rails ------------------------------------------------------
   Two dashed verticals that run the height of the page, the way a print sheet
   is trimmed. They are decoration and never take a click. */
.rail {
  position: fixed; top: 0; bottom: 0; width: 0;
  border-left: 1px dashed var(--hair);
  pointer-events: none; z-index: 3;
}
.rail.l { left: var(--rail); }
.rail.r { right: var(--rail); }
@media (max-width: 760px) { .rail { display: none; } }

.wrap {
  max-width: 1240px;
  margin: 0 auto;
  padding-inline: var(--gut);
}

/* ---- header ---------------------------------------------------------------
   The SAME header the homepage carries, so a visitor never crosses a seam.

   Menu left, mark centred, the one red action right. Three grid columns
   rather than a flex row with space-between: `minmax(0,1fr) auto minmax(0,1fr)`
   centres the mark against the WINDOW, not against whatever the menu and the
   button happen to measure. A bare 1fr is minmax(auto,1fr), so a wide right
   hand cell would push its track open and drag the mark off centre. */
.top {
  position: sticky; top: 0; z-index: 40;
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center; gap: 20px;
  padding: 12px var(--gut);
  border-bottom: 1px solid var(--hair);
}
/* The blurred plate is a pseudo element, not the header itself. backdrop-filter
   makes an element a containing block for any fixed descendant, so with the
   filter on .top the mobile sheet would be trapped inside the header box
   instead of filling the window. */
.top::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--veil); backdrop-filter: blur(10px);
}
.brand { display: block; }
.top .brand { justify-self: center; }
.foot .brand { width: max-content; }
/* 34px is the mark's floor. Below about 26px the 27 cell grid stops resolving
   and the dither tail turns to noise. */
.brand img { width: var(--logo, 56px); height: var(--logo, 56px); border-radius: 1px; display: block; }

/* Navigation is not metadata, so it does not take the muted ink the captions
   take. It sits just under full ink: readable at a glance, still quieter than
   the mark and the one red action beside it. */
.top nav {
  justify-self: start; display: flex; gap: 28px;
  font-size: 17px; color: var(--nav-ink);
}
.top nav a:hover { color: var(--ink); }
/* The page you are already on, stated quietly: full ink, no underline, no
   second colour. It is a position, not an action. */
.top nav a[aria-current="page"] { color: var(--ink); }
.top-right { justify-self: end; display: flex; align-items: center; gap: 14px; }

/* Off on desktop. Two bars, not three: the middle one does nothing the outer
   two do not, and two close into an X with no leftover to hide. */
.burger {
  display: none; justify-self: start;
  width: 52px; height: 52px; padding: 0;
  background: none; border: 1px solid var(--hair); border-radius: var(--r);
  cursor: pointer; position: relative; color: inherit;
}
.burger span, .burger span::before {
  content: ""; position: absolute; left: 50%; width: 26px; height: 1.5px;
  background: currentColor; transform: translateX(-50%);
  transition: transform .28s ease, opacity .2s ease;
}
.burger span { top: calc(50% - 6px); }
.burger span::before { top: 12px; left: 0; transform: none; }
.top.open .burger span { transform: translateX(-50%) translateY(6px) rotate(45deg); }
.top.open .burger span::before { transform: translateY(-12px) rotate(-90deg); }

/* The button carries both labels and shows the one that fits. Truncating one
   label with an ellipsis reads as broken; a shorter word does not. */
.cta-tight { display: none; }

/* The one quiet control. No ring, a small half inked disc, muted until the
   cursor is on it. It turns as the theme flips, so it says which way it is
   about to go without needing a label. */
.theme-toggle {
  width: 28px; height: 28px; padding: 0; border: 0;
  background: none; color: var(--muted);
  cursor: pointer; position: relative;
  transition: color .25s ease;
}
.theme-toggle::after {
  content: ""; position: absolute; inset: 7px; border-radius: 50%;
  border: 1px solid currentColor;
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
  transition: transform .4s cubic-bezier(.22, .61, .36, 1);
}
:root[data-theme="dark"] .theme-toggle::after { transform: rotate(180deg); }
.theme-toggle:hover { color: var(--ink); }

/* The one red thing on the page. */
.open-btn, .cta {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--accent); color: #F4F3EF;
  border: 1px solid transparent; border-radius: var(--r);
  padding: 11px 20px;
  font-family: var(--font-b); font-size: 15.5px;
  white-space: nowrap;
  transition: filter .2s;
}
.open-btn:hover, .cta:hover { filter: brightness(1.06); }
/* `.ghost` appears on its own in places, not always alongside `.cta`, so it
   has to carry the whole button on its own rather than only the override. */
.cta.ghost, a.ghost {
  display: inline-flex; align-items: center; gap: 9px;
  background: none; color: var(--ink);
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: 11px 20px;
  font-family: var(--font-b); font-size: 15.5px;
  white-space: nowrap;
  transition: border-color .2s;
}
.cta.ghost:hover, a.ghost:hover { border-color: var(--ink); filter: none; }

/* ---- the page head --------------------------------------------------------
   A mono kick, the title, and a lede. The same three parts on every page, so
   one page never arrives looking like a different site than the last. */
.page-head { padding-top: clamp(46px, 8vh, 96px); }
.kick {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--faint);
  margin: 0 0 16px;
  display: flex; align-items: baseline; gap: 12px;
}
.kick b { color: var(--accent); }
.kick i { font-style: normal; margin-left: auto; color: var(--faint); }

h1 { font-size: clamp(34px, 5.4vw, 62px); max-width: 18ch; text-wrap: balance; }

.lede {
  margin: clamp(16px, 2.4vh, 26px) 0 0;
  max-width: 62ch;
  color: var(--muted);
  font-size: clamp(17px, 1.3vw, 19px);
  line-height: 1.5;
  text-wrap: pretty;
}
.updated {
  margin: 20px 0 0;
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--faint);
}

/* ---- the document ---------------------------------------------------------
   Legal and reference pages are read, not scanned, so the measure is tight and
   the rhythm between a heading and its paragraph is close while the gap above
   the heading is wide. That contrast is what makes a long page navigable. */
section { padding-bottom: clamp(60px, 10vh, 130px); }

/* `.plate` is not a container on these pages, it is the eyebrow line sitting
   above the title. Named before the system was, and kept because renaming it
   would mean editing every page to gain nothing. */
.plate {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--faint);
  margin: 0 0 14px;
}

article { padding-top: clamp(34px, 5vh, 64px); }
article h2 {
  font-size: clamp(21px, 2.1vw, 27px);
  margin: clamp(38px, 5vh, 60px) 0 12px;
  padding-top: clamp(18px, 2.4vh, 26px);
  border-top: 1px solid var(--hair);
  max-width: 30ch;
}
article h3 {
  font-size: clamp(17px, 1.5vw, 20px);
  margin: clamp(24px, 3vh, 34px) 0 8px;
}
article p, article li {
  color: var(--muted);
  max-width: 68ch;
  font-size: 16.5px;
  line-height: 1.62;
}
article p { margin: 0 0 14px; }
article b, article strong { color: var(--ink); }
article ul, article ol { margin: 0 0 18px; padding: 0; list-style: none; }
article li { position: relative; padding-left: 20px; margin-bottom: 8px; }
/* the registration cross, doing duty as a bullet */
article ul > li::before {
  content: "+"; position: absolute; left: 0; top: 1px;
  font-family: var(--font-m); font-size: 12px; color: var(--faint);
}
article ol { counter-reset: n; }
article ol > li { counter-increment: n; }
article ol > li::before {
  content: counter(n, decimal-leading-zero);
  position: absolute; left: 0; top: 3px;
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .1em; color: var(--faint);
}

/* A single held-out note. Hairline, no fill, so it reads as an aside rather
   than a warning box. */
.callout {
  position: relative;
  margin: clamp(26px, 3.4vh, 38px) 0;
  padding: clamp(20px, 2.6vw, 28px);
  border: 1px dashed var(--hair);
  border-radius: var(--r);
  background: var(--card-bg);
}
.callout p:last-child { margin-bottom: 0; }
.callout p { max-width: none; }
/* The four corner crosses are in the markup already. Unstyled they pile up
   as literal "++++" at the top of the note, so they are placed on the
   junctions they were drawn for. */
.callout .x {
  position: absolute; line-height: 1;
  font-family: var(--font-m); font-size: 12px; color: var(--faint);
}
.callout .x.tl { left: -6px; top: -7px; }
.callout .x.tr { right: -6px; top: -7px; }
.callout .x.bl { left: -6px; bottom: -7px; }
.callout .x.br { right: -6px; bottom: -7px; }

/* ---- cards ----------------------------------------------------------------
   The generic plate used by pricing, roadmap and tutorials. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(16px, 2.2vw, 28px);
  margin-top: clamp(28px, 4vh, 46px);
}
.card {
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: clamp(22px, 2.4vw, 32px);
  display: flex; flex-direction: column;
}
.card h3 { margin-bottom: 10px; }
.card p { color: var(--muted); font-size: 16px; margin: 0 0 12px; }
.card .tag {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 14px;
}

/* ---- footer ---------------------------------------------------------------
   The SAME footer the homepage carries: an inverted band, four columns, the
   mark standing on its own at the left. */
.sheet { padding-inline: var(--gut); }
.grid {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(16px, 2vw, 28px);
}
.foot {
  background: var(--sheet); color: var(--sheet-ink);
  padding-block: clamp(46px, 7vh, 84px) 34px;
}
.foot .grid { row-gap: 36px; }
.foot-id { grid-column: 1 / 5; }
.foot-id p { margin-top: 16px; color: var(--sheet-muted); font-size: 15.5px; max-width: 30ch; }
.foot-col { grid-column: span 2; }
.foot h4 {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--sheet-faint); margin: 0;
}
.foot ul { margin: 15px 0 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.foot li { margin: 0; padding: 0; }
.foot li::before { content: none; }
.foot li a { color: var(--sheet-muted); font-size: 15px; }
.foot li a:hover { color: var(--sheet-ink); }
.foot-end {
  grid-column: 1 / -1; margin-top: 20px; padding-top: 20px;
  border-top: 1px solid var(--sheet-hair);
  display: flex; justify-content: space-between; gap: 16px;
  font-family: var(--font-m); font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--sheet-faint);
}

/* ---- the mobile menu ------------------------------------------------------
   A full sheet rather than a dropdown: at this size the links deserve to be
   the only thing on screen. */
@media (max-width: 940px) {
  .burger { display: block; }
  .top nav {
    position: fixed; inset: 0; z-index: -1;
    /* Must be reset from the desktop grid's `start`. A self-alignment other
       than normal/stretch makes an out-of-flow box shrink to fit rather than
       stretch to its inset, so the sheet would size to its longest link
       instead of filling the window. */
    justify-self: stretch;
    display: flex; flex-direction: column; justify-content: center;
    gap: clamp(14px, 3.4vh, 30px);
    padding: 0 var(--gut);
    background: var(--paper);
    font-family: var(--font-d); font-size: clamp(30px, 8vw, 54px);
    color: var(--ink);
    opacity: 0; visibility: hidden;
    transition: opacity .26s ease, visibility .26s;
  }
  .top.open nav { opacity: 1; visibility: visible; z-index: 1; }
  /* Shut, the sheet must not be reachable by keyboard either. */
  .top:not(.open) nav a { visibility: hidden; }
  .top.open { background: var(--paper); }
  .top-right, .brand, .burger { position: relative; z-index: 2; }
  body.nav-open { overflow: hidden; }
}

/* ---- phone ---------------------------------------------------------------- */
@media (max-width: 760px) {
  body { font-size: 16px; }
  .top { padding-inline: max(16px, calc(var(--gut) - 12px)); gap: 10px; }
  .brand img { width: var(--logo-m, var(--logo, 44px)); height: var(--logo-m, var(--logo, 44px)); }
  /* The button must stay on one line: wrapped, it doubles the header height
     and shoves the mark off the vertical centre. */
  .top-right .cta, .top-right .open-btn { padding: 9px 14px; font-size: 13.5px; white-space: nowrap; }
  .cta-full { display: none; }
  .cta-tight { display: inline; }
  .top-right { gap: 9px; }
  .theme-toggle { width: 26px; height: 26px; }
  .burger { width: 46px; height: 46px; }
  h1 { font-size: clamp(30px, 8.4vw, 44px); }
  .foot-id, .foot-col { grid-column: 1 / -1; }
  .foot-end { flex-direction: column; gap: 8px; }
}

/* ============================================================================
   PAGE COMPONENTS

   Each page below already had its own vocabulary of class names, and several
   of them are written by script rather than by hand: the roadmap list, the
   changelog timeline and the tutorial playlist all arrive after the fetch.
   The names here were read off those scripts, not guessed, so a card that is
   built at runtime lands already dressed.
   ========================================================================= */

/* ---- pricing ------------------------------------------------------------ */
.plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: clamp(18px, 2.4vw, 32px);
  margin-top: clamp(30px, 4.4vh, 54px);
}
.plan {
  position: relative;
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: clamp(24px, 2.6vw, 36px);
  display: flex; flex-direction: column;
}
.plan .x {
  position: absolute; line-height: 1;
  font-family: var(--font-m); font-size: 12px; color: var(--faint);
}
.plan .x.tl { left: -6px; top: -7px; }
.plan .x.tr { right: -6px; top: -7px; }
.plan .x.bl { left: -6px; bottom: -7px; }
.plan .x.br { right: -6px; bottom: -7px; }
.plan-name {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--faint);
}
/* the one live mark, and the only red on the card */
.plan-name .live, .live { color: var(--accent); }
.price {
  font-family: var(--font-d); font-size: clamp(40px, 4.6vw, 58px);
  line-height: 1; margin-top: 14px;
}
.price span, .price small, .price em {
  font-family: var(--font-m); font-size: 12px; font-style: normal;
  letter-spacing: .08em; color: var(--muted);
}
.price-alt {
  margin-top: 9px;
  font-family: var(--font-m); font-size: 10.5px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
.plan ul {
  list-style: none; padding: 0;
  margin: clamp(22px, 2.8vh, 30px) 0 clamp(24px, 3vh, 34px);
  display: grid; gap: 10px;
}
.plan li {
  position: relative; padding-left: 19px; margin: 0;
  color: var(--muted); font-size: 16px; line-height: 1.45;
}
.plan li::before {
  content: "+"; position: absolute; left: 0; top: 1px;
  font-family: var(--font-m); font-size: 12px; color: var(--faint);
}
.plan li strong, .plan li b { color: var(--ink); }
/* the action sits on the floor of its own card, since the two lists differ */
.cta-row { margin-top: auto; }
.fine {
  margin-top: clamp(34px, 5vh, 56px);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(18px, 2.4vw, 32px);
}
.fine h3 { font-size: 18px; margin-bottom: 8px; }
.fine p { color: var(--muted); font-size: 15.5px; max-width: 46ch; }

/* ---- roadmap ------------------------------------------------------------ */
.rm-toolbar {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: clamp(26px, 3.6vh, 44px);
}
.rm-toolbar button {
  font-family: var(--font-m); font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase;
  padding: 8px 13px; cursor: pointer;
  background: none; color: var(--muted);
  border: 1px solid var(--hair); border-radius: var(--r);
  transition: color .2s, border-color .2s;
}
.rm-toolbar button:hover { color: var(--ink); }
.rm-toolbar button[aria-pressed="true"], .rm-toolbar button.is-on {
  border-color: var(--ink); color: var(--ink);
}
.rm-list { margin-top: clamp(22px, 3vh, 34px); display: grid; gap: 12px; }
.rm-card {
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: clamp(18px, 2vw, 26px);
  display: flex; gap: clamp(14px, 1.8vw, 24px); align-items: flex-start;
}
.rm-votes {
  flex: none; min-width: 58px; text-align: center;
  font-family: var(--font-m); font-size: 15px; color: var(--ink);
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: 9px 6px;
}
.rm-main { min-width: 0; }
.rm-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.rm-title { font-family: var(--font-d); font-size: clamp(18px, 1.7vw, 21px); }
.rm-badge {
  font-family: var(--font-m); font-size: 9.5px;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--faint);
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: 3px 7px;
}
.rm-body, .rm-meta { color: var(--muted); font-size: 15.5px; margin-top: 8px; }
.rm-meta { font-family: var(--font-m); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.rm-response {
  margin-top: 12px; padding-left: 14px;
  border-left: 1px solid var(--hair);
  color: var(--muted); font-size: 15.5px;
}
.rm-state {
  font-family: var(--font-m); font-size: 11px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}
.rm-cta {
  margin-top: clamp(34px, 5vh, 56px); padding-top: clamp(22px, 3vh, 30px);
  border-top: 1px solid var(--hair);
  display: flex; flex-wrap: wrap; gap: 16px;
  align-items: center; justify-content: space-between;
}
.rm-cta p { margin: 0; color: var(--muted); }
.rm-cta a {
  display: inline-flex; align-items: center;
  background: var(--accent); color: #F4F3EF;
  border-radius: var(--r); padding: 11px 20px; font-size: 15.5px;
}

/* ---- changelog ---------------------------------------------------------- */
.page-head { padding-top: clamp(46px, 8vh, 96px); }
.page-head p { color: var(--muted); max-width: 62ch; margin-top: 16px; }
.kicker {
  display: block; margin-bottom: 14px;
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--faint);
}
/* The padding SHORTHAND here would reset the inline padding that .wrap sets,
   which dropped the whole timeline 124px to the left of the page heading. Only
   the block start is set, so the column stays where the rest of the site is. */
.timeline { position: relative; padding-block-start: clamp(30px, 5vh, 56px); }
/* The spine sits in the margin, just outside the text column, so the entries
   line up with the heading above them rather than being pushed off it. */
.timeline-ruler {
  position: absolute; left: calc(var(--gut) - 24px); top: 0; bottom: 0; width: 0;
  border-left: 1px dashed var(--hair);
}
.month { position: relative; }
.month-head {
  display: flex; align-items: baseline; gap: 12px;
  margin: clamp(30px, 4vh, 48px) 0 18px;
}
.month-name { font-family: var(--font-d); font-size: clamp(20px, 2vw, 26px); }
.month-count {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}
.entry {
  position: relative;
  border-top: 1px solid var(--hair);
  padding: clamp(20px, 2.6vh, 30px) 0;
  display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 7fr);
  gap: clamp(16px, 2.4vw, 34px);
}
.entry-main { min-width: 0; }
.entry-copy { color: var(--muted); font-size: 16px; }
.entry-copy p { color: var(--muted); }
/* the dot where an entry meets the spine, out in the margin with it */
.node {
  position: absolute; left: -24px;
  top: clamp(24px, 2.8vh, 34px);
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--faint); transform: translateX(-2px);
}
.just-shipped .node { background: var(--accent); }
.stamp-card { display: flex; flex-direction: column; gap: 2px; }
.stamp, .stamp-day, .stamp-weekday, .stamp-time {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.stamp-number { font-family: var(--font-d); font-size: clamp(26px, 3vw, 38px); line-height: 1; color: var(--ink); }
.tag-row { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.tag {
  font-family: var(--font-m); font-size: 9.5px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: 3px 7px;
}
.media { margin-top: 14px; border: 1px solid var(--hair); border-radius: var(--r); overflow: hidden; }
.media img, .media video { display: block; width: 100%; }
.media-cap, .release-preview-cap {
  font-family: var(--font-m); font-size: 9.5px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
  padding: 8px 10px; border-top: 1px solid var(--hair);
}
.origin { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.origin-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
.origin-label {
  font-family: var(--font-m); font-size: 9.5px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.release-section { margin-top: clamp(18px, 2.4vh, 26px); }
.release-section-head, .release-section-meta {
  font-family: var(--font-m); font-size: 9.5px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.release-section-number { font-family: var(--font-m); color: var(--faint); }
.release-section-copy { color: var(--muted); font-size: 16px; }
.release-good-for { margin-top: 10px; color: var(--muted); font-size: 15.5px; }
.compact-line { color: var(--muted); font-size: 15.5px; }
.load-error {
  font-family: var(--font-m); font-size: 11px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}

/* ---- tutorials ---------------------------------------------------------- */
.stage {
  margin-top: clamp(28px, 4vh, 48px);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 340px);
  gap: clamp(20px, 2.6vw, 36px); align-items: start;
}
.stage-main { min-width: 0; }
.player {
  aspect-ratio: 16 / 9; width: 100%;
  border: 1px solid var(--hair); border-radius: var(--r);
  overflow: hidden; background: var(--card-bg);
}
.player iframe, .player video { width: 100%; height: 100%; border: 0; display: block; }
.stage-below { margin-top: clamp(16px, 2.2vh, 24px); }
.now-kicker {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .18em; text-transform: uppercase; color: var(--faint);
}
.now-title { font-family: var(--font-d); font-size: clamp(21px, 2.2vw, 28px); margin-top: 8px; }
.now-blurb { color: var(--muted); margin-top: 10px; max-width: 62ch; }
.tut-controls, .tut-nav { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.tut-nav button, .tut-controls button {
  font-family: var(--font-m); font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase;
  padding: 9px 14px; cursor: pointer;
  background: none; color: var(--muted);
  border: 1px solid var(--hair); border-radius: var(--r);
}
.tut-nav button:hover, .tut-controls button:hover { color: var(--ink); border-color: var(--ink); }
.upnext-label, .playlist-label {
  font-family: var(--font-m); font-size: 10px;
  letter-spacing: .18em; text-transform: uppercase; color: var(--faint);
  margin-bottom: 12px;
}
/* The card is the BUTTON, not the list item around it, and the thumb is a
   span WRAPPING the image rather than the image itself. Styling the wrappers
   as though they were the picture is what left grey plates with the title and
   the blurb printed on top of each other. */
.playlist, .upnext-cards { display: grid; gap: 10px; list-style: none; margin: 0; padding: 0; }
.playlist li, .upnext-cards li { margin: 0; padding: 0; }
.playlist li::before, .upnext-cards li::before { content: none; }

/* The playlist wraps each card in an <li>; up next puts the buttons straight
   into the grid. Both shapes are named so neither goes out undressed. */
.playlist .item, .upnext-cards .item,
.upnext-cards > button, .upnext-cards > * > button {
  width: 100%; text-align: left; cursor: pointer;
  display: grid; grid-template-columns: 74px minmax(0, 1fr) auto;
  gap: 12px; align-items: center;
  background: none; color: inherit; font: inherit;
  border: 1px solid var(--hair); border-radius: var(--r);
  padding: 10px;
  transition: border-color .2s;
}
.playlist .item:hover, .upnext-cards .item:hover,
.upnext-cards > button:hover { border-color: var(--ink); }
/* The one playing states itself, and it is the only marked card in the list. */
.playlist .item[aria-current="true"] { border-color: var(--ink); }

.item-thumb, .upnext-thumb {
  position: relative; display: block;
  width: 74px; aspect-ratio: 16 / 10;
  border-radius: var(--r); overflow: hidden;
  background: var(--card-bg);
}
.item-thumb img, .upnext-thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.item-num, .upnext-num {
  position: absolute; left: 5px; bottom: 3px;
  font-family: var(--font-m); font-size: 9px; letter-spacing: .1em;
  color: #F4F3EF; text-shadow: 0 1px 3px rgba(0, 0, 0, .7);
}
.item-text, .upnext-meta { display: block; min-width: 0; }
.item-title, .upnext-t { display: block; font-size: 15px; line-height: 1.3; }
.item-blurb, .upnext-b {
  display: block; color: var(--faint); font-size: 12.5px;
  margin-top: 3px; line-height: 1.35;
}
.item-now {
  font-family: var(--font-m); font-size: 9px;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); white-space: nowrap;
}

@media (max-width: 860px) {
  .stage { grid-template-columns: 1fr; }
  .entry { grid-template-columns: 1fr; }
}
