:root {
  --bg: #F6F5F1;
  --ink: #211B17;
  --ink-2: #3A3128;
  --muted: #7A6F64;
  --accent: #3E7BFA;
  /* The four cards in the logo, in reading order. They are also the blob
     colors and the first four entries of PALETTE in app.js. */
  --brand-red: #FF5C61;
  --brand-blue: #3E7BFA;
  --brand-yellow: #FFC53D;
  --brand-green: #21C17C;
  --display: 'Bricolage Grotesque', system-ui, sans-serif;
  --body: 'Work Sans', system-ui, sans-serif;
}

* { box-sizing: border-box; }
/* Layout rules below set display on elements that app.js hides by attribute;
   this keeps hidden meaning hidden. */
[hidden] { display: none !important; }
html, body { margin: 0; }
body { font-family: var(--body); background: var(--bg); color: var(--ink); }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }
::selection { background: #FFC53D; color: var(--ink); }

.app { display: flex; min-height: 100vh; }

/* Sidebar */
.sidebar {
  width: 240px; flex: 0 0 240px;
  display: flex; flex-direction: column; gap: 24px;
  padding: 28px 18px;
  background: rgba(255,255,255,.45);
  border-right: 1px solid rgba(0,0,0,.05);
  position: sticky; top: 0; height: 100vh;
}
.sidebar-header { display: flex; align-items: center; justify-content: space-between; min-height: 32px; }
.sidebar-toggle {
  display: none; align-items: center; justify-content: center; flex-shrink: 0;
  position: absolute; top: 30px; right: 18px;
  width: 28px; height: 28px; padding: 0; border-radius: 9px;
  border: 1px solid rgba(33,27,23,.1); background: var(--bg); color: var(--muted);
  cursor: pointer;
}
.sidebar-toggle:hover { color: var(--ink); background: #fff; }
.sidebar-toggle:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.brand { display: flex; align-items: center; gap: 9px; width: fit-content; border-radius: 10px; }
.brand:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.brand-mark { display: block; flex-shrink: 0; width: 26px; height: 26px; }
.wordmark { font-family: var(--display); font-weight: 800; font-size: 18px; letter-spacing: -0.03em; }
.nav { display: flex; flex-direction: column; gap: 8px; }
.nav-heading { font-size: 13px; font-weight: 700; padding: 0 6px; }
.nav-list { display: flex; flex-direction: column; gap: 8px; }

/* Featured sits open at the top; every product waits under it behind a native
   disclosure that opens downward. Deliberately no `display` on .nav-more: it is
   a <details> that app.js hides with the hidden attribute when nothing is
   featured, and a display here would override that. */
.nav-group { display: flex; flex-direction: column; gap: 8px; }
/* More air than the 8px between tabs, so More Products reads as the start of a
   section rather than one more row of the list above it.

   Spacing inside the disclosure is margins, not the flex gap .nav-group sets:
   where a browser wraps the open content in ::details-content, that wrapper is
   the flex item, so the gap stops at it and never reaches the list or the slot
   below — which left Request sitting flush against the last product. Margins
   land the same in both. */
.nav-more { display: block; margin-top: 14px; }
.nav-more-content > .nav-list { margin-top: 8px; }
.nav-more-content > .tab-ghost { margin-top: 8px; }
.nav-summary-short { display: none; }
/* The pinned current product shows at every width: see renderTabs(). It is the
   lit tab, so it needs no decoration of its own to read as where you are. */
.nav-summary {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 0 6px; cursor: pointer;
  font-size: 13px; font-weight: 700; color: var(--ink);
  list-style: none;
}
/* The default triangle, in both dialects. The caret below replaces it. */
.nav-summary::-webkit-details-marker { display: none; }
.nav-summary::marker { content: ''; }
.nav-summary:hover { color: var(--ink-2); }
.nav-summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 6px; }
.nav-caret { flex-shrink: 0; color: var(--muted); transition: transform .18s ease; }
.nav-more[open] .nav-caret { transform: rotate(180deg); }

/* Opening eases; closing does not. The height transition that used to run both
   ways went through ::details-content, and on the way back it fights the
   browser hiding that box: the contents blink out and the drawer collapses
   around nothing. An instant close is honest and never looks broken, so only
   the open is animated — a short fade and settle on the contents, which needs
   no height interpolation and so behaves the same everywhere. */
@keyframes nav-drop {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
.nav-more[open] .nav-more-content { animation: nav-drop .18s ease-out both; }

.tab {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px;
  padding: 11px 14px; border: none; border-radius: 15px; cursor: pointer;
  font: 600 14px/1.2 var(--body); text-align: left;
  background: rgba(255,255,255,.55); color: #4A4038;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.05);
  transition: transform .15s ease, filter .15s ease, box-shadow .2s ease;
}
.tab:hover { filter: brightness(1.03); }
.tab:active { transform: translateY(1px); }
.tab:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.tab[aria-pressed="true"] {
  color: #fff;
  background: linear-gradient(145deg, var(--c), var(--c-dark));
  box-shadow: 0 10px 20px -8px color-mix(in srgb, var(--c) 60%, transparent),
              inset 0 1px 0 rgba(255,255,255,.35), inset 0 -2px 6px rgba(0,0,0,.18);
}
.tab svg { width: 18px; height: 18px; flex-shrink: 0; }
.tab-pic { width: 18px; height: 18px; flex-shrink: 0; border-radius: 4px; object-fit: cover; }

/* margin-top:auto pins this to the bottom of the sidebar column. The two
   controls here are different kinds of thing, so they are styled apart rather
   than as a matched pair: Request is an action that opens a dialog, About is a
   link to another view. Both centered on the column. */
/* Small + on the heading row: an icon-only control on the list it heads, so it
   rests like a tab and fills in solid on hover. The label lives in aria-label
   and title, since there is no text to read. */
/* The slot a product would sit in if anyone had asked for it: the tab's exact
   shape, drawn as a grey dashed outline instead of filled. The 2px border with
   9px/12px padding adds back to the 11px/14px a real tab has, so it lines up
   with them rather than standing 3px taller. */
.tab-ghost {
  padding: 9px 12px;
  border: 2px dashed rgba(0,0,0,.16);
  background: transparent; color: var(--muted);
  box-shadow: none;
}
.tab-ghost:hover {
  filter: none;
  color: var(--ink-2); border-color: rgba(0,0,0,.32);
  background: rgba(255,255,255,.4);
}

.sidebar-foot { margin-top: auto; flex-shrink: 0; display: flex; justify-content: flex-start; }
/* Quiet text, so a destination never competes with the lit technology tab
   above it. Underlined rather than filled when it is the view you are on. */
.about-link {
  padding: 2px 6px; border-radius: 8px;
  font: 500 13.5px/1.2 var(--body); color: var(--muted);
  transition: color .15s ease;
}
.about-link:hover { color: var(--ink); }
.about-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.about-link[aria-current="page"] {
  color: var(--ink); font-weight: 600;
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px;
}

/* The desktop rail uses the same box for every product's own logo. */
@media (min-width: 901px) {
  .sidebar {
    z-index: 2;
    transition: width .18s ease-out, flex-basis .18s ease-out, padding-inline .18s ease-out;
  }
  .sidebar-toggle { display: flex; transition: right .18s ease-out; }
  .sidebar .nav { min-height: 0; overflow-y: auto; padding: 4px; margin: -4px; scrollbar-width: thin; overscroll-behavior-y: contain; }
  .sidebar .nav-group { flex-shrink: 0; }
  .sidebar .brand { min-width: 0; overflow: hidden; }
  .sidebar .wordmark, .sidebar .tab-label { white-space: nowrap; }
  .sidebar .tab { overflow: hidden; }
  [data-sidebar-collapsed="true"] .sidebar { width: 88px; flex-basis: 88px; padding-inline: 16px; }
  [data-sidebar-collapsed="true"] .sidebar-header { justify-content: center; }
  [data-sidebar-collapsed="true"] .brand { justify-content: center; width: 48px; min-height: 32px; }
  /* Collapsed, the rail is icons only, so the headings go — and with them the
     More Products disclosure, whose whole job is a label you click. The featured
     icons remain; widen the sidebar to reach the rest. */
  [data-sidebar-collapsed="true"] .wordmark,
  [data-sidebar-collapsed="true"] .nav-heading,
  [data-sidebar-collapsed="true"] .nav-more,
  [data-sidebar-collapsed="true"] .tab-label { display: none; }
  [data-sidebar-collapsed="true"] .sidebar-toggle { right: -14px; }
  [data-sidebar-collapsed="true"] .sidebar-toggle svg { transform: rotate(180deg); }
  [data-sidebar-collapsed="true"] .nav { align-items: center; gap: 10px; }
  [data-sidebar-collapsed="true"] .nav-list { gap: 10px; }
  [data-sidebar-collapsed="true"] .tab {
    justify-content: center; width: 48px; height: 48px; padding: 0; border-radius: 12px;
  }
  [data-sidebar-collapsed="true"] .tab:not(.tab-ghost) {
    color: var(--ink-2); background: rgba(255,255,255,.8);
    box-shadow: inset 0 0 0 1px rgba(33,27,23,.1);
  }
  [data-sidebar-collapsed="true"] .tab[aria-pressed="true"] {
    color: var(--c); background: #fff;
    box-shadow: inset 0 0 0 2px var(--c), 0 3px 8px rgba(33,27,23,.06);
  }
  [data-sidebar-collapsed="true"] .tab-pic { width: 24px; height: 24px; object-fit: contain; border-radius: 5px; }
  [data-sidebar-collapsed="true"] .tab svg { width: 22px; height: 22px; }
  [data-sidebar-collapsed="true"] .sidebar-foot { justify-content: center; }
}

/* Request dialog */
.modal {
  width: min(440px, calc(100vw - 32px)); padding: 0; border: none;
  border-radius: 22px; background: var(--bg); color: var(--ink);
  box-shadow: 0 30px 60px -24px rgba(40,28,16,.5);
}
.modal::backdrop { background: rgba(33,27,23,.42); }
.modal-card { display: flex; flex-direction: column; gap: 18px; padding: 26px; }
.modal-title {
  margin: 0; font-family: var(--display); font-weight: 800;
  font-size: 19px; line-height: 1.3; letter-spacing: -0.02em;
}
.modal-input {
  width: 100%; padding: 13px 15px; font: 400 15.5px/1.3 var(--body); color: var(--ink);
  background: #fff; border: none; border-radius: 13px;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.14);
}
.modal-input::placeholder { color: var(--muted); }
.modal-input:focus { outline: none; box-shadow: inset 0 0 0 2px var(--ink); }
/* Sits in the button row and takes the slack, so an empty status line leaves
   no gap behind. flex (not margin-right:auto) because an auto margin pushes
   the buttons onto separate rows once the row wraps. */
.modal-note { margin: 0; flex: 1 1 auto; min-width: 0; font-size: 13.5px; line-height: 1.35; color: var(--muted); }
.modal-note[data-tone="error"] { color: #C02B3A; }
.modal-note[data-tone="ok"] { color: #12855A; }
.modal-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.btn {
  min-width: 94px; padding: 11px 18px; border: none; border-radius: 13px;
  cursor: pointer; font: 600 14.5px/1 var(--body);
}
.btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.btn[disabled] { opacity: .55; cursor: default; }
.btn-ghost { background: transparent; color: var(--ink-2); box-shadow: inset 0 0 0 1px rgba(0,0,0,.14); }
.btn-ghost:hover:not([disabled]) { background: rgba(0,0,0,.05); }
.btn-solid { background: var(--ink); color: #fff; }
.btn-solid:hover:not([disabled]) { filter: brightness(1.18); }

/* Main */
.main {
  flex: 1; min-width: 0; position: relative; overflow: hidden;
  padding: 52px 56px 72px;
  display: flex; flex-direction: column; gap: 36px;
}
.view { display: flex; flex-direction: column; gap: 36px; }
/* Keep the product feed compact, with a readable ceiling on wide screens. */
[data-view="feed"] .main { padding: 44px 48px 64px; }
#view-feed { width: 100%; max-width: 1040px; gap: 32px; }
/* Which view shows is data-view on <html> — set by the inline script in the
   head before first paint, and by showView() from then on. */
[data-view="feed"] #view-about, [data-view="about"] #view-feed { display: none; }
.blobs { position: absolute; inset: 0 0 auto 0; height: 820px; pointer-events: none; z-index: 0; }
.blob { position: absolute; border-radius: 50%; }
.b1 { top: -130px; left: -90px; width: 380px; height: 380px; background: #FF5C61; filter: blur(110px); opacity: .07; }
.b2 { top: 30px; right: -110px; width: 440px; height: 440px; background: #3E7BFA; filter: blur(120px); opacity: .07; }
.b3 { top: 360px; left: 140px; width: 400px; height: 400px; background: #FFC53D; filter: blur(115px); opacity: .06; }
.b4 { top: 480px; right: 180px; width: 340px; height: 340px; background: #21C17C; filter: blur(110px); opacity: .06; }

.hero {
  position: relative; z-index: 1; margin: 0;
  font-family: var(--display); font-weight: 800;
  font-size: clamp(24px, calc((100vw - 336px) / 26), 48px); line-height: 1.1; letter-spacing: -0.015em;
  white-space: nowrap;
}
.marker { position: relative; display: inline-block; isolation: isolate; }
.marker::before {
  content: ""; position: absolute; top: 12%; bottom: 6%; left: -4%; right: -4%;
  background: #FFC53D; opacity: .4; border-radius: 10px; transform: rotate(-2deg); z-index: -1;
}
/* Keep the placeholder's width so the headline does not jump while products
   load, but do not paint a fake blue product name. app.js reveals the real
   name only after its real color is ready. */
.hero-tech[aria-hidden="true"] { visibility: hidden; }
.hero-tech { color: var(--accent); transition: color .25s ease; }

/* Cards stay in ranked DOM order while app.js assigns them round-robin to
   masonry columns. One-pixel implicit rows let every column pack independently
   without grouping links into column-major containers. */
.feed {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: repeat(var(--feed-columns, 3), minmax(0, 1fr));
  column-gap: 20px; align-items: start;
  transition: opacity .15s ease;
}
.feed.is-masonry { grid-auto-rows: 1px; }
.feed[aria-busy="true"] { opacity: .58; }
/* Invisible, and deliberately weightless: the negative margin cancels the
   view's 36px gap so the trip wire cannot push the page around. */
#feed-sentinel { height: 1px; margin-top: -36px; }
.card {
  display: block; margin: 0; position: relative;
  padding: 14px; border-radius: 16px;
  /* No backdrop-filter here. Every card would be its own backdrop layer for
     the compositor to re-sample each frame, and a fast scroll outruns it and
     paints unrasterized tiles white. It bought nothing anyway: the backdrop is
     a flat colour plus blobs already blurred 110px at 7%, so there is no
     detail for a 24px blur to soften. */
  background: rgba(255,255,255,.78);
  border: 1px solid rgba(255,255,255,.9);
  box-shadow: 0 1px 2px rgba(40,28,16,.05), 0 12px 28px -18px rgba(40,28,16,.22);
  transition: transform .22s ease, box-shadow .22s ease;
  animation: rise .4s ease both;
}
@media (hover: hover) and (pointer: fine) {
  .card:hover { transform: translateY(-5px); box-shadow: 0 22px 36px -18px rgba(40,28,16,.35); }
}

/* The card is a div so that the expander can be a real button. The author's
   name holds the link and stretches an invisible overlay across the whole card,
   which keeps clicking anywhere on it opening the post. */
.card-link::after { content: ""; position: absolute; inset: 0; border-radius: 16px; }
.card-link:focus-visible { outline: none; }
.card-link:focus-visible::after { outline: 2px solid var(--ink); outline-offset: 3px; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
/* Pages appended while scrolling skip it — see appendCards() in app.js. */
.card.is-appended { animation: none; }

.card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.avatar {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; object-fit: cover;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 13px;
}
.who { min-width: 0; }
.name { font-weight: 700; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.meta { font-size: 12px; color: var(--muted); }
/* Sits opposite the name, marking the card as a way out to the post it came
   from rather than the end of the story. */
.card-out {
  margin-left: auto; align-self: flex-start; flex-shrink: 0;
  color: var(--muted); opacity: .7;
  transition: opacity .15s ease, color .15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .card:hover .card-out { color: var(--ink-2); opacity: 1; }
}
.card-title { margin: 0 0 6px; font-size: 14px; font-weight: 700; line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }
.content { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); white-space: pre-line; overflow-wrap: anywhere; }
/* Sits above the link overlay so it takes its own clicks rather than opening
   the post. */
.read-more {
  position: relative; z-index: 1;
  margin-top: 8px; padding: 0; border: none; background: none; cursor: pointer;
  font: 600 13px/1.3 var(--body); color: var(--accent);
}
.read-more:hover { text-decoration: underline; }
.read-more:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px; }

/* Media that came with the post. The box holds its own aspect ratio so a card
   measures the same before and after the image arrives and the masonry pack
   stays honest. Screenshots are cropped from the top: a chat transcript starts
   there. */
.card-media {
  position: relative; display: grid; gap: 2px;
  margin: 10px 0 0; overflow: hidden;
  border-radius: 12px; background: rgba(33,27,23,.05);
}
/* One image keeps its own shape (set from the row, capped at 4:5 in app.js).
   Several share one frame instead — a grid cannot honour three aspect ratios
   at once, and an even card height is worth more than an uncropped edge. */
.media-2, .media-3, .media-4 { aspect-ratio: 3 / 2; }
.media-2 { grid-template-columns: 1fr 1fr; }
/* Three reads as one large beside two stacked, the way the source posts set
   them out. */
.media-3 { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; }
.media-3 .media-cell:first-child { grid-row: span 2; }
.media-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }

.media-cell { position: relative; overflow: hidden; background: rgba(33,27,23,.05); }
/* Anchored top-left, not top-centre: a lone image always fills the width so it
   only ever crops vertically, but a cell in a grid crops sideways too, and
   these are mostly screenshots of text — losing the start of every line is
   worse than losing the right-hand margin. */
.card-media img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: top left;
}
/* A cell whose image is gone keeps its place and its tint rather than showing
   a broken-image glyph. */
.media-cell[data-failed] img { display: none; }

/* Video is shown as its poster frame; the badge marks it and the card opens
   the post, so nothing here plays. */
.media-play {
  position: absolute; inset: 0; margin: auto;
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(20,14,10,.55); box-shadow: 0 2px 12px rgba(0,0,0,.28);
}
.media-play::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 0; height: 0; transform: translateX(2px);
  border-left: 14px solid #fff;
  border-top: 8.5px solid transparent; border-bottom: 8.5px solid transparent;
}
.media-2 .media-play, .media-3 .media-play, .media-4 .media-play {
  width: 32px; height: 32px;
}
.media-2 .media-play::after, .media-3 .media-play::after, .media-4 .media-play::after {
  border-left-width: 10px; border-top-width: 6px; border-bottom-width: 6px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.search { position: relative; z-index: 1; margin: 0 0 16px; }
.search-input {
  width: 100%; min-height: 44px; padding: 12px 42px 12px 16px;
  font: 400 14px/1.3 var(--body); color: var(--ink);
  background: rgba(255,255,255,.72); border: none; border-radius: 14px;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.07);
  transition: box-shadow .2s ease, background .2s ease;
}
.search-input::placeholder { color: var(--muted); }
.search-input:focus {
  outline: none; background: #fff;
  box-shadow: inset 0 0 0 2px var(--ink);
}
.search-input::-webkit-search-cancel-button { display: none; }
.search-clear {
  position: absolute; top: 50%; right: 8px; transform: translateY(-50%);
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; cursor: pointer;
  background: transparent; color: var(--muted); font-size: 22px; line-height: 1;
}
.search-clear[hidden] { display: none; }
.search-clear:hover { color: var(--ink); background: rgba(0,0,0,.06); }
.search-clear:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.status { position: relative; z-index: 1; margin: 0; color: var(--muted); font-size: 14px; }
/* Empty, it leaves the flow (and the view's gap) without leaving the
   accessibility tree, where a live region has to be to be heard. */
.status:empty { position: absolute; }

/* About: alternating collage-and-copy sections, followed by the purpose of
   the collection. Copy keeps a readable size rather than scaling with images. */
#view-about {
  position: relative; z-index: 1;
  width: 100%; max-width: 1040px; gap: 64px;
}
.about-beat { display: grid; gap: 30px; min-width: 0; }
.about-title {
  margin: 0; padding-right: 1em;
  font: 800 clamp(34px, 4vw, 58px)/1.08 var(--display);
  letter-spacing: -.035em; text-wrap: balance;
}
/* The logo's four cards punctuate each rule, keeping its alternating heights. */
.about-divider {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  grid-column: 1 / -1;
}
.about-divider::before, .about-divider::after {
  content: ""; flex: 1; height: 1px; background: rgba(33,27,23,.12);
}
.about-divider::before { margin-right: 12px; }
.about-divider::after { margin-left: 12px; }
.about-divider i { width: 22px; height: 14px; border-radius: 4px; }
.about-divider i:nth-child(1) { background: var(--brand-red); }
.about-divider i:nth-child(2) { height: 9px; background: var(--brand-blue); }
.about-divider i:nth-child(3) { background: var(--brand-yellow); }
.about-divider i:nth-child(4) { height: 9px; background: var(--brand-green); }
.about-question .about-title {
  padding-right: 0; font-size: clamp(30px, 3vw, 42px);
}
.about-row {
  display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr);
  align-items: center; gap: 36px;
}
.about-row-reverse { grid-template-columns: minmax(0, 1fr) minmax(0, 1.65fr); }
.about-figure { margin: 0; min-width: 0; }
.about-figure figcaption {
  margin-top: 12px; color: var(--muted); font-size: 13px; line-height: 1.5;
}
/* <picture> only chooses the file. It lays out as if the img were the figure's
   own child, exactly as before it was wrapped. */
.about-figure picture { display: contents; }
.about-shot {
  display: block; width: 100%; height: auto;
  border-radius: 18px; border: 1px solid rgba(33,27,23,.09);
  background: #fff;
}
.about-copy {
  display: flex; flex-direction: column; align-items: flex-start; gap: 18px;
  min-width: 0; font-size: 17px; line-height: 1.65; color: var(--ink-2);
}
.about-copy p { margin: 0; }
.about-copy .about-lead {
  font: 700 26px/1.22 var(--display); letter-spacing: -.025em; color: var(--ink);
}
.about-copy .about-quote {
  max-width: 12em; margin-bottom: 4px;
  font: 800 34px/1.16 var(--display); letter-spacing: -.025em; color: var(--ink);
}
.about-quote .marker { white-space: nowrap; }
.about-mission {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.65fr);
  gap: 36px 48px;
}
.about-mission-title {
  display: flex; flex-direction: column; align-items: flex-start; gap: 18px;
  margin: 0; font: 600 23px/1.3 var(--display); letter-spacing: -.02em;
}
.about-brand {
  display: inline-flex; align-items: center; gap: 12px;
  font: 800 48px/1 var(--display); letter-spacing: -.04em; white-space: nowrap;
}
.about-logo { width: 44px; height: 44px; flex-shrink: 0; }
.about-invitation { color: var(--ink); font-weight: 500; }
.about-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 16px;
  margin-top: 6px; padding: 15px 20px; border-radius: 12px;
  background: var(--ink); color: #fff; font-size: 15px; font-weight: 600; line-height: 1.3;
  transition: background .15s ease;
}
.about-cta:hover { background: #44382f; }
.about-cta:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

/* Where the stories came from, and how to have one removed. Set quietly and
   last: it is not part of the pitch, but anyone looking for it should find it
   without having to ask. */
.about-provenance {
  max-width: 62ch; margin: 0; padding-top: 28px;
  border-top: 1px solid rgba(33,27,23,.1);
  color: var(--muted); font-size: 13px; line-height: 1.6;
}
.about-provenance a { color: var(--ink-2); text-decoration: underline; text-underline-offset: 2px; }
.about-provenance a:hover { color: var(--ink); }

/* Content stays visible by default. Each element gets one short entrance when
   it reaches the viewport; the motion never changes the page's spacing. */
@media (prefers-reduced-motion: no-preference) {
  .about-title.about-enter,
  .about-mission-title.about-enter,
  .about-copy.about-enter {
    animation: about-copy-in .55s cubic-bezier(.22, 1, .36, 1) backwards;
  }
  .about-figure.about-enter {
    --about-enter-x: -12px;
    animation: about-collage-in .7s cubic-bezier(.22, 1, .36, 1) backwards;
  }
  .about-row-reverse .about-figure.about-enter { --about-enter-x: 12px; }
  .about-divider.about-enter::before,
  .about-divider.about-enter::after {
    animation: about-rule-in .75s cubic-bezier(.22, 1, .36, 1) backwards;
  }
  .about-divider.about-enter::before { transform-origin: right center; }
  .about-divider.about-enter::after { transform-origin: left center; }
  .about-divider.about-enter i {
    animation: about-card-in .6s cubic-bezier(.22, 1, .36, 1) backwards;
  }
  .about-divider.about-enter i:nth-child(2) { animation-delay: .08s; }
  .about-divider.about-enter i:nth-child(3) { animation-delay: .16s; }
  .about-divider.about-enter i:nth-child(4) { animation-delay: .24s; }
  .about-cta { transition: background .15s ease, transform .2s ease, box-shadow .2s ease; }
  .about-cta svg { transition: transform .2s ease; }
  .about-cta:is(:hover, :focus-visible) {
    transform: translateY(-2px); box-shadow: 0 5px 12px rgba(33,27,23,.12);
  }
  .about-cta:is(:hover, :focus-visible) svg { transform: translateX(3px); }
}
@keyframes about-copy-in {
  from { opacity: .6; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
@keyframes about-collage-in {
  from { opacity: .65; transform: translate(var(--about-enter-x), 10px) scale(.988); }
  to { opacity: 1; transform: none; }
}
@keyframes about-rule-in {
  from { opacity: .45; transform: scaleX(.75); }
  to { opacity: 1; transform: none; }
}
@keyframes about-card-in {
  from { opacity: .55; transform: translateY(6px) scale(.85); }
  to { opacity: 1; transform: none; }
}

@media (min-width: 901px) and (max-width: 1150px) {
  .about-row { grid-template-columns: 1fr; gap: 24px; }
  .about-copy { max-width: 640px; }
  .about-mission { grid-template-columns: 1fr; gap: 28px; }
}
@media (max-width: 900px) {
  #view-about { max-width: 640px; margin-inline: auto; gap: 40px; }
  .about-beat { gap: 24px; }
  .about-title { font-size: clamp(30px, 8vw, 42px); padding-right: 0; }
  .about-title .fast { margin-right: 1.1em; }
  .about-row { grid-template-columns: 1fr; gap: 24px; }
  .about-row-reverse .about-figure { order: -1; }
  .about-question .about-title { font-size: clamp(28px, 7.3vw, 36px); }
  .about-shot { border-radius: 14px; }
  .about-figure figcaption { margin-top: 9px; font-size: 12px; }
  .about-copy { gap: 16px; font-size: 16px; line-height: 1.6; }
  .about-copy .about-lead { font-size: clamp(22px, 6vw, 26px); }
  .about-copy .about-quote { font-size: 28px; }
  .about-mission { grid-template-columns: 1fr; gap: 28px; }
  .about-mission-title { font-size: 22px; gap: 14px; }
  .about-brand { font-size: 42px; }
  .about-logo { width: 40px; height: 40px; }
  .about-figure.about-enter,
  .about-row-reverse .about-figure.about-enter { --about-enter-x: 0px; }
}

/* Both flourishes are built from the logo's cards — red, blue, yellow, green,
   alternating tall and short — shrunk to text scale. Sized in em throughout so
   they track the title across its whole 20-62px range. */

/* After "fast": four cards tear past the word, squashed by their own speed.
   Absolutely positioned, so they cost the line no width. The .18em offset
   clears the -.1em the run starts at, so they never flash across the word. */
.streaks { position: absolute; top: 0; bottom: 0; left: 100%; width: 1.5em; margin-left: .18em; pointer-events: none; }
.streaks i { position: absolute; left: 0; width: .34em; border-radius: .04em; animation: whoosh 1.7s ease-in-out infinite; }
.streaks i:nth-child(1) { top: 20%; height: .15em; background: var(--brand-red); animation-delay: 0s; }
.streaks i:nth-child(2) { top: 40%; height: .11em; background: var(--brand-blue); animation-delay: .1s; }
.streaks i:nth-child(3) { top: 58%; height: .15em; background: var(--brand-yellow); animation-delay: .2s; }
.streaks i:nth-child(4) { top: 78%; height: .11em; background: var(--brand-green); animation-delay: .3s; }
@keyframes whoosh {
  0%   { opacity: 0; transform: translateX(-.1em) scaleX(.35); }
  40%  { opacity: 1; transform: translateX(0) scaleX(1); }
  100% { opacity: 0; transform: translateX(.7em) scaleX(.5); }
}

/* After "question": a real ellipsis, in rectangles. This font's period is a
   rounded square of .206 x .181em sitting .013em under the baseline, so these
   are cut just inside it and dropped to the same depth. Each <i> is an empty
   inline-block, whose baseline is its bottom margin edge — that is what puts
   them on the text baseline instead of floating mid-line. */
.think i {
  display: inline-block; vertical-align: baseline;
  width: .18em; height: .16em; border-radius: .04em;
  margin: 0 0 -.013em .06em;
  animation: think-bob 1.5s ease-in-out infinite;
}
.think i:nth-child(1) { background: var(--brand-red); animation-delay: 0s; }
.think i:nth-child(2) { background: var(--brand-blue); animation-delay: .18s; }
.think i:nth-child(3) { background: var(--brand-yellow); animation-delay: .36s; }
@keyframes think-bob {
  0%, 62%, 100% { transform: translateY(0); opacity: .4; }
  30%           { transform: translateY(-.16em); opacity: 1; }
}

/* "fast" leans into the motion. */
.fast { position: relative; display: inline-block; }
.fast-word { display: inline-block; transform: skewX(-8deg); }

@media (max-width: 900px) {
  .app { flex-direction: column; }
  .sidebar {
    position: static; height: auto; width: 100%; flex: 0 0 auto;
    display: grid; grid-template-columns: 1fr auto; align-items: center;
    gap: 6px; z-index: 3;
    border-right: none; border-bottom: 1px solid rgba(0,0,0,.06);
    padding: 8px 16px 12px;
  }
  .sidebar-header { grid-column: 1; grid-row: 1; min-height: 0; }
  .brand, .about-link { display: flex; align-items: center; min-height: 44px; }
  .nav {
    grid-column: 1 / -1; grid-row: 2;
    position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto;
    min-width: 0; min-height: 52px; gap: 8px; align-items: center;
  }
  .nav-group { min-width: 0; }
  #featured-group { flex-direction: row; align-items: center; }
  #tabs {
    flex: 1; min-width: 0; padding: 4px 2px; overflow-x: auto;
    overscroll-behavior-inline: contain; scrollbar-width: none;
  }
  #tabs::-webkit-scrollbar { display: none; }
  .nav-heading { display: none; }
  .nav-more { margin: 0; }
  .nav-summary {
    min-height: 44px; padding: 0 12px; border: 1px solid rgba(33,27,23,.12);
    border-radius: 12px; background: var(--bg); gap: 6px;
  }
  .nav-summary-label { display: none; }
  .nav-summary-short { display: inline; }
  .nav-more[open] .nav-summary { background: var(--ink); color: #fff; }
  .nav-more[open] .nav-caret { color: inherit; }
  .nav-more-content {
    position: absolute; inset: calc(100% + 8px) 0 auto; z-index: 4;
    max-height: min(60vh, 420px); max-height: min(60dvh, 420px); overflow-y: auto;
    overscroll-behavior: contain; padding: 12px; border-radius: 16px;
    background: #fcfbf8; border: 1px solid rgba(33,27,23,.1);
    box-shadow: 0 12px 32px rgba(33,27,23,.16);
  }
  .nav-more-content > .nav-list { margin-top: 0; }
  #tabs-all { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  #tabs-all .tab { white-space: normal; overflow-wrap: anywhere; padding: 12px 10px; height: 100%; }
  #tabs-all .tab-label { min-width: 0; }
  .nav-more-content > .tab-ghost { width: 100%; justify-content: center; }
  .nav-list { flex-direction: row; }
  .tab { width: auto; white-space: nowrap; flex-shrink: 0; border-radius: 12px; }
  #tabs .tab { max-width: 100%; padding-inline: 12px; }
  #tabs .tab-label { overflow: hidden; text-overflow: ellipsis; }
  #featured-group > .tab-ghost { width: 44px; padding: 0; justify-content: center; }
  #featured-group > .tab-ghost .tab-label { display: none; }
  .tab[aria-pressed="true"] { box-shadow: inset 0 1px 0 rgba(255,255,255,.25); }
  .sidebar-foot { grid-column: 2; grid-row: 1; margin-top: 0; }
  .about-link { white-space: nowrap; }
  .main { padding: 28px 20px 48px; }
  [data-view="feed"] .main { padding: 28px 16px 44px; }
  #view-feed { gap: 24px; }
  .hero { font-size: clamp(26px, 6.8vw, 32px); line-height: 1.15; white-space: normal; overflow-wrap: anywhere; text-wrap: balance; }
  .search { margin-bottom: 0; }
  /* Keep mobile input text at 16px so focusing search does not zoom the page. */
  .search-input { font-size: 16px; padding: 13px 48px 13px 14px; }
  .search-clear { width: 44px; height: 44px; right: 2px; }
  .content { font-size: 14px; line-height: 1.55; }
  .read-more { min-height: 44px; margin: 0 0 -8px; padding: 8px 4px 8px 0; }
  .modal { max-height: calc(100dvh - 32px); }
  .modal-card { padding: 22px; }
  .modal-input { font-size: 16px; }
  .btn { min-height: 44px; }
  .modal-actions { flex-wrap: wrap; }
  .modal-note:empty { display: none; }
  .modal-note:not(:empty) { flex: 1 0 100%; }
  /* One painted gradient avoids several large blurred layers on phones. */
  .blobs { background: radial-gradient(ellipse at 0 0, #ff5c610c, transparent 65%), radial-gradient(ellipse at 100% 25%, #3e7bfa0c, transparent 65%), radial-gradient(ellipse at 30% 90%, #21c17c09, transparent 60%); }
  .blob { display: none; }
}
@media (max-width: 420px) {
  .about-cta { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .sidebar, .sidebar-toggle { transition: none; }
  .card, .feed { animation: none; transition: none; }
  .nav-caret { transition: none; }
  .nav-more[open] .nav-more-content { animation: none; }
  .think i { animation: none; }
  .about-cta { transition: none; }
  .streaks { display: none; }
  .fast-word { transform: none; }
}
