/* LonLink Blog */

:root {
  --bg:        #f0f2f5;
  --bg-card:   #ffffff;
  --fg:        #16181d;
  --fg-muted:  #5b6472;
  --border:    #dfe3e8;
  --accent:    #0a58ca;
  --brand:     #76b729;          /* the green from the Lon.TV logo */
  --yt:        #ff0000;
  --shadow:    0 1px 2px rgba(16, 24, 40, .08), 0 1px 3px rgba(16, 24, 40, .06);
  --radius:    12px;
  --maxw:      960px;
  --rail:      212px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:       #0d0f13;
    --bg-card:  #171a21;
    --fg:       #e8eaed;
    --fg-muted: #9aa3b2;
    --border:   #262b35;
    --accent:   #7ab3ff;
    --shadow:   none;
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
}

a { color: var(--accent); }

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 16px;
}

/* ---- header ---- */

.site-header {
  background: var(--bg-card);
  border-bottom: 1px solid var(--border);
  padding: 16px 0;
  margin-bottom: 24px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}

.brand__logo {
  width: 64px;
  height: 64px;
  display: block;
  flex: none;
}

.brand__text { display: flex; flex-direction: column; }

.site-title {
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
}

.site-tagline {
  color: var(--fg-muted);
  font-size: 14.5px;
  line-height: 1.35;
  margin-top: 2px;
}

.site-footer {
  margin-top: 40px;
  padding: 24px 0 40px;
  color: var(--fg-muted);
  font-size: 14px;
  text-align: center;
}

/* ---- two-column shell ---- */

.layout {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: 28px;
  align-items: start;
}

/* ---- left rail ---- */

.rail {
  position: sticky;
  top: 16px;
  /* A sticky rail taller than the viewport strands its own bottom items: page
     scrolling moves the feed, not the rail, so they can never be reached.
     Capping the height lets the rail scroll internally on short windows. */
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.ico { flex: none; display: block; }

.rail__photo {
  display: block;
  /* Full rail width so its edges line up with the YouTube button and the
     socials panel below it. */
  width: 100%;
  /* height:auto is load-bearing: the img's height="300" attribute is a
     presentational hint, and aspect-ratio only fills in a MISSING dimension.
     Without this the hint wins and the photo renders as a tall sliver. */
  height: auto;
  /* Matches the source image's native 240x300, so nothing gets cropped. */
  aspect-ratio: 4 / 5;
  margin: 0 0 14px;
  /* Square, with the same corner softening as the cards next to it. */
  border-radius: 10px;
  object-fit: cover;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}

/* YouTube gets its own full-width button above the rest. */
.rail__yt {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  background: var(--yt);
  color: #fff;
  text-decoration: none;
  font-weight: 700;
  font-size: 14.5px;
  padding: 12px 14px;
  border-radius: 10px;
  margin-bottom: 14px;
  box-shadow: var(--shadow);
  transition: filter .15s ease;
}

.rail__yt:hover { filter: brightness(1.1); }
.rail__yt .ico { width: 22px; height: 22px; }

.rail__socials {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 6px;
  display: flex;
  flex-direction: column;
}

.rail__link {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 10px;
  border-radius: 8px;
  color: var(--fg);
  text-decoration: none;
  font-size: 14.5px;
  line-height: 1.2;
}

.rail__link .ico {
  width: 18px;
  height: 18px;
  color: var(--fg-muted);
  transition: color .15s ease;
}

.rail__link:hover { background: var(--bg); }

/* Brand colour on hover only — a rail of 13 saturated marks is visual noise. */
.rail__link:hover .ico { color: var(--fg); }
.rail__link--youtube:hover  .ico { color: #ff0000; }
.rail__link--amazon:hover   .ico { color: #ff9900; }
.rail__link--tiktok:hover   .ico { color: #ff0050; }
.rail__link--x:hover        .ico { color: #000; }
.rail__link--telegram:hover .ico { color: #26a5e4; }
.rail__link--linkedin:hover .ico { color: #0a66c2; }
.rail__link--facebook:hover .ico { color: #0866ff; }
.rail__link--reddit:hover   .ico { color: #ff4500; }
.rail__link--discord:hover  .ico { color: #5865f2; }
.rail__link--rss:hover      .ico { color: #ff6600; }
.rail__link--blog:hover     .ico { color: var(--brand); }
.rail__link--mail:hover     .ico { color: var(--brand); }
.rail__link--mastodon:hover .ico { color: #6364ff; }
.rail__link--threads:hover  .ico { color: #000; }
.rail__link--bluesky:hover  .ico { color: #0285ff; }

@media (prefers-color-scheme: dark) {
  .rail__link--x:hover .ico,
  .rail__link--threads:hover .ico { color: #fff; }
}

/* ---- cards ----
   Vertical feed post: full-bleed image, then headline, then narrative. */

.feed {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  /* Clips the image to the card's rounded top corners. */
  overflow: hidden;
}

.card__media {
  display: block;
  width: 100%;
  line-height: 0;
}

/* 1.91:1 is the Open Graph standard ratio, so the vast majority of scraped
   thumbnails display uncropped. Fixing the ratio also reserves the space
   before the image loads, which keeps infinite scroll from jumping. */
.card__img,
.card__placeholder {
  width: 100%;
  aspect-ratio: 1.91 / 1;
  object-fit: cover;
  display: block;
  background: var(--border);
}

/* Shown when a source has no usable og:image, or when the hotlink is refused.
   --card-hue is derived server-side from the domain, so a given site always
   gets the same colour. */
.card__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  text-align: center;
  background: linear-gradient(
    135deg,
    hsl(var(--card-hue, 210) 42% 44%),
    hsl(calc(var(--card-hue, 210) + 40) 46% 30%)
  );
  color: #fff;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: .01em;
  word-break: break-word;
}

.card__body { padding: 16px 18px 18px; }

.card__title {
  margin: 0 0 8px;
  font-size: 20px;
  line-height: 1.3;
  letter-spacing: -.015em;
}

.card__title a { color: var(--fg); text-decoration: none; }
.card__title a:hover { color: var(--accent); text-decoration: underline; }

.card__desc { color: var(--fg-muted); font-size: 15.5px; }
.card__desc p { margin: 0 0 8px; }
.card__desc p:last-child { margin-bottom: 0; }
.card__desc a { color: var(--accent); }

.card__meta {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--fg-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.card__domain { font-weight: 600; }
.card__dot { opacity: .5; }

/* Share button sits right-aligned; permalink trails it. */
.card__share {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  padding: 3px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--fg-muted);
  text-decoration: none;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.5;
}

.card__share .ico { width: 13px; height: 13px; }

.card__share:hover {
  color: var(--fg);
  border-color: var(--fg-muted);
  background: var(--bg);
}

.card__perma {
  color: var(--fg-muted);
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.card__perma:hover { color: var(--accent); }

/* ---- tablet: rail collapses to a horizontal icon strip ---- */

@media (max-width: 820px) {
  .layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 18px;
  }

  .rail {
    position: static;
    max-height: none;
    overflow: visible;
  }

  /* Collapsed strip: full width would be enormous, so pin it to the same
     centred column as the button below. */
  .rail__photo {
    width: 120px;
    margin: 0 auto 12px;
  }

  .rail__yt { max-width: 320px; margin-left: auto; margin-right: auto; }

  .rail__socials {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: 2px;
  }

  /* Icons only — the labels don't fit once this is a strip. */
  .rail__link span { display: none; }
  .rail__link { padding: 10px; }
  .rail__link .ico { width: 20px; height: 20px; }
}

/* ---- phone ---- */

@media (max-width: 560px) {
  .wrap { padding: 0 10px; }
  .feed { gap: 14px; }
  .card { border-radius: 10px; }
  .card__body { padding: 14px 15px 16px; }
  .card__title { font-size: 18px; }
  .card__desc { font-size: 15px; }
  .card__placeholder { font-size: 16px; }
  .brand__logo { width: 52px; height: 52px; }
  .site-title { font-size: 21px; }
  .site-tagline { font-size: 13.5px; }
}

/* ---- scroll affordances ---- */

.sentinel {
  min-height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 0;
}

.spinner {
  width: 26px;
  height: 26px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: lb-spin .7s linear infinite;
}

@keyframes lb-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 2s; }
}

.feed-end {
  text-align: center;
  color: var(--fg-muted);
  font-size: 14px;
  padding: 8px 0 32px;
}

.notice {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  color: var(--fg-muted);
  background: var(--bg-card);
}

.notice--error {
  border-color: #d9534f66;
  color: #d9534f;
}

.notice--error button {
  font: inherit;
  cursor: pointer;
  border: 1px solid currentColor;
  background: none;
  color: inherit;
  border-radius: 6px;
  padding: 2px 10px;
  margin-left: 6px;
}
