<script lang="ts" setup>
import fontColorContrast from "font-color-contrast"
import { getHex } from "pastel-color"
import { computed, onMounted, ref } from "vue"
import { useRouter } from "vue-router"

import ProfileModal from "@/components/ProfileModal.vue"
import ThemeSwap from "@/components/ThemeSwap.vue"
import UserPill from "@/components/UserPill.vue"
import { useATProtoLogin } from "@/hooks/useATProtoLogin.hook"
import { useForm } from "@/hooks/useForm.hook"
import { useGitHubLogin } from "@/hooks/useGitHubLogin.hook"
import { usePublicNoteList } from "@/hooks/usePublicNoteList.hook"
import { toShortDid } from "@/modules/atproto/shortDid"
import { useNeedReviewCards } from "@/modules/card/hooks/useNeedReviewCards"
import { useLastVisitedRepos } from "@/modules/history/hooks/useLastVisitedRepos.hook"
import { useFavoriteRepos } from "@/modules/repo/hooks/useFavoriteRepos.hook"
import { slugify } from "@/utils/slugify"

const { username, accessToken } = useGitHubLogin()
const { isLoggedIn: isATProtoLoggedIn, handle } = useATProtoLogin()
const { userInput, repoInput, submit } = useForm()
const { savedFavoriteRepos } = useFavoriteRepos()
const { lastVisitedRepos } = useLastVisitedRepos()
const { cardsToReview } = useNeedReviewCards()
const router = useRouter()

const isGitHubLoggedIn = computed(() => !!accessToken.value)
const isAnyUserLoggedIn = computed(
  () => isGitHubLoggedIn.value || isATProtoLoggedIn.value
)
const displayUsername = computed(() => handle.value || username.value || "")

const openProfile = () => {
  ;(document.getElementById("profile_modal") as HTMLDialogElement)?.showModal()
}

const tileStyle = (seed: string) => {
  const bg = getHex(seed)
  return { backgroundColor: bg, color: fontColorContrast(bg) }
}

const openRepo = (user: string, repo: string) => {
  router.push({ name: "FluxNoteView", params: { user, repo } })
}

const greeting = computed(() => {
  const h = new Date().getHours()
  const name = displayUsername.value
  if (h < 6) return `Still up${name ? ", " + name : ""}?`
  if (h < 12) return `Good morning${name ? ", " + name : ""}.`
  if (h < 18) return `Good afternoon${name ? ", " + name : ""}.`
  return `Good evening${name ? ", " + name : ""}.`
})

const today = computed(() =>
  new Date().toLocaleDateString(undefined, {
    weekday: "long",
    month: "long",
    day: "numeric"
  })
)

const offsetHighlighted = ref(false)
const flashOffset = () => {
  offsetHighlighted.value = true
  setTimeout(() => {
    offsetHighlighted.value = false
  }, 900)
}

const firstHighlighted = ref(false)
const flashFirst = () => {
  firstHighlighted.value = true
  setTimeout(() => {
    firstHighlighted.value = false
  }, 900)
}

const zettelRevealed = ref(false)
const toggleZettel = () => {
  zettelRevealed.value = !zettelRevealed.value
}

const reviewRepo = computed(() => savedFavoriteRepos.value[0] ?? null)
const showReviewCard = computed(
  () => cardsToReview.value.length > 0 && reviewRepo.value !== null
)

const {
  notes: publicNotes,
  isLoading: publicNotesLoading,
  onLoadMore: loadPublicNotes,
  getAuthor: getPublicAuthor
} = usePublicNoteList()
const recentPublicNotes = computed(() => publicNotes.value.slice(0, 5))
const sidebarPublicNotes = computed(() => publicNotes.value.slice(0, 3))
const hasPublicNotes = computed(() => recentPublicNotes.value.length > 0)
const publicNotesLoadFailed = computed(
  () => !publicNotesLoading.value && publicNotes.value.length === 0
)
const formatPublicDate = (iso: string) =>
  new Date(iso).toLocaleDateString(undefined, {
    month: "short",
    day: "numeric"
  })
const publicNoteHandle = (did: string) => {
  const handle = getPublicAuthor(did)
  return handle ? `@${handle}` : toShortDid(did)
}
const publicNoteRoute = (note: { did: string; rkey: string; title: string }) => ({
  name: "PublicNoteView",
  params: {
    shortDid: toShortDid(note.did),
    rkey: note.rkey,
    slug: slugify(note.title)
  }
})

onMounted(() => {
  loadPublicNotes()
})
</script>

<template>
  <div class="welcome-world">
    <!-- ── Top Nav ─────────────────────────────────────────── -->
    <nav class="topnav">
      <div class="topnav-left">
        <router-link :to="{ name: 'Home' }" class="brand">
          <img
            src="/favicon.png"
            alt="Remanso"
            class="brand-mark"
            width="28"
            height="28"
          />
          <span class="brand-word">Remanso</span>
        </router-link>
      </div>
      <div class="topnav-right">
        <a href="#about" class="navlink">About</a>
        <router-link :to="{ name: 'PublicNoteListView' }" class="navlink"
          >Public&nbsp;notes</router-link
        >
        <router-link
          :to="{
            name: 'FluxNoteView',
            params: { user: 'remanso-space', repo: 'getting-started' }
          }"
          class="navlink"
          >Getting&nbsp;started</router-link
        >
        <UserPill @click="openProfile" />
      </div>
    </nav>

    <!-- ── Main content ───────────────────────────────────── -->
    <main>
      <!-- =========== LOGGED-IN: Launchpad ============== -->
      <template v-if="isAnyUserLoggedIn">
        <section class="li-hero">
          <div class="li-hero-inner">
            <div>
              <div class="eyebrow mono">the pool is calm today</div>
              <h1 class="li-h1">{{ greeting }}</h1>
              <p class="li-sub">
                <span class="mono">{{ today }}</span>
                <span class="li-dot">·</span>
                <router-link
                  :to="{ name: 'PublicNoteListView' }"
                  class="li-sub-link"
                  >Public notes</router-link
                >
              </p>
            </div>
            <div class="li-quick">
              <div class="li-quick-label mono">jump to a repo</div>
              <form class="gh-form compact" @submit.prevent="submit">
                <label class="input gh-input-group">
                  <span class="gh-prefix mono">github/</span>
                  <input
                    v-model="userInput"
                    placeholder="user"
                    class="gh-input"
                    spellcheck="false"
                    autocapitalize="off"
                  />
                  <span class="gh-slash">/</span>
                  <input
                    v-model="repoInput"
                    placeholder="repo"
                    class="gh-input"
                    spellcheck="false"
                    autocapitalize="off"
                  />
                </label>
                <button type="submit" class="hw-btn hw-btn-pink gh-go">
                  →
                </button>
              </form>
            </div>
          </div>
        </section>

        <section class="li-main">
          <div class="li-grid">
            <!-- Left: Repos -->
            <div>
              <div class="section-label mono" style="margin-top: 0">
                § your repos
              </div>
              <div
                v-if="savedFavoriteRepos.length"
                class="favs-grid"
                :class="{ 'single-col': savedFavoriteRepos.length === 1 }"
              >
                <a
                  v-for="(repo, i) in savedFavoriteRepos"
                  :key="repo._id"
                  class="repo-tile"
                  :class="{
                    'size-xl': i === 0 && savedFavoriteRepos.length > 1,
                    'size-lg': i > 0 || savedFavoriteRepos.length === 1,
                    featured: i === 0 && savedFavoriteRepos.length > 1
                  }"
                  :style="tileStyle(`${repo.name}-${username}`)"
                  href="#"
                  @click.prevent="openRepo(String(username), repo.name)"
                >
                  <div class="tile-top">
                    <span class="tile-owner mono">{{ username }}/</span>
                    <span class="tile-name">{{ repo.name }}</span>
                  </div>
                </a>
                <router-link
                  :to="{ name: 'RepoList' }"
                  class="add-tile"
                  title="Manage repos"
                >
                  <span class="plus">+</span>
                  <span>manage repos</span>
                </router-link>
              </div>
              <div v-else class="empty-repos">
                <p>No repos saved yet.</p>
                <router-link :to="{ name: 'RepoList' }" class="hw-btn">
                  Add a repo
                </router-link>
                <div class="section-label mono" style="margin-top: 1.5rem">
                  or open one directly
                </div>
                <form class="gh-form" @submit.prevent="submit">
                  <label class="input gh-input-group">
                    <span class="gh-prefix mono">github/</span>
                    <input
                      v-model="userInput"
                      placeholder="user"
                      class="gh-input"
                      spellcheck="false"
                      autocapitalize="off"
                    />
                    <span class="gh-slash">/</span>
                    <input
                      v-model="repoInput"
                      placeholder="repo"
                      class="gh-input"
                      spellcheck="false"
                      autocapitalize="off"
                    />
                  </label>
                  <button type="submit" class="hw-btn hw-btn-pink gh-go">
                    Open →
                  </button>
                </form>
              </div>
            </div>

            <!-- Right: Sidebar -->
            <aside>
              <div
                v-if="lastVisitedRepos.length"
                class="section-label mono"
                style="margin-top: 0"
              >
                § last visited
              </div>
              <ul v-if="lastVisitedRepos.length" class="recent-list">
                <li
                  v-for="repo in lastVisitedRepos.slice(0, 5)"
                  :key="`${repo.user}-${repo.repo}`"
                >
                  <router-link
                    :to="{
                      name: 'FluxNoteView',
                      params: { user: repo.user, repo: repo.repo }
                    }"
                  >
                    <span class="r-path mono"
                      >{{ repo.user }} / {{ repo.repo }}</span
                    >
                  </router-link>
                </li>
              </ul>

              <template v-if="showReviewCard">
                <div class="section-label mono">§ due for review</div>
                <div class="due-card">
                  <div class="due-count">{{ cardsToReview.length }}</div>
                  <div>
                    <div class="due-t">Cards waiting</div>
                    <div class="due-d">Spaced repetition</div>
                  </div>
                  <router-link
                    :to="{
                      name: 'NeedReviewCards',
                      params: {
                        user: username,
                        repo: reviewRepo!.name
                      }
                    }"
                    class="hw-btn hw-btn-pink due-btn"
                  >
                    Review →
                  </router-link>
                </div>
              </template>

              <div class="section-label mono">§ drifting in</div>
              <ul
                v-if="hasPublicNotes"
                class="network-side-list"
              >
                <li
                  v-for="note in sidebarPublicNotes"
                  :key="`${note.did}-${note.rkey}`"
                >
                  <router-link
                    :to="publicNoteRoute(note)"
                    class="network-side-link"
                  >
                    <span class="network-side-title">{{ note.title }}</span>
                    <span class="mono network-side-meta">
                      {{ publicNoteHandle(note.did) }}
                      <span class="li-dot">·</span>
                      {{ formatPublicDate(note.publishedAt) }}
                    </span>
                  </router-link>
                </li>
              </ul>
              <ul
                v-else-if="publicNotesLoading"
                class="network-side-list"
                aria-hidden="true"
              >
                <li v-for="i in 3" :key="i" class="network-side-skel">
                  <span class="skel skel-title" />
                  <span class="skel skel-date" />
                </li>
              </ul>
              <router-link
                :to="{ name: 'PublicNoteListView' }"
                class="network-side-all"
              >
                See all public notes →
              </router-link>
            </aside>
          </div>
        </section>
      </template>

      <!-- =========== Editorial (always visible) ============== -->
      <!-- Hero -->
      <section class="hero-ed">
        <div class="hero-ed-inner">
          <div class="hero-ed-left">
            <div class="eyebrow mono">a quiet place for your notes</div>
            <h1 class="display">
              Remanso is where your<br />
              <em>scattered thinking</em><br />
              comes to rest.
            </h1>
            <p class="lede">
              Point it at any markdown — a GitHub repo of your own, or public
              notes from the open ATProto network — and Remanso turns it into a
              calm, stackable notebook with backlinks where your thinking
              finally runs clear.
            </p>
            <div class="hero-ed-paths">
              <!-- CTA 01: GitHub repo -->
              <div class="hero-ed-path">
                <div class="hep-head">
                  <span class="hep-n mono">01</span>
                  <div>
                    <div class="hep-t">From a GitHub repo</div>
                    <div class="hep-d">
                      Point it at your markdown. Public works instantly, private
                      via OAuth.
                    </div>
                  </div>
                </div>
                <form class="gh-form" @submit.prevent="submit">
                  <label class="input gh-input-group">
                    <span class="gh-prefix mono">github/</span>
                    <input
                      v-model="userInput"
                      placeholder="user"
                      class="gh-input"
                      spellcheck="false"
                      autocapitalize="off"
                    />
                    <span class="gh-slash">/</span>
                    <input
                      v-model="repoInput"
                      placeholder="repo"
                      class="gh-input"
                      spellcheck="false"
                      autocapitalize="off"
                    />
                  </label>
                  <button type="submit" class="hw-btn hw-btn-pink gh-go">
                    →
                  </button>
                </form>
              </div>
              <!-- CTA 02: Public notes (live preview) -->
              <div class="hero-ed-path hero-ed-path-network">
                <div class="hep-head">
                  <span class="hep-n mono">02</span>
                  <div>
                    <div class="hep-t">From the open network</div>
                    <div class="hep-d">
                      Live notes published via ATProto. No account needed —
                      tap one and read.
                    </div>
                  </div>
                </div>
                <div
                  v-if="hasPublicNotes"
                  class="network-strip"
                  role="list"
                >
                  <router-link
                    v-for="note in recentPublicNotes"
                    :key="`${note.did}-${note.rkey}`"
                    :to="publicNoteRoute(note)"
                    class="network-card"
                    role="listitem"
                  >
                    <span class="mono network-card-handle">{{
                      publicNoteHandle(note.did)
                    }}</span>
                    <span class="network-card-title">{{ note.title }}</span>
                    <span class="mono network-card-date">{{
                      formatPublicDate(note.publishedAt)
                    }}</span>
                  </router-link>
                </div>
                <div
                  v-else-if="publicNotesLoading"
                  class="network-strip"
                  aria-hidden="true"
                >
                  <div
                    v-for="i in 3"
                    :key="i"
                    class="network-card network-card--skel"
                  >
                    <span class="skel skel-handle" />
                    <span class="skel skel-title" />
                    <span class="skel skel-date" />
                  </div>
                </div>
                <div v-else-if="publicNotesLoadFailed" class="network-empty">
                  The pool is quiet right now.
                </div>
                <router-link
                  :to="{ name: 'PublicNoteListView' }"
                  class="network-all"
                >
                  Browse all public notes →
                </router-link>
              </div>
            </div>
            <div class="hero-ed-sample mono">
              new here?
              <router-link
                :to="{
                  name: 'FluxNoteView',
                  params: { user: 'remanso-space', repo: 'getting-started' }
                }"
              >
                try remanso-space/getting-started →
              </router-link>
            </div>
          </div>
          <div class="hero-ed-right">
            <div class="flower-stage">
              <img
                src="/favicon.png"
                alt="Remanso"
                class="flower-mark"
                width="240"
                height="240"
              />
              <div class="flower-ripple" />
              <div class="flower-ripple r2" />
            </div>
          </div>
        </div>
      </section>

      <!-- Manifesto -->
      <section class="manifesto" id="about">
        <div class="manifesto-inner">
          <div class="section-label mono">§ 01 — what is remanso</div>
          <p class="drop-cap manifesto-p">
            <em>Remanso</em> is a Portuguese word for the still pool that forms
            where a river slows. The current still moves through — but for a
            moment, it is calm enough to see the bottom. This is what notes
            should feel like. A Remanso takes your markdown files and lays them
            out as a linked notebook you can read, follow, and add to. No
            lock-in. Your notes stay in Git.
          </p>
          <div class="feature-row">
            <div class="feat">
              <span class="feat-icon" aria-hidden="true">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="24"
                  height="24"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <path d="M12 4l-8 4l8 4l8 -4l-8 -4" />
                  <path d="M4 12l8 4l8 -4" />
                  <path d="M4 16l8 4l8 -4" />
                </svg>
              </span>
              <h4>Stacked notes</h4>
              <p>
                Click a link and the next note slides in beside the current one.
                Your train of thought stays visible — never lose where you came
                from.
              </p>
            </div>
            <div class="feat">
              <span class="feat-icon" aria-hidden="true">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="24"
                  height="24"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <path d="M9 14l-4 -4l4 -4" />
                  <path d="M5 10h11a4 4 0 1 1 0 8h-1" />
                </svg>
              </span>
              <h4>Automatic backlinks</h4>
              <p>
                Every mention becomes a two-way link. See every note that points
                back at the one you're reading.
              </p>
            </div>
            <div class="feat">
              <span class="feat-icon" aria-hidden="true">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="24"
                  height="24"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                >
                  <path d="M15 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
                  <path d="M11 8a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
                  <path d="M11 16a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
                  <path d="M12 15v-6" />
                  <path d="M15 11l-2 -2" />
                  <path d="M11 7l-1.9 -1.9" />
                  <path
                    d="M13.446 2.6l7.955 7.954a2.045 2.045 0 0 1 0 2.892l-7.955 7.955a2.045 2.045 0 0 1 -2.892 0l-7.955 -7.955a2.045 2.045 0 0 1 0 -2.892l7.955 -7.955a2.045 2.045 0 0 1 2.892 0"
                  />
                </svg>
              </span>
              <h4>Your files, your Git</h4>
              <p>
                Remanso reads GitHub directly. Edit in your favourite editor.
                Ship to Bluesky via ATProto when you're ready to share.
              </p>
            </div>
          </div>
        </div>
      </section>

      <!-- Demo notes -->
      <section class="demo" id="getting-started">
        <div class="demo-inner">
          <div class="section-label mono">§ 02 — a note, in full</div>
          <h2 class="h2">
            This is what a note looks like.<br />
            <span class="h2-quiet italic">
              Tap a link to stack another beside it.
            </span>
          </h2>
          <div class="demo-notes">
            <article
              class="note-preview"
              :class="{ 'note-preview--flash': firstHighlighted }"
            >
              <div class="note-header">
                <span class="mono note-breadcrumb"
                  >remanso-space / getting-started</span
                >
              </div>
              <h3 class="note-title">On keeping notes</h3>
              <div class="note-body">
                <p>
                  A note should be small enough to hold one idea and
                  <a class="note-link" href="#" @click.prevent="flashOffset"
                    >durable enough</a
                  >
                  to outlive the day it was written.
                </p>
                <p>
                  Luhmann called this the
                  <a class="note-link" href="#" @click.prevent="toggleZettel"
                    >zettelkasten</a
                  >: a slip-box of thoughts you converse with, rather than a
                  hoard of pages you re-read.
                </p>
              </div>
              <div class="note-backlinks">
                <div class="backlinks-h mono">↖ linked from</div>
                <ul>
                  <li>
                    <a @click.prevent href="#"
                      >why links are better than folders</a
                    >
                  </li>
                  <li><a @click.prevent href="#">a reading diary</a></li>
                </ul>
              </div>
            </article>
            <div class="note-stack">
              <article
                class="note-preview note-preview-offset"
                :class="{ 'note-preview--flash': offsetHighlighted }"
              >
                <div class="note-header">
                  <span class="mono note-breadcrumb"
                    >remanso-space / getting-started</span
                  >
                </div>
                <h3 class="note-title">Durable enough</h3>
                <div class="note-body">
                  <p>
                    A durable note survives its own context. You should be able
                    to pick it up six months from now and still know what it
                    means.
                  </p>
                  <p>
                    Rule of thumb: write the title as the claim, and the body as
                    the argument.
                  </p>
                </div>
                <div class="note-backlinks">
                  <div class="backlinks-h mono">↖ linked from</div>
                  <ul>
                    <li>
                      <a @click.prevent="flashFirst" href="#"
                        >on keeping notes</a
                      >
                    </li>
                  </ul>
                </div>
              </article>
              <article
                class="note-preview note-preview-zettel"
                :class="{ 'is-revealed': zettelRevealed }"
                :aria-hidden="!zettelRevealed"
              >
                <div class="note-header">
                  <span class="mono note-breadcrumb"
                    >remanso-space / getting-started</span
                  >
                </div>
                <h3 class="note-title">Zettelkasten</h3>
                <div class="note-body">
                  <p>
                    A <em>slip-box</em> of atomic notes wired together by links
                    instead of filed away in folders. Niklas Luhmann kept ninety
                    thousand of them in a wooden cabinet and wrote with them,
                    not just about them.
                  </p>
                  <p>
                    Each <em>Zettel</em> earns its keep by being linked to. Open
                    one, follow a thread, end up somewhere you didn't plan to
                    go.
                  </p>
                </div>
                <div class="note-backlinks">
                  <div class="backlinks-h mono">↖ linked from</div>
                  <ul>
                    <li><a @click.prevent href="#">on keeping notes</a></li>
                  </ul>
                </div>
              </article>
            </div>
          </div>
        </div>
      </section>

      <!-- Zettelkasten primer -->
      <section class="zk" id="zk">
        <div class="zk-inner">
          <div class="section-label mono">§ 03 — zettelkasten, in a minute</div>
          <ol class="zk-steps">
            <li>
              <span class="zk-n mono">01</span>
              <div>
                <h4>One idea per note.</h4>
                <p>Keep them small. A note that does one thing gets reused.</p>
              </div>
            </li>
            <li>
              <span class="zk-n mono">02</span>
              <div>
                <h4>Link, don't nest.</h4>
                <p>
                  Folders calcify. Links compound. Every
                  <code>[link](note.md)</code> becomes a door to a new idea.
                </p>
              </div>
            </li>
            <li>
              <span class="zk-n mono">03</span>
              <div>
                <h4>Let the web emerge.</h4>
                <p>
                  Don't plan the structure. Write, link, re-read. Structure
                  emerges from what you return to.
                </p>
              </div>
            </li>
          </ol>
        </div>
      </section>
    </main>

    <!-- ── Footer ─────────────────────────────────────────── -->
    <footer class="page-footer">
      <div class="footer-inner">
        <div class="footer-brand">
          <img
            src="/favicon.png"
            alt="Remanso"
            width="32"
            height="32"
            class="footer-mark"
          />
          <div>
            <div class="footer-title">Remanso</div>
            <div class="footer-sub mono">a quiet pool for your notes</div>
          </div>
        </div>
        <div class="footer-cols">
          <div>
            <div class="footer-h">Product</div>
            <router-link
              :to="{
                name: 'FluxNoteView',
                params: { user: 'remanso-space', repo: 'getting-started' }
              }"
              class="footer-link"
              >Getting started</router-link
            >
            <router-link
              :to="{ name: 'PublicNoteListView' }"
              class="footer-link"
              >Public notes</router-link
            >
            <router-link :to="{ name: 'RepoList' }" class="footer-link"
              >Your repos</router-link
            >
          </div>
          <div>
            <div class="footer-h">Learn</div>
            <a href="#about" class="footer-link">What is Remanso?</a>
            <a href="#zk" class="footer-link">Zettelkasten</a>
            <a
              href="https://atproto.com/"
              target="_blank"
              rel="noreferrer"
              class="footer-link"
              >atproto</a
            >
          </div>
        </div>
      </div>
      <div class="footer-fine">
        <theme-swap />
        <span>
          made with <span style="color: var(--hw-pink-deep)">♥</span> by
          <a
            href="https://apoena.dev"
            target="_blank"
            rel="noreferrer"
            class="footer-link"
            >apoena.dev ↗</a
          >
        </span>
      </div>
    </footer>

    <ProfileModal />
  </div>
</template>

<style lang="scss" scoped>
/* ── CSS variables ─────────────────────────────────────────── */
.welcome-world {
  /* Derived from DaisyUI base tokens — adapts to any theme automatically.
     base-100 is the lightest surface; base-200/300 are progressively deeper.
     Paper uses base-200 so cards (base-100) appear slightly elevated above it. */
  --hw-surface: var(--color-base-100);
  --hw-paper: var(--color-base-200);
  --hw-paper-warm: var(--color-base-300);
  --hw-ink: var(--color-base-content);
  --hw-ink-soft: color-mix(
    in oklch,
    var(--color-base-content) 65%,
    var(--color-base-200)
  );
  --hw-ink-faint: color-mix(
    in oklch,
    var(--color-base-content) 38%,
    var(--color-base-200)
  );
  --hw-rule: color-mix(
    in oklch,
    var(--color-base-content) 12%,
    var(--color-base-200)
  );

  /* Brand accent — intentionally fixed, not derived from the active theme */
  --hw-pink: #e36598;
  --hw-pink-deep: color-mix(in oklch, #e36598 75%, var(--color-base-content));
  --hw-pink-wash: color-mix(in oklch, #e36598 12%, var(--color-base-200));
  --hw-pink-wash-2: color-mix(in oklch, #e36598 22%, var(--color-base-200));
  --hw-leaf: #6b8e4e;
  --hw-serif: "Libertinus Serif", "Iowan Old Style", "Palatino", serif;
  --hw-mono: "Courier Prime", "IBM Plex Mono", ui-monospace, monospace;

  font-family: var(--hw-serif);
  background: var(--hw-paper);
  color: var(--hw-ink);
  font-size: 18px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  position: relative;
}

.welcome-world::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(
      circle at 20% 10%,
      rgba(227, 101, 152, 0.04),
      transparent 40%
    ),
    radial-gradient(
      circle at 90% 80%,
      rgba(107, 142, 78, 0.035),
      transparent 45%
    );
}

main {
  position: relative;
  flex: 1;
}

/* ── Shared button system ───────────────────────────────────── */
.hw-btn {
  font-family: var(--hw-serif);
  font-size: 16px;
  padding: 0.55rem 1rem;
  border-radius: 2px;
  border: 1px solid var(--hw-ink);
  background: transparent;
  color: var(--hw-ink);
  cursor: pointer;
  transition:
    background 0.15s,
    color 0.15s,
    transform 0.1s;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;

  &:hover {
    background: var(--hw-ink);
    color: var(--hw-paper);
  }

  &:active {
    transform: translateY(1px);
  }
}

.hw-btn-primary {
  background: var(--hw-ink);
  color: var(--hw-paper);

  &:hover {
    background: var(--hw-pink-deep);
    border-color: var(--hw-pink-deep);
  }
}

.hw-btn-pink {
  background: var(--hw-pink);
  border-color: var(--hw-pink);
  color: #fff;

  &:hover {
    background: var(--hw-pink-deep);
    border-color: var(--hw-pink-deep);
  }
}

/* ── Utility classes ────────────────────────────────────────── */
.mono {
  font-family: var(--hw-mono);
}

.italic {
  font-style: italic;
}

.drop-cap::first-letter {
  font-family: var(--hw-serif);
  float: left;
  font-size: 4.6em;
  line-height: 0.85;
  font-weight: 600;
  margin: 0.1em 0.1em 0 0;
  color: var(--hw-pink-deep);
}

/* ── Top nav ────────────────────────────────────────────────── */
.topnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 2rem;
  border-bottom: 1px solid var(--hw-rule);
  background: var(--hw-paper);
  position: sticky;
  top: 0;
  z-index: 20;
  backdrop-filter: saturate(1.1) blur(6px);
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  text-decoration: none;
  color: var(--hw-ink);
}

.brand-mark {
  display: block;
  object-fit: contain;
  view-transition-name: remanso-logo;
}

.brand-word {
  font-size: 1.25rem;
  letter-spacing: 0.02em;
  font-weight: 600;
}

.topnav-right {
  display: flex;
  align-items: center;
  gap: 1.25rem;
}

.navlink {
  text-decoration: none;
  color: var(--hw-ink-soft);
  font-size: 0.95rem;
  transition: color 0.15s;

  &:hover {
    color: var(--hw-pink-deep);
  }
}

/* ── GitHub form ────────────────────────────────────────────── */
.gh-form {
  display: flex;
  align-items: stretch;

  &.compact {
    .gh-input-group {
      padding: 0.15rem 0.35rem 0.15rem 0.75rem;
    }

    .gh-go {
      padding: 0.3rem 0.7rem;
      font-size: 0.85rem;
    }
  }
}

.gh-input-group {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.35rem 0.45rem 0.35rem 0.9rem;
  background: var(--hw-surface);
  border: 1px solid var(--hw-rule);
  border-right: none;
  border-radius: 999px 0 0 999px;
  box-shadow:
    0 1px 0 rgba(0, 0, 0, 0.02),
    0 6px 18px -10px rgba(201, 74, 125, 0.15);
  cursor: text;
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
  height: auto;
  outline: none;

  &:focus-within {
    border-color: var(--hw-pink);
    box-shadow:
      0 1px 0 rgba(0, 0, 0, 0.02),
      0 10px 28px -10px rgba(201, 74, 125, 0.25);
    outline: none;
  }
}

.gh-prefix {
  color: var(--hw-ink-faint);
  font-size: 0.85rem;
  user-select: none;
}

.gh-slash {
  color: var(--hw-ink-faint);
  font-family: var(--hw-mono);
}

.gh-input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-family: var(--hw-mono);
  font-size: 0.95rem;
  color: var(--hw-ink);
  padding: 0;

  &::placeholder {
    color: var(--hw-ink-faint);
    font-style: italic;
  }
}

.gh-go {
  flex-shrink: 0;
  padding: 0.4rem 0.9rem;
  font-size: 0.9rem;
  border-radius: 0 999px 999px 0;
  align-self: stretch;
  display: flex;
  align-items: center;
}

/* ── Hero (logged out) ──────────────────────────────────────── */
.hero-ed {
  padding: 4.5rem 2rem 3rem;
}

.hero-ed-inner {
  max-width: 1180px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 4rem;
  align-items: center;
}

.eyebrow {
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--hw-pink-deep);
  margin-bottom: 1.5rem;
}

.display {
  font-family: var(--hw-serif);
  font-size: clamp(2.5rem, 5.5vw, 4.6rem);
  line-height: 1.02;
  letter-spacing: -0.01em;
  margin: 0 0 1.75rem;
  font-weight: 600;
  text-wrap: balance;

  em {
    font-style: italic;
    font-weight: 400;
    color: var(--hw-pink-deep);
  }
}

.lede {
  font-size: 1.18rem;
  line-height: 1.55;
  color: var(--hw-ink-soft);
  max-width: 36ch;
  margin: 0 0 2rem;
  text-wrap: pretty;
}

.hero-ed-paths {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: 0.5rem;
}

.hero-ed-path {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 2.25rem 2rem;
  background: var(--hw-surface);
  border: 1px solid var(--hw-rule);
  border-radius: 6px;
  transition:
    border-color 0.15s,
    box-shadow 0.2s,
    transform 0.15s;

  &:hover {
    border-color: var(--hw-pink-wash-2);
    box-shadow: 0 18px 30px -22px rgba(201, 74, 125, 0.18);
    transform: translateY(-1px);
  }
}

.hero-ed-path-network {
  gap: 1.25rem;

  &:hover {
    transform: none;
    border-color: var(--hw-rule);
    box-shadow: none;
  }
}

.network-strip {
  display: flex;
  gap: 0.85rem;
  overflow-x: auto;
  padding: 0.25rem 0.25rem 0.75rem;
  margin: 0 -0.25rem;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;

  &::-webkit-scrollbar {
    height: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background: var(--hw-pink-wash-2);
    border-radius: 999px;
  }
}

.network-card {
  flex: 0 0 220px;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0.9rem 1rem 0.85rem;
  background: var(--hw-paper);
  border: 1px solid var(--hw-rule);
  border-radius: 4px;
  text-decoration: none;
  color: var(--hw-ink);
  position: relative;
  min-height: 130px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.02);
  transition:
    transform 0.15s ease,
    border-color 0.15s ease,
    box-shadow 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    border-color: var(--hw-pink-wash-2);
    box-shadow: 0 14px 24px -18px rgba(201, 74, 125, 0.35);

    .network-card-title {
      color: var(--hw-pink-deep);
    }
  }
}

.network-card-handle {
  font-size: 0.72rem;
  color: var(--hw-ink-faint);
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.network-card-title {
  font-family: var(--hw-serif);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--hw-ink);
  flex: 1;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color 0.15s ease;
}

.network-card-date {
  font-size: 0.7rem;
  color: var(--hw-ink-faint);
  letter-spacing: 0.04em;
  text-transform: lowercase;
  margin-top: auto;
}

.network-card--skel {
  pointer-events: none;
}

.skel {
  display: block;
  border-radius: 3px;
  background: linear-gradient(
    90deg,
    var(--hw-pink-wash) 0%,
    var(--hw-pink-wash-2) 50%,
    var(--hw-pink-wash) 100%
  );
  background-size: 200% 100%;
  animation: skel-shimmer 1.4s ease-in-out infinite;
}

.skel-handle {
  height: 0.6rem;
  width: 60%;
}

.skel-title {
  height: 0.95rem;
  width: 90%;
  margin-top: 0.1rem;
}

.skel-date {
  height: 0.55rem;
  width: 30%;
  margin-top: auto;
}

@keyframes skel-shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

.network-empty {
  font-size: 0.9rem;
  color: var(--hw-ink-faint);
  font-style: italic;
  padding: 0.5rem 0;
}

.network-all {
  align-self: flex-start;
  font-family: var(--hw-mono);
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  color: var(--hw-pink-deep);
  text-decoration: none;
  border-bottom: 1px dashed var(--hw-pink-wash-2);
  padding-bottom: 1px;

  &:hover {
    color: var(--hw-pink-deep);
    border-bottom-color: var(--hw-pink);
  }
}

.hep-head {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
}

.hep-n {
  font-size: 0.85rem;
  letter-spacing: 0.12em;
  color: var(--hw-pink-deep);
  padding-top: 0.35rem;
}

.hep-t {
  font-family: var(--hw-serif);
  font-size: 1.45rem;
  font-weight: 600;
  line-height: 1.2;
  margin-bottom: 0.4rem;
}

.hep-d {
  font-size: 1.05rem;
  color: var(--hw-ink-soft);
  line-height: 1.55;
  text-wrap: pretty;
}

.hep-btn {
  align-self: flex-start;
  padding: 0.65rem 1.25rem;
  font-size: 1.05rem;
}

.hero-ed-sample {
  margin-top: 1.1rem;
  font-size: 0.8rem;
  color: var(--hw-ink-faint);

  a {
    color: var(--hw-ink-soft);
    text-decoration: underline;
    text-decoration-color: var(--hw-rule);

    &:hover {
      color: var(--hw-pink-deep);
    }
  }
}

.hero-ed-left {
  min-width: 0;
}

.hero-ed-right {
  display: flex;
  justify-content: center;
}

.flower-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.flower-mark {
  position: relative;
  z-index: 2;
  display: block;
  object-fit: contain;
}

.flower-ripple {
  position: absolute;
  inset: 10% 10%;
  border: 4px solid var(--hw-pink-wash-2);
  border-radius: 50%;
  animation: ripple 4.5s ease-out infinite;

  &.r2 {
    animation-delay: 1.8s;
  }
}

@keyframes ripple {
  0% {
    transform: scale(0.6);
    opacity: 0;
  }
  30% {
    opacity: 0.6;
  }
  100% {
    transform: scale(1.35);
    opacity: 0;
  }
}

/* ── Manifesto ──────────────────────────────────────────────── */
.manifesto {
  padding: 2rem 2rem 3rem;
  border-top: 1px solid var(--hw-rule);
}

.manifesto-inner {
  max-width: 760px;
  margin: 0 auto;
}

.section-label {
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  color: var(--hw-ink-faint);
  text-transform: lowercase;
  margin: 2.75rem 0 1.5rem;
}

.manifesto-p {
  font-size: 1.25rem;
  line-height: 1.6;
  color: var(--hw-ink);
  text-wrap: pretty;
  margin: 0;

  em {
    font-style: italic;
    color: var(--hw-pink-deep);
  }
}

.feature-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.25rem;
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--hw-rule);
}

.feat {
  h4 {
    font-size: 1.05rem;
    margin: 0.6rem 0 0.35rem;
    font-weight: 600;
  }

  p {
    font-size: 0.95rem;
    color: var(--hw-ink-soft);
    line-height: 1.55;
    margin: 0;
    text-wrap: pretty;
  }
}

.feat-icon {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--hw-pink-deep);
  border: 1px solid var(--hw-pink);
  border-radius: 50%;

  svg {
    width: 16px;
    height: 16px;
  }
}

/* ── Demo notes ─────────────────────────────────────────────── */
.demo {
  padding: 2rem 2rem 4rem;
  background: linear-gradient(
    180deg,
    transparent,
    color-mix(in srgb, var(--hw-pink-wash) 35%, transparent) 40%,
    transparent
  );
}

.demo-inner {
  max-width: 1080px;
  margin: 0 auto;
}

.h2 {
  font-family: var(--hw-serif);
  font-size: clamp(1.8rem, 3.2vw, 2.6rem);
  line-height: 1.15;
  font-weight: 600;
  margin: 0 0 2.5rem;
  letter-spacing: -0.005em;
}

.h2-quiet {
  font-weight: 400;
  color: var(--hw-ink-soft);
}

.demo-notes {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
}

.note-preview {
  background: var(--hw-surface);
  border: 1px solid var(--hw-rule);
  border-radius: 4px;
  padding: 1.5rem 1.75rem 1.25rem;
  box-shadow:
    0 1px 0 rgba(0, 0, 0, 0.02),
    0 20px 40px -25px rgba(0, 0, 0, 0.15);
  max-width: 420px;
  font-size: 0.95rem;
  line-height: 1.6;
}

.note-preview-offset {
  margin-top: 2.5rem;
  transform: rotate(0.4deg);
  transition:
    box-shadow 0.15s ease,
    outline-color 0.15s ease;
  outline: 2px solid transparent;
  outline-offset: 3px;
}

.note-preview--flash {
  animation: note-flash 0.9s ease forwards;
}

.note-stack {
  position: relative;
  display: flex;
  align-items: flex-start;
}

.note-preview-zettel {
  position: absolute;
  inset: 0;
  margin-top: 2.5rem;
  transform: rotate(-0.6deg) translate(0, 0) scale(0.97);
  opacity: 0;
  pointer-events: none;
  z-index: -1;
  transition:
    transform 0.4s cubic-bezier(0.2, 0.7, 0.2, 1),
    opacity 0.3s ease;

  &.is-revealed {
    transform: rotate(-2deg) translate(28px, 28px) scale(0.97);
    opacity: 1;
    pointer-events: auto;
  }
}

@media (max-width: 640px) {
  .note-preview-zettel {
    &.is-revealed {
      transform: rotate(-1.5deg) translate(12px, 22px) scale(0.96);
    }
  }
}

@keyframes note-flash {
  0% {
    box-shadow:
      0 0 0 3px var(--hw-pink-wash-2),
      0 1px 0 rgba(0, 0, 0, 0.02),
      0 20px 40px -25px rgba(0, 0, 0, 0.15);
  }
  25% {
    box-shadow:
      0 0 0 6px var(--hw-pink-wash-2),
      0 1px 0 rgba(0, 0, 0, 0.02),
      0 20px 40px -25px rgba(0, 0, 0, 0.15);
  }
  100% {
    box-shadow:
      0 1px 0 rgba(0, 0, 0, 0.02),
      0 20px 40px -25px rgba(0, 0, 0, 0.15);
  }
}

.note-header {
  margin-bottom: 0.5rem;
}

.note-breadcrumb {
  font-size: 0.72rem;
  color: var(--hw-ink-faint);
  letter-spacing: 0.02em;
}

.note-title {
  font-family: var(--hw-serif);
  font-size: 1.4rem;
  margin: 0.3rem 0 0.8rem;
  font-weight: 600;
  line-height: 1.2;
}

.note-body {
  color: var(--hw-ink-soft);

  p {
    margin: 0 0 0.75rem;

    &:last-child {
      margin-bottom: 0;
    }
  }
}

.note-link {
  color: var(--hw-pink-deep);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
}

.note-backlinks {
  margin-top: 1.2rem;
  padding-top: 0.9rem;
  border-top: 1px dashed var(--hw-rule);

  ul {
    list-style: none;
    padding: 0;
    margin: 0;
  }

  li {
    padding: 0.15rem 0;
  }

  a {
    color: var(--hw-ink-soft);
    text-decoration: none;
    font-size: 0.9rem;
    font-style: italic;

    &:hover {
      color: var(--hw-pink-deep);
    }
  }
}

.backlinks-h {
  font-size: 0.7rem;
  color: var(--hw-ink-faint);
  letter-spacing: 0.1em;
  text-transform: lowercase;
  margin-bottom: 0.4rem;
}

/* ── Zettelkasten section ───────────────────────────────────── */
.zk {
  padding: 2rem 2rem 3rem;
  border-top: 1px solid var(--hw-rule);
}

.zk-inner {
  max-width: 760px;
  margin: 0 auto;
}

.zk-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 1.75rem;

  li {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 1.5rem;
    padding: 1rem 0;
    border-bottom: 1px dashed var(--hw-rule);

    &:last-child {
      border-bottom: 0;
    }
  }

  h4 {
    font-family: var(--hw-serif);
    font-size: 1.3rem;
    margin: 0 0 0.35rem;
    font-weight: 600;
  }

  p {
    margin: 0;
    color: var(--hw-ink-soft);
    font-size: 1rem;
    line-height: 1.55;
  }

  code {
    font-family: var(--hw-mono);
    background: var(--hw-pink-wash);
    color: var(--hw-pink-deep);
    padding: 0.05em 0.35em;
    border-radius: 3px;
    font-size: 0.9em;
  }
}

.zk-n {
  font-size: 0.95rem;
  color: var(--hw-pink-deep);
  letter-spacing: 0.1em;
  padding-top: 0.25rem;
}

img {
  box-shadow: none;
}

/* ── Logged-in hero ─────────────────────────────────────────── */
.li-hero {
  padding: 3rem 2rem 1.5rem;
}

.li-hero-inner {
  max-width: 1180px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 2rem;
  flex-wrap: wrap;
}

.li-h1 {
  font-family: var(--hw-serif);
  font-size: clamp(2rem, 4vw, 3.2rem);
  font-weight: 600;
  margin: 0.5rem 0 0.75rem;
  letter-spacing: -0.005em;
}

.li-sub {
  margin: 0;
  color: var(--hw-ink-soft);
  font-size: 0.95rem;
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  align-items: center;
}

.li-dot {
  color: var(--hw-ink-faint);
}

.li-sub-link {
  color: var(--hw-ink-soft);
  text-decoration: underline;
  text-decoration-color: var(--hw-rule);

  &:hover {
    color: var(--hw-pink-deep);
  }
}

.li-quick {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.4rem;
}

.li-quick-label {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  color: var(--hw-ink-faint);
  text-transform: lowercase;
}

/* ── Logged-in main ─────────────────────────────────────────── */
.li-main {
  padding: 1rem 2rem 3rem;
}

.li-grid {
  max-width: 1180px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 3rem;
}

.favs-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;

  > :first-child.featured {
    grid-column: span 2;
    grid-row: span 2;
  }

  &.single-col {
    grid-template-columns: 1fr 1fr;
  }
}

.repo-tile {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 1rem 1.1rem;
  border-radius: 6px;
  border: 1px solid rgba(0, 0, 0, 0.04);
  transition:
    transform 0.15s ease,
    box-shadow 0.2s ease;
  min-height: 110px;
  position: relative;
  overflow: hidden;
  text-decoration: none;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 20px -10px rgba(0, 0, 0, 0.15);
  }

  &.size-xl {
    min-height: 160px;

    .tile-name {
      font-size: 1.8rem;
    }
  }
}

.tile-top {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.tile-owner {
  font-size: 0.75rem;
  opacity: 0.65;
}

.tile-name {
  font-size: 1.3rem;
  font-weight: 600;
  line-height: 1.1;
}

.add-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  border: 1px dashed var(--hw-rule);
  border-radius: 6px;
  color: var(--hw-ink-faint);
  text-decoration: none;
  min-height: 110px;
  font-size: 0.9rem;
  transition: all 0.15s;
  font-family: var(--hw-serif);

  &:hover {
    border-color: var(--hw-pink);
    color: var(--hw-pink-deep);
    background: var(--hw-pink-wash);
  }
}

.plus {
  font-size: 1.8rem;
  font-weight: 400;
  line-height: 1;
}

.empty-repos {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: flex-start;

  p {
    color: var(--hw-ink-soft);
    margin: 0;
    font-size: 1rem;
  }
}

/* ── Sidebar lists ──────────────────────────────────────────── */
.recent-list {
  list-style: none;
  padding: 0;
  margin: 0;

  li {
    border-bottom: 1px dashed var(--hw-rule);

    &:last-child {
      border-bottom: 0;
    }
  }

  a {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
    padding: 0.7rem 0;
    text-decoration: none;
    color: var(--hw-ink);

    &:hover .r-path {
      color: var(--hw-pink-deep);
    }
  }
}

.r-path {
  font-size: 0.82rem;
  color: var(--hw-ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.due-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 0.9rem;
  align-items: center;
  padding: 1rem 1.1rem;
  background: var(--hw-pink-wash);
  border: 1px solid var(--hw-pink-wash-2);
  border-radius: 6px;
  margin-bottom: 1rem;
}

.due-count {
  font-family: var(--hw-serif);
  font-size: 2.4rem;
  font-weight: 600;
  color: var(--hw-pink-deep);
  line-height: 1;
}

.due-t {
  font-weight: 600;
  font-size: 0.95rem;
}

.due-d {
  font-size: 0.85rem;
  color: var(--hw-ink-soft);
}

.due-btn {
  font-size: 0.85rem;
  padding: 0.35rem 0.8rem;
}

.network-side-list {
  list-style: none;
  padding: 0;
  margin: 0 0 0.75rem;

  li {
    border-bottom: 1px dashed var(--hw-rule);

    &:last-child {
      border-bottom: 0;
    }
  }
}

.network-side-link {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.65rem 0;
  text-decoration: none;
  color: var(--hw-ink);
  transition: color 0.15s ease;

  &:hover {
    .network-side-title {
      color: var(--hw-pink-deep);
    }
  }
}

.network-side-title {
  font-family: var(--hw-serif);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--hw-ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color 0.15s ease;
}

.network-side-meta {
  font-size: 0.72rem;
  color: var(--hw-ink-faint);
  display: flex;
  gap: 0.4rem;
  align-items: center;
  letter-spacing: 0.02em;
}

.network-side-skel {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.65rem 0;
}

.network-side-all {
  display: inline-block;
  margin-top: 0.25rem;
  font-family: var(--hw-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--hw-pink-deep);
  text-decoration: none;
  border-bottom: 1px dashed var(--hw-pink-wash-2);
  padding-bottom: 1px;

  &:hover {
    border-bottom-color: var(--hw-pink);
  }
}

/* ── Footer ─────────────────────────────────────────────────── */
.page-footer {
  border-top: 1px solid var(--hw-rule);
  padding: 3.5rem 2rem 2rem;
  margin-top: 5rem;
  background: linear-gradient(180deg, transparent, var(--hw-paper-warm));
  position: relative;
}

.footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: 3rem;
}

.footer-brand {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.footer-mark {
  display: block;
  object-fit: contain;
}

.footer-title {
  font-size: 1.1rem;
  font-weight: 600;
}

.footer-sub {
  font-size: 0.8rem;
  color: var(--hw-ink-faint);
  letter-spacing: 0.03em;
}

.footer-cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
}

.footer-h {
  font-family: var(--hw-mono);
  text-transform: uppercase;
  font-size: 0.72rem;
  letter-spacing: 0.15em;
  color: var(--hw-ink-faint);
  margin-bottom: 0.75rem;
}

.footer-link {
  display: block;
  text-decoration: none;
  color: var(--hw-ink-soft);
  padding: 0.25rem 0;
  font-size: 0.95rem;

  &:hover {
    color: var(--hw-pink-deep);
  }
}

.footer-fine {
  max-width: 1100px;
  margin: 2.5rem auto 0;
  padding-top: 1.5rem;
  border-top: 1px dashed var(--hw-rule);
  display: flex;
  gap: 0.75rem;
  align-items: center;
  justify-content: center;
  font-family: var(--hw-mono);
  font-size: 0.8rem;
  color: var(--hw-ink-faint);
}

.footer-dot {
  color: var(--hw-ink-faint);
}

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 900px) {
  .hero-ed-inner {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .hero-ed-right {
    order: -1;
  }

  .flower-mark {
    width: 160px;
    height: 160px;
  }

  .feature-row {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }

  .li-grid {
    grid-template-columns: 1fr;
  }

  .favs-grid {
    grid-template-columns: repeat(2, 1fr);

    > :first-child.featured {
      grid-column: span 2;
      grid-row: auto;
    }
  }

  .footer-inner {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .footer-cols {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 640px) {
  .topnav {
    padding: 1rem 1.25rem;
  }

  .navlink {
    display: none;
  }

  .hero-ed {
    padding: 3rem 1.25rem 2rem;
  }

  .li-hero {
    padding: 2rem 1.25rem 1rem;
  }

  .li-hero-inner {
    flex-direction: column;
    align-items: flex-start;
  }

  .li-quick {
    align-items: flex-start;
    width: 100%;
  }

  .li-main,
  .manifesto,
  .demo,
  .zk,
  .page-footer {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }
}

@media (max-width: 520px) {
  .footer-cols {
    grid-template-columns: 1fr 1fr;
  }

  .favs-grid {
    grid-template-columns: 1fr;

    > :first-child.featured {
      grid-column: span 1;
    }
  }
}
</style>
