/* ── skeet grep ─────────────────────────────────────────────────────────────
   A child page of fubarchitect.com. Every colour, timing and rule comes from
   theme.css; nothing here invents a palette. The house style is: one ground
   colour with no card surfaces, hairline rules doing all the separating, gold
   for accent only, radii of 2-4px, and no shadows.

   Two departures, both deliberate:

   1. The type is Inter, not Source Serif 4. Inter is what Bluesky renders posts
      in, and these ARE Bluesky posts -- setting them in someone else's face
      makes them read as quotations rather than as the thing itself. webb's DM
      Mono stays for every label, readout and control, which is what carries the
      family resemblance.
   2. html font-size is NOT pinned to 16px the way webb pins it. This page is
      sized in rem throughout so that a reader who has raised their browser's
      default font size actually gets larger text -- and ui/post.js measures the
      result rather than assuming it.                                        */

:root {
  /* Inter is Bluesky's typeface. --font-mono is webb's, inherited untouched. */
  --font-ui: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --fs-name:  clamp(1.35rem, 1.2rem + .7vw, 1.9rem);
  --fs-body:  clamp(0.9rem, 0.85rem + 0.2vw, 1rem);
  --fs-label: clamp(0.68rem, 0.64rem + 0.15vw, 0.76rem);
  --fs-post:  clamp(0.95rem, 0.9rem + 0.25vw, 1.05rem);

  --measure: 78ch;
  --gutter: clamp(1.5rem, 4vw, 4rem);
  /* The post column. Bluesky's feed is ~600px; without a cap the text runs to
     an unreadable measure and a single image renders a metre across. In ch, so
     it tracks the reader's font size instead of fighting it. */
  --col-max: 62ch;
}

html {
  /* Not a pinned 16px: whatever the reader has chosen is the base. */
  font-size: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-ui);
  font-optical-sizing: auto;
  color: var(--text);
  background: var(--ground);
  line-height: 1.5;
  height: 100dvh;
  overflow: hidden;
  display: grid;
  /* #app is display:contents, so the flow-level grid items are breadcrumb,
     masthead, sources, work, footer -- five, not four. Only the work area
     takes the slack; everything else is intrinsic.

     minmax(0, 1fr), never a bare 1fr: a grid track's implied minimum is
     `auto`, i.e. its content's height. The scroller's content is the whole
     result set, so a bare 1fr lets the track grow to fit 4000 posts, which
     makes scroll.clientHeight the height of the entire list -- and ui/vlist.js
     sizes its window from clientHeight, so it dutifully mounts every row and
     the virtualization silently stops existing. */
  grid-template-rows: auto auto auto minmax(0, 1fr) auto;
  padding-inline: var(--gutter);
  transition: background var(--duration) var(--ease);
}

/* webb's fixed off-centre wash, behind everything. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(ellipse 50% 70% at 5% 40%, var(--glow), transparent);
}

.controls {
  position: fixed; top: 1.5rem; right: var(--gutter); z-index: 10;
  display: flex; align-items: center; gap: .75rem;
}
.controls input[type=range] {
  -webkit-appearance: none; appearance: none;
  width: 4rem; height: 1px; background: var(--rule); outline: none; cursor: pointer;
}
.controls input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: .5rem; height: .5rem;
  border-radius: 50%; background: var(--gold); border: none;
}
.controls input[type=range]::-moz-range-thumb {
  width: .5rem; height: .5rem; border-radius: 50%; background: var(--gold); border: none;
}

.breadcrumb {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text-2); letter-spacing: .06em;
  padding-top: clamp(2rem, 6vh, 4rem);
}
.breadcrumb a { color: var(--text-2); text-decoration: none; transition: color var(--duration) var(--ease) }
.breadcrumb a:hover { color: var(--gold) }
.breadcrumb span { color: var(--text) }

a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 1px solid var(--gold); outline-offset: 3px;
}

/* ── masthead ────────────────────────────────────────────────────────── */
#app { display: contents }

/* One band: title, lede and sign-in on a single baseline. The page does not
   scroll, so chrome height comes straight out of the results viewport. */
.masthead {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .4rem .9rem;
  padding-block: clamp(.9rem, 2.5vh, 1.6rem) clamp(.7rem, 2vh, 1.1rem);
}
.masthead h1 {
  font-family: var(--font-ui); font-size: var(--fs-name);
  font-weight: 700; line-height: 1; letter-spacing: -.035em;
}
.masthead .lede {
  font-size: var(--fs-body); font-weight: 300; color: var(--text-2);
}
.meta-line {
  font-family: var(--font-mono); font-size: var(--fs-label);
  font-weight: 300; letter-spacing: .08em; color: var(--text-2);
}
.linkish {
  font: inherit; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--gold); text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: .18em;
  transition: color var(--duration) var(--ease);
}
.linkish:hover { color: var(--gold-bright) }

/* ── sources ─────────────────────────────────────────────────────────
   A row of mono links, not a sidebar: webb has no sidebar on any page. The
   selected one is marked by the same gold underline the site uses on hover. */
.sources {
  display: flex; flex-wrap: wrap; gap: 0 clamp(.9rem, 2vw, 1.6rem);
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  padding-block: .55rem;
}
.source {
  position: relative; background: none; border: 0; padding: .35rem 0; cursor: pointer;
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  letter-spacing: .06em; color: var(--text-2);
  transition: color var(--duration) var(--ease);
}
.source::after {
  content: ''; position: absolute; left: 0; bottom: 0; width: 0; height: 1px;
  background: var(--gold); transition: width .5s var(--ease-out);
}
.source:hover:not(:disabled) { color: var(--text) }
.source:hover:not(:disabled)::after { width: 100% }
.source[aria-selected=true] { color: var(--gold) }
.source[aria-selected=true]::after { width: 100% }
.source:disabled { opacity: .35; cursor: not-allowed }
.source small {
  font-size: .82em; margin-left: .4em; color: var(--text-2); opacity: .7;
}

/* ── work area ───────────────────────────────────────────────────────── */
.work {
  display: grid; grid-template-rows: auto auto minmax(0, 1fr) auto;
  min-height: 0; min-width: 0;
}

.query {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: .75rem 1.1rem; padding-block: 1.1rem;
  border-bottom: 1px solid var(--rule);
}
.hint {
  flex-basis: 100%; font-family: var(--font-mono); font-size: var(--fs-label);
  font-weight: 300; color: var(--text-2); letter-spacing: .04em;
}
.field { display: flex; flex-direction: column; gap: .25rem; min-width: 0; position: relative }
.field > label {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  letter-spacing: .06em; color: var(--text-2);
}
.field.grow { flex: 1 1 18rem }
.field.num { width: 7rem }
.query-actions { display: flex; gap: .5rem; margin-left: auto; align-items: flex-end }

input[type=text], input[type=number], input[type=password], select {
  width: 100%; min-width: 0;
  font-family: var(--font-ui); font-size: var(--fs-body);
  color: var(--text); background: var(--ground);
  border: 1px solid var(--rule); border-radius: 2px;
  padding: .45rem .6rem; outline: none;
  transition: border-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease);
}
input:focus, select:focus { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold) }
input[type=number] { font-family: var(--font-mono); font-variant-numeric: tabular-nums }
.check { flex-direction: row; align-items: center; gap: .45rem; padding-bottom: .4rem }
.check input { accent-color: var(--gold); width: .85rem; height: .85rem }
.check label { letter-spacing: .04em }

.btn {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 400;
  letter-spacing: .08em; color: var(--ground); background: var(--gold);
  border: none; border-radius: 2px; padding: .5rem 1.4rem; cursor: pointer;
  transition: background var(--duration) var(--ease);
}
.btn:hover { background: var(--gold-bright) }
.btn.ghost { background: none; border: 1px solid var(--rule); color: var(--text-2) }
.btn.ghost:hover { background: none; border-color: var(--gold); color: var(--gold) }
.btn:disabled { opacity: .38; cursor: default; background: none;
                border: 1px solid var(--rule); color: var(--text-2) }

/* ── handle autocomplete ─────────────────────────────────────────────
   The one place this page floats anything. webb has no popovers, so the menu
   borrows the vocabulary it does have: a hairline box on the ground colour,
   gold for the active row, no shadow and no radius beyond the 2px inputs use. */
.ta-menu {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 20;
  margin-top: 2px; max-height: 17rem; overflow-y: auto;
  background: var(--ground); border: 1px solid var(--rule); border-radius: 2px;
}
.ta-menu[hidden] { display: none }
.ta-row {
  display: flex; align-items: center; gap: .5rem; cursor: pointer;
  padding: .35rem .5rem; border-bottom: 1px solid var(--rule);
}
.ta-row:last-child { border-bottom: 0 }
.ta-row.on { background: color-mix(in oklch, var(--ground), var(--gold) 14%) }
.ta-av {
  width: 1.35rem; height: 1.35rem; border-radius: 50%; flex: none; object-fit: cover;
  background: color-mix(in oklch, var(--ground), var(--text) 8%);
}
.ta-text { min-width: 0; display: flex; align-items: baseline; gap: .45rem }
.ta-handle {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text); white-space: nowrap;
}
/* The typed run is what explains the match, so it is the only thing emphasised. */
.ta-handle b { font-weight: 500; color: var(--gold) }
.ta-name {
  font-size: var(--fs-label); color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.ta-name b { font-weight: 600; color: var(--text) }

/* ── grep bar ────────────────────────────────────────────────────────── */
.seek {
  display: flex; align-items: center; gap: .75rem;
  padding-block: .9rem; border-bottom: 1px solid var(--rule);
}
.seek-wrap { position: relative; flex: 1 }
.seek-wrap::before {
  content: '/'; position: absolute; left: .6rem; top: 50%; transform: translateY(-50%);
  font-family: var(--font-mono); color: var(--gold); pointer-events: none;
}
#seek { padding-left: 1.6rem; font-size: var(--fs-post) }
#seek::placeholder { color: var(--text-2); opacity: .8 }
.seek select { width: auto; font-family: var(--font-mono); font-size: var(--fs-label) }

.help-btn {
  flex: none; width: 1.7rem; height: 1.7rem; border-radius: 50%; cursor: pointer;
  background: none; border: 1px solid var(--rule); color: var(--text-2);
  font-family: var(--font-mono); font-size: var(--fs-label); line-height: 1;
  transition: color var(--duration) var(--ease), border-color var(--duration) var(--ease);
}
.help-btn:hover { color: var(--gold); border-color: var(--gold) }

/* ── query-syntax help ───────────────────────────────────────────────── */
dialog.help { width: min(58rem, 94vw); max-height: 88dvh; overflow-y: auto; padding: 1.3rem 1.5rem }
.help-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem }
.help-head h2 { margin-bottom: 0 }
.help-cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: 0 2.4rem; margin-top: .4rem;
}
dialog.help h3 {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 400;
  letter-spacing: .12em; text-transform: uppercase; color: var(--text-2);
  margin: 1.1rem 0 .35rem; padding-bottom: .28rem; border-bottom: 1px solid var(--rule);
}
.help-tbl { width: 100%; border-collapse: collapse }
.help-tbl td { padding: .28rem .6rem .28rem 0; vertical-align: baseline }
.help-tbl td:first-child { width: 1%; white-space: nowrap }
.help-tbl td:last-child { font-size: var(--fs-body); color: var(--text-2); line-height: 1.45 }
dialog.help code {
  font-family: var(--font-mono); font-size: var(--fs-label); color: var(--text);
  background: color-mix(in oklch, var(--ground), var(--text) 6%);
  border-radius: 3px; padding: .12em .35em; white-space: nowrap;
}
.help-tbl td:first-child code { color: var(--gold) }
.help-note {
  font-size: var(--fs-body); color: var(--text-2); line-height: 1.55;
  margin: .55rem 0 0; max-width: 46ch;
}
.help-eg { margin-top: .2rem }
.help-keys {
  display: flex; flex-wrap: wrap; gap: 1.2rem; margin-top: 1.5rem;
  padding-top: .8rem; border-top: 1px solid var(--rule);
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text-2); letter-spacing: .04em;
}
.help-keys kbd {
  font-family: var(--font-mono); font-size: inherit; color: var(--text);
  background: color-mix(in oklch, var(--ground), var(--text) 6%);
  border: 1px solid var(--rule); border-radius: 3px; padding: .1em .4em; margin-right: .3em;
}

/* ── results ─────────────────────────────────────────────────────────── */
/* overflow-anchor: none is load-bearing, not a tweak. Chrome's native scroll
   anchoring rewrites scrollTop whenever content above its chosen anchor node
   resizes -- and ui/vlist.js resizes the spacers on every frame. Left enabled,
   it fights the list's own anchoring and the scroll position snaps around. */
.scroll { overflow-y: auto; position: relative; min-height: 0; overflow-anchor: none }
.scroll > *, .vwin > * { overflow-anchor: none }
.vwin { display: flow-root }
.vspace { width: 100% }

/* ── post row ────────────────────────────────────────────────────────
   webb separates list items with a hairline rule and no card, and wipes a gold
   rule in from the left on hover. Same here. Rows stay variable-height (see
   ui/vlist.js) so embeds render at their true size.                        */
.row {
  position: relative; cursor: pointer;
  padding-block: .9rem; border-bottom: 1px solid var(--rule);
  display: grid; grid-template-columns: 2.4rem 1fr; gap: .7rem;
  transition: opacity var(--duration) var(--ease);
}
.row::after {
  content: ''; position: absolute; left: 0; bottom: 0; width: 0; height: 1px;
  background: var(--gold); transition: width .5s var(--ease-out);
}
.row:hover::after { width: 100% }
.row:hover .who { color: var(--gold) }

.col { min-width: 0; max-width: var(--col-max) }

.av {
  width: 2.4rem; height: 2.4rem; border-radius: 50%;
  background: color-mix(in oklch, var(--ground), var(--text) 8%);
  border: 1px solid var(--rule); object-fit: cover;
}

.rp {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text-2); margin-bottom: .15rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.meta { display: flex; align-items: baseline; gap: .35rem; min-width: 0 }
.who {
  font-size: var(--fs-post); font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 46%;
  transition: color var(--duration) var(--ease);
}
.at, .dot, .when {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text-2);
}
.at { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0 }
.dot, .when { flex: none }

.body {
  font-size: var(--fs-post); line-height: 1.5; color: var(--text); margin-top: .1rem;
  /* Post text is preformatted: Bluesky renders it pre-wrap, and ~1 in 3 posts
     contains a newline that otherwise collapses into a space. */
  white-space: pre-wrap; word-break: break-word; overflow-wrap: break-word;
}

/* rich-text facets: mentions, links, hashtags */
.fx { color: var(--gold); text-decoration: none }
.fx:hover { color: var(--gold-bright); text-decoration: underline;
            text-underline-offset: .18em; text-decoration-thickness: 1px }

mark {
  background: color-mix(in oklch, var(--ground), var(--gold) 28%);
  color: var(--text); border-radius: 2px; padding: 0 .1em;
}

/* Hovering one row dims the rest -- webb's :has() trick, applied to the feed. */
.vwin:has(.row:hover) .row:not(:hover) { opacity: .45 }

/* ── embeds ──────────────────────────────────────────────────────────── */
.emb {
  display: block; margin-top: .5rem; border-radius: 4px; overflow: hidden;
  border: 1px solid var(--rule); text-decoration: none; color: inherit;
  transition: border-color var(--duration) var(--ease);
}
.emb:hover { border-color: var(--gold) }
.emb-stack > .emb:first-child { margin-top: .5rem }

.emb-img { border: 0 }
.emb-img.one img { display: block; width: 100%; max-height: 32rem;
                   object-fit: cover; border-radius: 4px }
.emb-img.grid { display: grid; gap: 2px; border-radius: 4px }
.emb-img.grid img { width: 100%; height: 100%; object-fit: cover; display: block }
.emb-img.grid.n2 { grid-template-columns: 1fr 1fr; aspect-ratio: 2/1 }
.emb-img.grid.n3 { grid-template-columns: 1fr 1fr; aspect-ratio: 3/2 }
.emb-img.grid.n3 img:first-child { grid-row: span 2 }
.emb-img.grid.n4 { grid-template-columns: 1fr 1fr; aspect-ratio: 3/2 }

.emb-img.video { position: relative }
.emb-img.video .play {
  position: absolute; inset: 50% auto auto 50%; transform: translate(-50%,-50%);
  width: 2.6rem; height: 2.6rem; border-radius: 50%; display: grid; place-items: center;
  background: color-mix(in oklch, var(--ground) 70%, transparent);
  color: var(--text); padding-left: 2px; backdrop-filter: blur(2px);
}

.emb-ext { display: flex; align-items: stretch;
           background: color-mix(in oklch, var(--ground), var(--text) 4%) }
.ext-thumb { flex: none; width: 5.4rem }
.ext-thumb img { width: 100%; height: 100%; object-fit: cover; display: block }
.ext-meta { padding: .55rem .7rem; min-width: 0; display: flex; flex-direction: column; gap: .1rem }
.ext-host {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text-2); letter-spacing: .04em;
}
.ext-title { font-size: var(--fs-body); font-weight: 600; color: var(--text);
             overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2 }
.ext-desc { font-size: var(--fs-body); color: var(--text-2);
            overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2 }

.emb-quote { display: block; padding: .55rem .7rem;
             background: color-mix(in oklch, var(--ground), var(--text) 4%) }
.emb-quote.missing { color: var(--text-2); font-family: var(--font-mono); font-size: var(--fs-label) }
.q-head { display: flex; align-items: center; gap: .35rem; margin-bottom: .2rem; min-width: 0 }
.q-av { width: 1.05rem; height: 1.05rem; border-radius: 50%; flex: none; object-fit: cover;
        background: color-mix(in oklch, var(--ground), var(--text) 8%) }
.q-name { font-size: var(--fs-body); font-weight: 600; color: var(--text); white-space: nowrap }
.q-handle { font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
            color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.q-text { font-size: var(--fs-body); color: var(--text-2); white-space: pre-wrap;
          word-break: break-word; overflow: hidden;
          display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4 }

/* ── counts ──────────────────────────────────────────────────────────── */
.tags {
  display: flex; gap: 1.2rem; margin-top: .45rem; align-items: center;
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text-2); font-variant-numeric: tabular-nums;
}
.tags b { font-weight: 400 }
.tags .zero { opacity: .5 }
.tags .flag { margin-left: auto; letter-spacing: .06em; opacity: .6 }

.empty {
  padding-block: clamp(3rem, 12vh, 7rem); text-align: center; color: var(--text-2);
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  line-height: 1.8;
}
.empty kbd {
  font-family: var(--font-mono); font-size: inherit;
  background: color-mix(in oklch, var(--ground), var(--text) 6%);
  border: 1px solid var(--rule); border-radius: 3px; padding: .15em .4em; color: var(--text);
}

/* ── status readout ──────────────────────────────────────────────────── */
.status {
  display: flex; align-items: center; flex-wrap: wrap;
  border-top: 1px solid var(--rule); padding-block: .55rem;
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  letter-spacing: .06em; color: var(--text-2);
}
.stat { display: flex; align-items: center; gap: .4rem; padding-right: 1.4rem; white-space: nowrap }
.stat b { font-weight: 400; color: var(--text); font-variant-numeric: tabular-nums }
.stat.hi b { color: var(--gold) }
.stat.warn b { color: var(--gold-bright) }
.stat.ok { opacity: .55 }
.spacer { flex: 1 }

.bar { position: relative; width: 5.6rem; height: 2px; overflow: hidden;
       background: var(--rule); border-radius: 1px }
.bar i { position: absolute; inset: 0 auto 0 0; background: var(--gold); transition: width .2s }
.bar.indet i { width: 34% !important; animation: slide 1.1s ease-in-out infinite }
@keyframes slide { 0% { left: -34% } 100% { left: 100% } }

/* ── footer ──────────────────────────────────────────────────────────── */
footer { padding-block: .9rem 0; border-top: 1px solid var(--rule) }
.footer-row { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem }
footer p {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 300;
  color: var(--text-2); letter-spacing: .06em; opacity: .5;
}

/* ── sign-in dialog ──────────────────────────────────────────────────── */
dialog {
  /* theme.css resets `* { margin: 0 }`, which also clears the UA's
     `dialog { margin: auto }` -- without this every modal opens in the
     top-left corner instead of centred. */
  margin: auto;
  background: var(--ground); color: var(--text);
  border: 1px solid var(--rule); border-radius: 4px;
  padding: 1.5rem; width: min(26rem, 92vw);
}
dialog::backdrop { background: color-mix(in oklch, var(--ground) 75%, transparent) }
dialog h2 {
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: 400;
  letter-spacing: .12em; color: var(--gold); margin-bottom: 1rem;
}
dialog p { font-size: var(--fs-body); color: var(--text-2); line-height: 1.6; margin: .7rem 0 }
dialog .field { margin-bottom: .8rem }
dialog .actions { display: flex; gap: .5rem; justify-content: flex-end; margin-top: 1.2rem }
.err { color: var(--gold-bright); font-family: var(--font-mono); font-size: var(--fs-label); margin-top: .5rem }

@media (max-width: 34rem) {
  .query-actions { margin-left: 0; width: 100% }
  .controls { top: .8rem }
}
