/* chrome/app.css — the DunceLab app shell (feed + bottom nav + Ask).
   Composes tokens.css only; never hardcode a color/size here. The per-sim chrome lives
   inside each sim iframe (sim-card.css) — this stylesheet owns ONLY the container around them.
   See docs/MODEL.md (the feed = lean-back; the Ask tab = lean-forward). */

@import url("./tokens.css");

:root {
    --nav-h: 58px;
    --sidebar-w: clamp(232px, 18vw, 288px);   /* desktop rail width */
    --feed-max: 880px;                          /* desktop feed "device" column */
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
    background: var(--app-frame);        /* darker than --surface-0 so the phone frame reads */
    color: var(--ink-1);
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
    overscroll-behavior: none;
}

/* Phone-framed app on desktop; full-bleed on a real phone. */
#app {
    height: 100dvh;
    max-width: 520px;
    margin-inline: auto;
    display: flex;
    flex-direction: column;
    background: var(--surface-0);
    position: relative;
    overflow: hidden;
}
@media (min-width: 560px) {
    #app { box-shadow: var(--shadow-3); border-inline: 1px solid var(--border-subtle); }
}

/* The stage holds the stacked views (feed / ask), filling everything above the nav. */
#stage { position: relative; flex: 1 1 auto; min-height: 0; }
.view  { position: absolute; inset: 0; }
/* Hidden must always win, even over ID-level display rules like `#ask { display:flex }` (specificity
   1,0,0 beats 0,2,0). Without !important a hidden view leaks and overlays the active tab. */
.view[hidden] { display: none !important; }

/* ──────────── FEED ──────────────────────────────────────────────────────── */
#feed {
    overflow-y: scroll;
    scroll-snap-type: y mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
#feed::-webkit-scrollbar { display: none; }

.feed-card {
    position: relative;
    height: 100%;
    scroll-snap-align: start;
    scroll-snap-stop: always;
    background: var(--surface-0);
    overflow: hidden;
}

/* Placeholder shown until (and after) an iframe is mounted. */
.feed-card .ph {
    position: absolute; inset: 0; z-index: 1;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: var(--s-2); padding: var(--s-6); text-align: center;
    background: radial-gradient(120% 80% at 50% 35%, var(--surface-2), var(--surface-0) 70%);
}
.feed-card .ph .ph-dot {
    width: 10px; height: 10px; border-radius: var(--r-pill);
    background: var(--brand); box-shadow: var(--glow-brand);
    animation: phpulse 1.4s var(--ease-in-out) infinite;
}
@keyframes phpulse { 0%,100% { opacity: .35; transform: scale(.85); } 50% { opacity: 1; transform: scale(1); } }
.feed-card .ph .ph-name { font-size: var(--fs-lg); font-weight: var(--fw-semibold); color: var(--ink-1); }
.feed-card .ph .ph-blurb { font-size: var(--fs-sm); color: var(--ink-3); max-width: 26ch; }

/* Completion badge on the card placeholder — shown only for cleared concepts. */
.feed-card .ph-done {
    display: none;
    position: absolute; top: calc(var(--s-5) + env(safe-area-inset-top)); left: 50%; transform: translateX(-50%);
    font-size: var(--fs-xs); font-weight: var(--fw-semibold); letter-spacing: var(--ls-caps); text-transform: uppercase;
    color: var(--good); background: rgba(51, 214, 159, .12); border: 1px solid rgba(51, 214, 159, .3);
    padding: 4px var(--s-3); border-radius: var(--r-pill);
}
.feed-card.completed .ph-done { display: inline-flex; }

.feed-card iframe {
    position: absolute; inset: 0; z-index: 2;
    width: 100%; height: 100%; border: 0; display: block;
    background: var(--surface-0);
    opacity: 0; transition: opacity var(--dur-slow) var(--ease-out);
}
.feed-card.on iframe { opacity: 1; }

/* One right-edge nav rail (prev / traverse / explore / next), vertically centered so it sits
   in the canvas band and never overlaps the sim's bottom dock. Replaces the old full-height dot
   column and the bottom-corner chevrons that collided with the dock's sliders + ⋯ FAB. */
.fab-rail {
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    z-index: 4; display: flex; flex-direction: column; align-items: center; gap: var(--s-3);
}

/* Feed-only chrome — shown only on the feed. */
#stage:not([data-view="feed"]) .fab-rail { display: none; }

.chev {
    position: static; flex: 0 0 auto;
    width: 34px; height: 34px; border-radius: var(--r-pill);
    border: 1px solid var(--border-strong); background: var(--surface-glass);
    backdrop-filter: blur(var(--blur-sm)); color: var(--ink-2);
    display: grid; place-items: center; cursor: pointer;
    opacity: .55; transition: opacity var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.chev:hover { opacity: 1; }
.chev svg { width: 16px; height: 16px; }
/* ── Top-right "More" (⋮) menu — the current concept's secondary actions (feed only). Consolidates
   the old right-edge Explore / Related / Share buttons into one tucked-away button + popover. ── */
.fab-more { position: absolute; z-index: 5; top: calc(env(safe-area-inset-top) + var(--s-3)); right: 10px; }
#stage:not([data-view="feed"]) .fab-more { display: none; }
.more-btn {
    width: 38px; height: 38px; border-radius: var(--r-pill);
    border: 1px solid var(--border-strong); background: var(--surface-glass);
    -webkit-backdrop-filter: blur(var(--blur-sm)); backdrop-filter: blur(var(--blur-sm));
    color: var(--ink-1); display: grid; place-items: center; cursor: pointer; box-shadow: var(--shadow-1);
    transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.more-btn:hover { border-color: var(--border-brand); color: var(--brand); }
.more-btn svg { width: 20px; height: 20px; }
.more-menu {
    position: absolute; top: calc(100% + var(--s-2)); right: 0; min-width: 172px;
    display: flex; flex-direction: column; gap: 2px; padding: var(--s-2);
    border-radius: var(--r-lg); border: 1px solid var(--border-strong);
    background: var(--surface-glass-strong);
    -webkit-backdrop-filter: blur(var(--blur-md)); backdrop-filter: blur(var(--blur-md));
    box-shadow: var(--shadow-3);
}
.more-menu[hidden] { display: none; }
.more-item {
    display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
    padding: var(--s-2) var(--s-3); border: 0; border-radius: var(--r-md);
    background: none; color: var(--ink-1); cursor: pointer; font: inherit; font-size: var(--fs-sm);
    transition: background var(--dur-fast) var(--ease-out);
}
.more-item:hover { background: var(--surface-2); }
.more-item svg { width: 18px; height: 18px; flex: 0 0 auto; color: var(--ink-2); }
.more-item:hover svg { color: var(--brand); }

/* ──────────── TRAVERSE SHEET (related concepts) ──────────────────────────── */
#traverse { position: absolute; inset: 0; z-index: 45; }
#traverse[hidden] { display: none; }
.tv-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .5); backdrop-filter: blur(var(--blur-sm)); }
.tv-sheet {
    position: absolute; left: 0; right: 0; bottom: 0;
    background: var(--surface-2); border-top: 1px solid var(--border-strong);
    border-radius: var(--r-xl) var(--r-xl) 0 0; box-shadow: var(--shadow-3);
    padding: var(--s-4) var(--s-5) calc(var(--s-6) + env(safe-area-inset-bottom));
    max-height: 70%; overflow-y: auto;
    animation: tvrise var(--dur-base) var(--ease-out);
}
@keyframes tvrise { from { transform: translateY(100%); } to { transform: translateY(0); } }
.tv-head { display: flex; flex-direction: column; margin-bottom: var(--s-3); }
.tv-kicker { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); }
.tv-title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); color: var(--ink-1); }
.tv-group { margin-top: var(--s-3); }
.tv-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); margin-bottom: var(--s-2); }
.tv-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.tv-chip {
    font-size: var(--fs-sm); color: var(--brand); cursor: pointer;
    padding: 6px var(--s-3); border-radius: var(--r-pill);
    border: 1px solid var(--border-brand); background: var(--brand-soft);
    font-family: var(--font-sans);
}
.tv-chip:hover { background: rgba(var(--brand-rgb), .22); }
.tv-chip.soon { color: var(--ink-3); border-color: var(--border-subtle); background: var(--surface-1); cursor: default; display: inline-flex; align-items: center; gap: 6px; }
.tv-chip.soon i { font-style: normal; font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); border: 1px solid var(--border-subtle); border-radius: var(--r-pill); padding: 1px 5px; }
.tv-empty { color: var(--ink-3); font-size: var(--fs-sm); padding: var(--s-3) 0; }

/* module chips/tags — a system home is not a sim, so flag it distinctly. */
.tv-chip.module { border-color: var(--border-brand); background: var(--brand-soft); color: var(--brand); font-weight: var(--fw-semibold); }
.res .res-tag.module { color: var(--brand); background: var(--brand-soft); }

/* ──────────── MODULE HOME (system-scale entry point — docs/MODEL.md) ────── */
/* ──────────── ENTITY HUB ─────────────────────────────────────────────────
   The universal five-surface node view (docs/MODEL.md). Generalizes the old
   module-home: the Play surface is the members portal at topic scale, a launch-the-sim
   action at leaf scale. Overlay over the stage; full-bleed scrolling sheet. */
/* Above the profile avatar (.dl-you, z-index 60) so opening a node's hub from the map cleanly
   covers the map's top-right tools instead of leaving the avatar floating over it. */
#entity { position: absolute; inset: 0; z-index: 62; background: var(--surface-0); }
#entity[hidden] { display: none; }
.eh-sheet {
    position: absolute; inset: 0; overflow-y: auto;
    padding: calc(var(--s-5) + env(safe-area-inset-top)) var(--s-5) calc(var(--s-6) + env(safe-area-inset-bottom));
    background: radial-gradient(120% 55% at 50% 0%, var(--surface-2), var(--surface-0) 70%);
    animation: ehrise var(--dur-base) var(--ease-out);
}
@keyframes ehrise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.eh-back {
    display: inline-flex; align-items: center; gap: 4px; padding: 0;
    background: none; border: 0; cursor: pointer;
    color: var(--ink-3); font-family: var(--font-sans); font-size: var(--fs-sm);
    transition: color var(--dur-fast) var(--ease-out);
}
.eh-back:hover { color: var(--ink-1); }
.eh-kicker { display: block; margin-top: var(--s-4); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--brand); }
.eh-title { margin: 2px 0 var(--s-2); font-size: var(--fs-2xl); letter-spacing: var(--ls-tight); color: var(--ink-1); }
.eh-lede { margin: 0 0 var(--s-4); font-size: var(--fs-md); line-height: var(--lh-snug); color: var(--ink-2); }

/* The node's ONE distinct takeaway, led front-and-center so every zoom level rewards (CONCEPTUAL-NODE.md). */
.eh-learn {
    margin: 0 0 var(--s-4); padding: var(--s-3); border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--brand) 10%, transparent);
    border-left: 3px solid var(--brand);
    font-size: var(--fs-md); line-height: var(--lh-snug); color: var(--ink-1);
}
.eh-learn b { display: block; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--brand); margin-bottom: 2px; }

/* Tab rail — the five surfaces. Horizontal-scrollable on narrow phones. */
.eh-tabs {
    display: flex; gap: var(--s-1); margin-bottom: var(--s-4);
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    border-bottom: 1px solid var(--border-subtle); padding-bottom: var(--s-2);
}
.eh-tabs::-webkit-scrollbar { display: none; }
.eh-tab {
    flex: 0 0 auto; padding: var(--s-2) var(--s-3); border-radius: var(--r-pill);
    background: none; border: 1px solid transparent; cursor: pointer;
    color: var(--ink-3); font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: var(--fw-medium);
    transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.eh-tab:hover { color: var(--ink-1); }
.eh-tab.active { color: var(--brand); background: var(--brand-soft); border-color: var(--border-brand); }
.eh-body { animation: ehfade var(--dur-fast) var(--ease-out); }
@keyframes ehfade { from { opacity: 0; } to { opacity: 1; } }

.eh-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); margin: var(--s-3) 0 var(--s-2); }
.eh-empty { color: var(--ink-3); font-size: var(--fs-sm); line-height: var(--lh-snug); padding: var(--s-3) 0; }

/* PLAY — leaf launch hero. */
.eh-play-hero {
    display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
    padding: var(--s-4); border-radius: var(--r-lg);
    border: 1px solid var(--border-brand); background: var(--brand-soft);
}
.eh-play-glyph { flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-pill); display: inline-flex; align-items: center; justify-content: center; background: var(--brand); color: var(--ink-inverse); font-size: var(--fs-lg); }
.eh-play-copy { flex: 1 1 160px; min-width: 0; }
.eh-play-name { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink-1); }
.eh-play-blurb { font-size: var(--fs-sm); color: var(--ink-2); line-height: var(--lh-snug); }
.eh-play-btn {
    flex: 0 0 auto; padding: var(--s-2) var(--s-5); border-radius: var(--r-pill);
    background: var(--brand); border: 0; cursor: pointer;
    color: var(--ink-inverse); font-family: var(--font-sans); font-size: var(--fs-md); font-weight: var(--fw-semibold);
    transition: background var(--dur-fast) var(--ease-out);
}
.eh-play-btn:hover { background: var(--brand-hover); }

/* The lesson, embedded in the node's hub — the sim plays here; the hub's Back zooms out to the parent. */
.eh-sim { display: flex; flex-direction: column; gap: var(--s-2); }
.eh-sim-frame {
    width: 100%; height: min(68vh, 600px); border: 0; border-radius: var(--radius-md);
    background: var(--bg-2, #0b1020); display: block;
}
.eh-sim-full {
    align-self: flex-end; padding: var(--s-1) var(--s-3); border-radius: var(--r-pill);
    background: transparent; border: 1px solid var(--border-subtle); cursor: pointer;
    color: var(--ink-2); font-family: var(--font-sans); font-size: var(--fs-sm);
}
.eh-sim-full:hover { color: var(--ink-1); border-color: var(--brand); }

/* THINGS — the real-world entry door: a gallery of real things you zoom into (docs/MODEL.md). */
.things-wrap { max-width: 760px; margin: 0 auto; padding: var(--s-6) var(--s-4) var(--s-8); overflow-y: auto; height: 100%; }
.things-head h1 { font-size: var(--fs-2xl); color: var(--ink-1); margin: 0 0 var(--s-2); letter-spacing: var(--ls-tight); }
.things-head p { font-size: var(--fs-md); color: var(--ink-2); margin: 0 0 var(--s-6); line-height: var(--lh-snug); }
.things-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s-3); }
.thing-card {
    display: flex; flex-direction: column; gap: var(--s-2); text-align: left;
    padding: var(--s-4); border-radius: var(--radius-md); min-height: 120px;
    background: var(--surface-1, var(--bg-2, #131a2e)); border: 1px solid var(--border-subtle);
    cursor: pointer; transition: border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.thing-card:hover { border-color: var(--brand); transform: translateY(-2px); }
.thing-name { font-size: var(--fs-lg); font-weight: var(--fw-semibold); color: var(--ink-1); }
.thing-blurb { font-size: var(--fs-sm); color: var(--ink-2); line-height: var(--lh-snug); }
.thing-parts { margin-top: auto; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--brand); }

/* Object page — plain intro, a tagged "theory" list, and "look inside" (docs/MODEL.md). */
.eh-stem-note { font-size: var(--fs-sm); color: var(--ink-2); margin: 0 0 var(--s-3); line-height: var(--lh-snug); }

.eh-intro { margin: var(--s-2) 0 var(--s-5); display: flex; flex-direction: column; gap: var(--s-3); }
.eh-intro-row { display: flex; flex-direction: column; gap: 2px; }
.eh-intro-k { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--brand); }
.eh-intro-v { font-size: var(--fs-md); color: var(--ink-1); line-height: var(--lh-snug); }

/* ── Its questions — the spine face (docs/CONCEPTUAL-NODE.md §5). Collapsed question rows that
   expand the answer IN PLACE; the answer carries [[thing]] links, a formula chip, and the
   "play with it" door to the shared module. ── */
.eh-questions { margin-top: var(--s-5); }
.eh-q {
    border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
    background: var(--surface-1, var(--bg-2, #131a2e)); margin-bottom: var(--s-2);
    transition: border-color var(--dur-fast) var(--ease-out);
}
.eh-q:hover, .eh-q[open] { border-color: var(--border-brand); }
.eh-q-q {
    display: flex; align-items: center; gap: var(--s-2); padding: var(--s-3);
    cursor: pointer; list-style: none; color: var(--ink-1);
}
.eh-q-q::-webkit-details-marker { display: none; }
.eh-q-level {
    flex: 0 0 auto; font-size: var(--fs-micro); font-weight: var(--fw-semibold);
    text-transform: uppercase; letter-spacing: var(--ls-caps);
    padding: 2px 8px; border-radius: var(--r-pill);
}
.eh-q-level.easy   { background: rgba(63, 185, 80, .16);  color: var(--good, #3fb950); }
.eh-q-level.medium { background: var(--brand-soft);       color: var(--brand); }
.eh-q-level.hard   { background: rgba(255, 123, 92, .16); color: var(--warn, #ff7b5c); }
.eh-q-text { flex: 1 1 auto; font-size: var(--fs-md); font-weight: var(--fw-medium); line-height: var(--lh-snug); }
.eh-q-caret { flex: 0 0 auto; color: var(--ink-3); transition: transform var(--dur-fast) var(--ease-out); }
.eh-q[open] .eh-q-caret { transform: rotate(180deg); }
.eh-q-a { padding: 0 var(--s-3) var(--s-3); display: flex; flex-direction: column; gap: var(--s-2); }
.eh-q-formula {
    align-self: flex-start; font-family: var(--font-mono, ui-monospace, monospace);
    font-size: var(--fs-sm); color: var(--brand);
    padding: 3px 10px; border-radius: var(--r-pill);
    background: var(--brand-soft); border: 1px solid var(--border-brand);
}
.eh-q-body { margin: 0; font-size: var(--fs-md); color: var(--ink-1); line-height: var(--lh-relaxed, 1.55); }
.eh-q-link {
    display: inline; background: none; border: 0; padding: 0; cursor: pointer;
    font: inherit; color: var(--brand); text-decoration: underline;
    text-decoration-color: var(--border-brand); text-underline-offset: 3px;
}
.eh-q-link:hover { color: var(--brand-hover, var(--brand)); text-decoration-color: currentColor; }
.eh-q-play {
    align-self: flex-start; font-family: var(--font-sans); font-size: var(--fs-sm);
    font-weight: var(--fw-semibold); cursor: pointer;
    padding: 7px var(--s-3); border-radius: var(--r-pill);
    border: 1px solid var(--border-brand); background: var(--brand-soft); color: var(--brand);
    transition: background var(--dur-fast) var(--ease-out);
}
.eh-q-play:hover { background: rgba(var(--brand-rgb), .22); }

.eh-theory-sec { margin-top: var(--s-5); }
.eh-theories { display: flex; flex-direction: column; gap: var(--s-2); }
.eh-theory {
    display: flex; align-items: center; gap: var(--s-2); text-align: left; width: 100%;
    padding: var(--s-3); border-radius: var(--radius-md);
    background: var(--surface-1, var(--bg-2, #131a2e)); border: 1px solid var(--border-subtle);
    cursor: pointer; transition: border-color var(--dur-fast) var(--ease-out);
}
.eh-theory:hover:not([disabled]) { border-color: var(--brand); }
.eh-theory[disabled] { opacity: .5; cursor: default; }
.eh-theory.done { border-color: var(--good, #3fb950); }
.eh-ttext { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.eh-tname { font-size: var(--fs-sm); color: var(--ink-1); line-height: var(--lh-snug); }
.eh-tmeta { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.eh-tformula { font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--brand); }
.eh-tag { font-size: var(--fs-xs); color: var(--ink-2); background: var(--surface-2, rgba(255,255,255,.06)); padding: 1px 7px; border-radius: var(--r-pill); }

.eh-look { margin-top: var(--s-5); }

/* "This formula shows up in" — the convergence back-links on a formula node (CONCEPTUAL-NODE.md). */
.eh-usedin { margin-top: var(--s-5); }
.eh-usedin-list { display: flex; flex-direction: column; gap: var(--s-2); }
.eh-usedin-item {
    display: flex; align-items: center; gap: var(--s-2); text-align: left; width: 100%;
    padding: var(--s-3); border-radius: var(--radius-md);
    background: var(--surface-1, var(--bg-2, #131a2e)); border: 1px solid var(--border-subtle);
    cursor: pointer; transition: border-color var(--dur-fast) var(--ease-out);
}
.eh-usedin-item:hover { border-color: var(--brand); }
.eh-usedin-name { flex: 1 1 auto; font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--ink-1); }

/* PLAY — container members portal (the generalized module-home rows). */
.eh-progress { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--good); min-height: 1em; }

/* EXPLORE — the "zoom into a real thing" surface: a labeled visual whose parts are tappable. */
.eh-explore { display: flex; flex-direction: column; gap: var(--s-3); }
.eh-explore-cta { font-size: var(--fs-sm); color: var(--ink-2); text-align: center; }
.eh-drill { display: block; width: 100%; max-width: 340px; height: auto; margin: var(--s-2) auto 0; }
.eh-drill-body { fill: var(--surface-2); stroke: var(--border-strong); stroke-width: 1.5; stroke-linejoin: round; }
.eh-hot { cursor: pointer; }
.eh-hot-zone { fill: rgba(var(--brand-rgb), .10); stroke: var(--border-brand); stroke-width: 1.5; stroke-dasharray: 4 3; transition: fill var(--dur-fast) var(--ease-out), stroke var(--dur-fast) var(--ease-out); }
.eh-hot:hover .eh-hot-zone, .eh-hot:focus-visible .eh-hot-zone { fill: rgba(var(--brand-rgb), .26); stroke: var(--brand); }
.eh-hot-pill { fill: var(--surface-0); stroke: var(--border-brand); stroke-width: 1; }
.eh-hot:hover .eh-hot-pill { stroke: var(--brand); }
.eh-hot-label { fill: var(--brand); font: var(--fw-semibold) .72rem var(--font-sans); }
.eh-hot-check { fill: var(--good); font-size: .8rem; font-weight: 900; }
.eh-hot.done .eh-hot-zone { fill: rgba(51, 214, 159, .14); stroke: rgba(51, 214, 159, .5); stroke-dasharray: none; }

.eh-members { display: flex; flex-direction: column; gap: var(--s-2); }
.eh-member {
    display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
    padding: var(--s-3) var(--s-4); border-radius: var(--r-lg);
    border: 1px solid var(--border-subtle); background: var(--surface-1);
    color: var(--ink-1); cursor: pointer; font-family: var(--font-sans);
    transition: border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.eh-member:hover { border-color: var(--border-brand); transform: translateX(2px); }
.eh-member.soon { cursor: default; opacity: .6; }
.eh-member.soon:hover { transform: none; border-color: var(--border-subtle); }
.eh-check {
    flex: 0 0 auto; width: 20px; height: 20px; border-radius: var(--r-pill);
    border: 1.5px solid var(--border-strong); display: inline-flex; align-items: center; justify-content: center;
    font-size: .7rem; font-weight: 900; color: transparent;
}
.eh-member.done { border-color: rgba(51, 214, 159, .3); }
.eh-member.done .eh-check { background: var(--good); border-color: var(--good); color: var(--ink-inverse); }
.eh-mtext { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.eh-mname { font-size: var(--fs-md); font-weight: var(--fw-semibold); }
.eh-mblurb { font-size: var(--fs-sm); color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eh-arrow { flex: 0 0 auto; color: var(--ink-3); font-size: var(--fs-lg); }
.eh-foot { margin: var(--s-4) 0 0; font-size: var(--fs-sm); color: var(--ink-3); text-align: center; line-height: var(--lh-snug); }

/* TRAVERSE — neighbour chips (each opens its own entity hub). */
.eh-tv-group { margin-bottom: var(--s-3); }
.eh-tv-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.eh-tv-chip {
    padding: var(--s-2) var(--s-3); border-radius: var(--r-pill);
    border: 1px solid var(--border-brand); background: var(--brand-soft);
    color: var(--brand); font-family: var(--font-sans); font-size: var(--fs-sm); cursor: pointer;
    transition: background var(--dur-fast) var(--ease-out);
}
.eh-tv-chip:hover { background: rgba(var(--brand-rgb), .22); }
.eh-tv-chip.module { font-weight: var(--fw-semibold); }
.eh-tv-chip.soon { color: var(--ink-3); border-color: var(--border-subtle); background: var(--surface-1); cursor: default; display: inline-flex; align-items: center; gap: 6px; }
.eh-tv-chip.soon i { font-style: normal; font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); border: 1px solid var(--border-subtle); border-radius: var(--r-pill); padding: 1px 5px; }
/* zoom-out chip + the "show all connections" disclosure (lead-with-3 navigation). */
.eh-tv-chip.zoomout { background: transparent; font-weight: var(--fw-semibold); }
.eh-tv-all { margin-top: var(--s-2); }
.eh-tv-all > summary { cursor: pointer; list-style: none; user-select: none; color: var(--ink-3); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); margin: var(--s-2) 0; }
.eh-tv-all > summary::-webkit-details-marker { display: none; }
.eh-tv-all > summary:hover { color: var(--brand); }
/* "More" tab — Discover + Real-world + Community stacked behind one tab. */
.eh-more-sec { margin-bottom: var(--s-4); }
.eh-more-sec:not(:first-child) { padding-top: var(--s-3); border-top: 1px solid var(--border-subtle); }

/* DISCOVER — explanation + the deferred "why?" tutor placeholder. */
.eh-disc-explain { padding: var(--s-4); border-radius: var(--r-lg); border: 1px solid var(--border-subtle); background: var(--surface-1); }
.eh-disc-blurb { margin: 0; font-size: var(--fs-md); line-height: var(--lh-snug); color: var(--ink-2); }
.eh-disc-why { margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--border-subtle); }
.eh-disc-why-lbl { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); }
.eh-disc-why p { margin: 4px 0 0; font-size: var(--fs-sm); line-height: var(--lh-snug); color: var(--ink-2); }
.eh-tutor { margin-top: var(--s-3); padding: var(--s-4); border-radius: var(--r-lg); border: 1px dashed var(--border-brand); background: var(--brand-soft); }
.eh-tutor-head { display: flex; align-items: center; gap: var(--s-2); }
.eh-tutor-spark { color: var(--brand); }
.eh-tutor-title { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink-1); }
.eh-tutor-copy { margin: var(--s-2) 0 var(--s-3); font-size: var(--fs-sm); line-height: var(--lh-snug); color: var(--ink-2); }
.eh-tutor-btn { padding: var(--s-2) var(--s-4); border-radius: var(--r-pill); border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--ink-3); font-family: var(--font-sans); font-size: var(--fs-sm); cursor: not-allowed; }

/* Shared "coming soon" pill for the deferred surfaces. */
.eh-soon-tag { font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); border: 1px solid var(--border-subtle); border-radius: var(--r-pill); padding: 1px 6px; }
.eh-soon-note { font-size: var(--fs-sm); color: var(--ink-3); line-height: var(--lh-snug); margin-bottom: var(--s-3); }

/* REAL-WORLD — mock Watch / Read / Build. */
.eh-rw-list, .eh-cm-list { display: flex; flex-direction: column; gap: var(--s-2); }
.eh-rw-item { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-lg); border: 1px solid var(--border-subtle); background: var(--surface-1); opacity: .85; }
.eh-rw-glyph { flex: 0 0 auto; font-size: var(--fs-lg); }
.eh-rw-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.eh-rw-h { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink-1); }
.eh-rw-t { font-size: var(--fs-sm); color: var(--ink-3); line-height: var(--lh-snug); }

/* COMMUNITY — mock expert-layer preview. */
.eh-cm-item { display: flex; flex-direction: column; gap: 2px; padding: var(--s-3) var(--s-4); border-radius: var(--r-lg); border: 1px solid var(--border-subtle); background: var(--surface-1); opacity: .85; }
.eh-cm-q { font-size: var(--fs-md); color: var(--ink-1); }
.eh-cm-meta { font-size: var(--fs-xs); color: var(--ink-3); }
.eh-cm-ask { margin-top: var(--s-3); display: inline-flex; align-items: center; gap: var(--s-2); padding: var(--s-2) var(--s-4); border-radius: var(--r-pill); border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--ink-3); font-family: var(--font-sans); font-size: var(--fs-sm); cursor: not-allowed; }

/* ──────────── ASK ───────────────────────────────────────────────────────── */
#ask { display: flex; flex-direction: column; background: var(--surface-0); padding-top: env(safe-area-inset-top); }
.ask-head { padding: var(--s-5) var(--s-5) var(--s-3); }
.ask-head h1 { margin: 0; font-size: var(--fs-2xl); letter-spacing: var(--ls-tight); }
.ask-head p  { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--ink-3); }
.ask-wrap { padding: 0 var(--s-5); }
.ask-input {
    width: 100%; padding: var(--s-3) var(--s-4); border-radius: var(--r-lg);
    border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--ink-1);
    font-size: var(--fs-md); font-family: var(--font-sans); outline: none;
}
.ask-input:focus { border-color: var(--border-brand); box-shadow: var(--focus-ring); }
.ask-input::placeholder { color: var(--ink-3); }

.ask-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); padding: var(--s-3) var(--s-5) 0; }
.ask-chip {
    font-size: var(--fs-sm); color: var(--ink-2); cursor: pointer;
    padding: 5px var(--s-3); border-radius: var(--r-pill);
    border: 1px solid var(--border-subtle); background: var(--surface-1);
}
.ask-chip:hover { border-color: var(--border-brand); color: var(--ink-1); }

.ask-results { flex: 1 1 auto; overflow-y: auto; padding: var(--s-4) var(--s-5) var(--s-6); }
.ask-section-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); margin: var(--s-4) 0 var(--s-2); }

.res {
    display: flex; align-items: center; gap: var(--s-3);
    padding: var(--s-3); margin-bottom: var(--s-2);
    border-radius: var(--r-lg); border: 1px solid var(--border-subtle);
    background: var(--surface-1); cursor: pointer; text-align: left; width: 100%;
    transition: border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.res:hover { border-color: var(--border-brand); transform: translateX(2px); }
.res.soon { cursor: default; opacity: .9; }
.res.soon:hover { transform: none; border-color: var(--border-subtle); }
.res .res-body { flex: 1 1 auto; min-width: 0; }
.res .res-name { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--ink-1); }
.res .res-blurb { font-size: var(--fs-sm); color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res .res-tag { font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--ls-caps); padding: 3px 7px; border-radius: var(--r-pill); }
.res .res-tag.live { color: var(--good); background: rgba(51,214,159,.12); }
.res .res-tag.soon { color: var(--ink-3); background: var(--surface-2); }

.recover { padding: var(--s-2) 0 var(--s-3) var(--s-3); }
.recover .recover-label { font-size: var(--fs-sm); color: var(--ink-3); margin-bottom: var(--s-2); }
.recover .recover-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.recover-chip {
    font-size: var(--fs-sm); color: var(--brand); cursor: pointer;
    padding: 4px var(--s-3); border-radius: var(--r-pill);
    border: 1px solid var(--border-brand); background: var(--brand-soft);
}

.ask-empty { color: var(--ink-3); font-size: var(--fs-sm); padding: var(--s-5) 0; text-align: center; }
.misslog { margin-top: var(--s-6); border-top: 1px solid var(--border-subtle); padding-top: var(--s-3); }
.misslog summary { font-size: var(--fs-sm); color: var(--ink-3); cursor: pointer; }
.misslog ul { margin: var(--s-2) 0 0; padding-left: var(--s-5); color: var(--ink-2); font-size: var(--fs-sm); }

/* ──────────── ONBOARDING (first run) ─────────────────────────────────────── */
#onboarding {
    position: absolute; inset: 0; z-index: 50;
    display: flex; align-items: center; justify-content: center; padding: var(--s-5);
    background: var(--surface-glass-strong); backdrop-filter: blur(var(--blur-lg));
}
#onboarding[hidden] { display: none; }
.ob-card {
    width: 100%; max-width: 360px; text-align: center;
    background: var(--surface-1); border: 1px solid var(--border-strong);
    border-radius: var(--r-xl); box-shadow: var(--shadow-3);
    padding: var(--s-6) var(--s-5);
}
.ob-mark {
    width: 56px; height: 56px; margin: 0 auto var(--s-3);
    display: block; border-radius: var(--r-lg);
    object-fit: cover; box-shadow: var(--glow-brand);
}
.ob-card h2 { margin: 0 0 var(--s-2); font-size: var(--fs-xl); letter-spacing: var(--ls-tight); }
.ob-card p { margin: 0 0 var(--s-4); font-size: var(--fs-md); color: var(--ink-2); line-height: var(--lh-snug); }
.ob-points { list-style: none; margin: 0 0 var(--s-5); padding: 0; text-align: left; display: flex; flex-direction: column; gap: var(--s-2); }
.ob-points li { font-size: var(--fs-sm); color: var(--ink-2); padding-left: var(--s-5); position: relative; }
.ob-points li::before { content: "→"; position: absolute; left: 0; color: var(--brand); font-weight: var(--fw-bold); }
#obStart {
    width: 100%; padding: var(--s-3); border: 0; border-radius: var(--r-lg); cursor: pointer;
    background: var(--brand); color: #fff; font-family: var(--font-sans);
    font-size: var(--fs-md); font-weight: var(--fw-semibold);
    transition: background var(--dur-fast) var(--ease-out);
}
#obStart:hover { background: var(--brand-hover); }

/* ──────────── PROGRESS ──────────────────────────────────────────────────── */
#progress { display: flex; flex-direction: column; background: var(--surface-0); padding-top: env(safe-area-inset-top); }
.pg-head { padding: var(--s-5) var(--s-5) var(--s-3); }
.pg-head h1 { margin: 0; font-size: var(--fs-2xl); letter-spacing: var(--ls-tight); }
.pg-head p { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--ink-3); }
.pg-body { flex: 1 1 auto; overflow-y: auto; padding: 0 var(--s-5) var(--s-6); }

.pg-stats { display: flex; gap: var(--s-3); margin: var(--s-2) 0 var(--s-4); }
.pg-stat {
    flex: 1; text-align: center; padding: var(--s-4) var(--s-2);
    border-radius: var(--r-lg); border: 1px solid var(--border-subtle); background: var(--surface-1);
}
.pg-stat-num { font-size: var(--fs-2xl); font-weight: var(--fw-bold); color: var(--brand); letter-spacing: var(--ls-tight); }
.pg-stat-lbl { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); margin-top: 2px; }

.pg-section-label { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--ink-3); margin: var(--s-4) 0 var(--s-2); }

.pg-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); }
.pg-item {
    display: flex; align-items: center; gap: var(--s-2);
    padding: var(--s-3); border-radius: var(--r-md);
    border: 1px solid var(--border-subtle); background: var(--surface-1);
    color: var(--ink-2); cursor: pointer; text-align: left;
    font-size: var(--fs-sm); transition: border-color var(--dur-fast) var(--ease-out);
}
.pg-item:hover { border-color: var(--border-brand); }
.pg-item .pg-check {
    flex: 0 0 auto; width: 16px; height: 16px; border-radius: 5px;
    border: 1.5px solid var(--border-strong); display: inline-flex; align-items: center; justify-content: center;
    font-size: .65rem; font-weight: 900; color: transparent;
}
.pg-item.done { color: var(--ink-1); border-color: rgba(51, 214, 159, .3); }
.pg-item.done .pg-check { background: var(--good); border-color: var(--good); color: var(--ink-inverse); }
.pg-item .pg-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.pg-misses { margin: var(--s-2) 0 0; padding-left: var(--s-5); color: var(--ink-2); font-size: var(--fs-sm); }
.pg-misses li { margin-bottom: 3px; }

/* Feed-level (tier) filter — School / College / Advanced. A content calibration, no stored grade. */
.pg-tiers { display: flex; gap: var(--s-2); margin: var(--s-2) 0 6px; }
.pg-tier {
    flex: 1 1 0; min-width: 0; padding: var(--s-2) 4px;
    border-radius: var(--r-md); border: 1px solid var(--border-subtle);
    background: var(--surface-1); color: var(--ink-2); cursor: pointer;
    font-size: var(--fs-sm); font-family: var(--font-sans);
    display: flex; align-items: center; justify-content: center; gap: 4px;
    transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.pg-tier:hover { border-color: var(--border-brand); color: var(--ink-1); }
.pg-tier.active { border-color: var(--brand); background: var(--brand-soft); color: var(--ink-1); }
.pg-tier-n { font-size: var(--fs-micro); color: var(--ink-3); font-weight: var(--fw-semibold); }
.pg-tier.active .pg-tier-n { color: var(--brand); }
.pg-tier-note { font-size: var(--fs-xs); color: var(--ink-3); margin: 0 0 var(--s-2); line-height: var(--lh-snug); }

/* Support DunceLab — two Stripe Payment Links (monthly + one-time). Hosted by Stripe; no backend here. */
.pg-support { display: flex; gap: var(--s-2); margin: 6px 0 var(--s-4); flex-wrap: wrap; }
.pg-support-btn {
    flex: 1 1 0; min-width: 140px; padding: var(--s-3) var(--s-3);
    border-radius: var(--r-md); border: 1px solid var(--border-subtle);
    background: var(--surface-1); color: var(--ink-1); cursor: pointer;
    font-size: var(--fs-sm); font-family: var(--font-sans); font-weight: var(--fw-semibold);
    text-align: center; text-decoration: none;
    transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.pg-support-btn:hover { border-color: var(--border-brand); transform: translateY(-1px); }
.pg-support-btn.primary { border-color: var(--brand); background: var(--brand-soft); }

/* ──────────── BOTTOM NAV ─────────────────────────────────────────────────── */
#nav {
    flex: 0 0 auto; height: var(--nav-h);
    padding-bottom: env(safe-area-inset-bottom);
    display: flex; border-top: 1px solid var(--border-subtle);
    background: var(--surface-glass-strong); backdrop-filter: blur(var(--blur-md));
}
#nav button {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    background: none; border: 0; cursor: pointer; color: var(--ink-3);
    font-size: var(--fs-micro); font-family: var(--font-sans); letter-spacing: var(--ls-caps); text-transform: uppercase;
    transition: color var(--dur-fast) var(--ease-out);
}
#nav button svg { width: 22px; height: 22px; }
#nav button.active { color: var(--brand); }

/* ──────────── STAR-MAP PORTAL (the spatial entry surface — docs/MODEL.md) ─────────────────
   Two semantic-zoom levels rendered by chrome/star-map.mjs: topic bubbles → a node constellation.
   Composes tokens only; no new colors. A deep-space gradient sets the "map" mood vs the feed. */
#map {
    display: flex; flex-direction: column; overflow-y: auto;
    padding-top: env(safe-area-inset-top);
    background:
        radial-gradient(80% 50% at 18% 8%, rgba(var(--brand-rgb), .14), transparent 60%),
        radial-gradient(70% 50% at 90% 95%, rgba(91, 192, 235, .08), transparent 60%),
        var(--surface-0);
}
#map[hidden] { display: none; }

/* Scale-transition animation (rule #3: animate, never teleport). Gated off under reduced-motion
   because star-map.mjs simply doesn't add the classes in that case. */
#map.sm-leaving  { opacity: 0; transform: scale(.985); transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out); }
#map.sm-entering { opacity: 0; transform: scale(1.012); }
#map:not(.sm-entering):not(.sm-leaving) { opacity: 1; transform: none; transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out); }

/* Explore is headerless now — just the full-bleed map. The title/breadcrumb/legend were removed;
   only the floating tools (search + random) and the zoom controls sit over the sky. */

/* ── Fixed top-right tools: Search + Random ("surprise me"). ── */
.sm-tools {
    position: absolute; z-index: 5;
    /* Sit below the profile avatar (.dl-you, 44px) so profile → search → random read as one stack. */
    top: calc(env(safe-area-inset-top) + var(--s-4) + 44px + var(--s-2)); right: var(--s-4);
    display: flex; flex-direction: column; gap: var(--s-2);
}
.sm-tool {
    width: 44px; height: 44px; display: grid; place-items: center;
    border-radius: var(--r-pill); cursor: pointer; color: var(--ink-1);
    border: 1px solid var(--border-strong); background: var(--surface-glass-strong);
    -webkit-backdrop-filter: blur(var(--blur-md)); backdrop-filter: blur(var(--blur-md));
    box-shadow: var(--shadow-1);
    transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.sm-tool:hover { border-color: var(--border-brand); color: var(--brand); }
.sm-tool:active { transform: scale(.93); }

/* ── Inline search overlay: covers the frame so a click anywhere outside the card dismisses it. ── */
.sm-search-overlay {
    position: absolute; inset: 0; z-index: 10;
    display: flex; justify-content: flex-end; align-items: flex-start;
    padding: calc(env(safe-area-inset-top) + var(--s-4)) var(--s-4) var(--s-4);
    background: var(--surface-glass);
    -webkit-backdrop-filter: blur(var(--blur-sm)); backdrop-filter: blur(var(--blur-sm));
}
.sm-search-overlay[hidden] { display: none; }
.sm-search-card {
    width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--s-2);
    padding: var(--s-3); border-radius: var(--r-xl);
    border: 1px solid var(--border-strong); background: var(--surface-1); box-shadow: var(--shadow-3);
}
.sm-search-field {
    display: flex; align-items: center; gap: var(--s-2);
    padding: var(--s-2) var(--s-3); border-radius: var(--r-pill);
    border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--ink-3);
}
.sm-search-field:focus-within { border-color: var(--brand); }
.sm-search-input { flex: 1 1 auto; min-width: 0; background: none; border: 0; outline: none;
    color: var(--ink-1); font-family: var(--font-sans); font-size: var(--fs-md); }
.sm-search-input::placeholder { color: var(--ink-3); }
.sm-search-x { flex: 0 0 auto; background: none; border: 0; cursor: pointer; color: var(--ink-3); font-size: var(--fs-md); padding: 2px 4px; line-height: 1; }
.sm-search-x:hover { color: var(--ink-1); }
.sm-search-out { display: flex; flex-direction: column; gap: 4px; max-height: 52vh; overflow-y: auto; }
.sm-search-out:empty { display: none; }
.sm-search-empty { color: var(--ink-3); font-size: var(--fs-sm); padding: var(--s-2) var(--s-1); }
.sm-search-row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
    width: 100%; text-align: left; padding: var(--s-2) var(--s-3);
    border-radius: var(--r-md); border: 1px solid transparent;
    background: var(--surface-1); color: var(--ink-1); cursor: pointer; font: inherit;
    transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.sm-search-row:hover:not(:disabled) { border-color: var(--border-brand); background: var(--surface-2); }
.sm-search-row.soon { opacity: .55; cursor: default; }
.sm-search-row-name { font-weight: var(--fw-semibold); font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sm-search-row-tag { flex: 0 0 auto; font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--ls-caps); padding: 2px 7px; border-radius: var(--r-pill); }
.sm-search-row-tag.live { background: var(--brand-soft); color: var(--brand); }
.sm-search-row-tag.soon { background: var(--surface-2); color: var(--ink-3); }

/* ── The universe: one continuous, pannable, zoomable sky. ── */
.sm-sky {
    position: relative; flex: 1 1 auto; min-height: 0;
    margin: 0; border: 0; border-radius: 0; overflow: hidden;
    background:
        radial-gradient(60% 60% at 50% 45%, rgba(var(--brand-rgb), .08), transparent 70%),
        var(--surface-1);
}

/* ── Shell rings: a thing's boundary, revealed as it opens into its parts (docs/MODEL.md §3).
   Drawn in world coords; the stroke stays hairline-constant across zoom. ── */
/* Intrinsic 2400×2400 size — svg units must map 1:1 onto world px (forcing width/height:100%
   would letterbox-fit the viewBox to the sky and land every ring at the wrong place/scale). */
.sm-rings { position: absolute; left: 0; top: 0; overflow: visible; }
.sm-rings circle {
    fill: rgba(var(--brand-rgb), .05); stroke: rgba(var(--brand-rgb), .5); stroke-width: 1.6;
    vector-effect: non-scaling-stroke; stroke-dasharray: 6 8; opacity: 0;
}

/* ── A thing: dot + name (+ part count on containers). Fused glyph when far, cross-fades away as
   its shell opens. Positioned in world coords; JS counter-scales to a constant screen size. ── */
.sm-thing {
    position: absolute; transform: translate(-50%, -50%);
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    background: none; border: 0; padding: 6px; cursor: pointer; font-family: var(--font-sans);
    color: var(--ink-1); max-width: 128px; will-change: transform, opacity;
}
.sm-thing-dot {
    width: 12px; height: 12px; border-radius: var(--r-pill);
    background: var(--brand); box-shadow: 0 0 0 4px var(--brand-ring);
    transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.sm-thing.shellable .sm-thing-dot {
    width: 18px; height: 18px;
    background: radial-gradient(circle at 38% 32%, var(--brand-hover, var(--brand)), var(--brand) 70%);
    box-shadow: 0 0 0 5px var(--brand-ring), 0 0 22px 2px var(--brand-ring);
}
.sm-thing-label {
    font-size: var(--fs-micro); font-weight: var(--fw-medium); color: var(--ink-2);
    text-align: center; line-height: 1.15; text-shadow: var(--shadow-text);
    max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sm-thing.shellable .sm-thing-label { font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--ink-1); }
.sm-thing-stat {
    font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--ls-caps);
    color: var(--ink-3);
}
.sm-thing:hover .sm-thing-dot { transform: scale(1.25); }
.sm-thing:hover .sm-thing-label { color: var(--ink-1); }
.sm-thing.soon { cursor: default; }
.sm-thing.soon .sm-thing-dot { background: var(--ink-3); box-shadow: none; opacity: .55; }
.sm-thing.soon .sm-thing-label { color: var(--ink-3); opacity: .8; }
/* ambient teaser highlight — a gentle pulse on the spotlighted thing */
.sm-thing.teasing .sm-thing-dot { animation: smpulse 2.4s var(--ease-in-out); }
.sm-thing.teasing .sm-thing-label { color: var(--ink-1); }
@keyframes smpulse { 0%,100% { box-shadow: 0 0 0 4px var(--brand-ring); } 50% { box-shadow: 0 0 0 9px var(--brand-ring); transform: scale(1.3); } }

/* ── Shell label: an opened thing's name pinned to the top of its ring — the tap that opens the
   thing's own page once you're inside it. Counter-scaled like the glyphs. ── */
.sm-shell {
    position: absolute; transform: translate(-50%, -50%);
    padding: 4px var(--s-3); cursor: pointer; font-family: var(--font-sans);
    font-size: var(--fs-xs); font-weight: var(--fw-semibold); white-space: nowrap;
    color: var(--ink-1); border-radius: var(--r-pill);
    border: 1px solid var(--border-strong); background: var(--surface-glass-strong);
    -webkit-backdrop-filter: blur(var(--blur-sm)); backdrop-filter: blur(var(--blur-sm));
    box-shadow: var(--shadow-1); will-change: transform, opacity; opacity: 0;
    transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.sm-shell:hover { border-color: var(--border-brand); color: var(--brand); }

/* ── "You are here" crumb (orientation rule #1): the chain of opened shells around you, and the
   one-tap ▲ back up a level. Floats top-left, above the zoomable sky. ── */
.sm-crumb {
    position: absolute; z-index: 5;
    top: calc(env(safe-area-inset-top) + var(--s-4)); left: var(--s-4);
    display: flex; align-items: center; gap: 6px; max-width: 70%;
    padding: 6px var(--s-3); cursor: pointer; font-family: var(--font-sans);
    font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink-2);
    border-radius: var(--r-pill); border: 1px solid var(--border-strong);
    background: var(--surface-glass-strong);
    -webkit-backdrop-filter: blur(var(--blur-sm)); backdrop-filter: blur(var(--blur-sm));
    box-shadow: var(--shadow-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.sm-crumb:hover { border-color: var(--border-brand); color: var(--ink-1); }
.sm-crumb[hidden] { display: none; }
.sm-crumb-up { color: var(--brand); }
.sm-crumb-sep { color: var(--ink-3); }

.sm-teaser {
    position: absolute; left: 50%; bottom: var(--s-3); transform: translateX(-50%);
    max-width: 85%; padding: 6px var(--s-3); border-radius: var(--r-pill);
    background: var(--surface-glass-strong); backdrop-filter: blur(var(--blur-sm));
    border: 1px solid var(--border-strong); box-shadow: var(--shadow-2);
    font-size: var(--fs-sm); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    opacity: 0; transition: opacity var(--dur-base) var(--ease-out);
}
.sm-teaser b { color: var(--ink-1); font-weight: var(--fw-semibold); }
.sm-teaser.show { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
    #map, #map.sm-leaving, #map.sm-entering { transition: none; transform: none; opacity: 1; }
    .sm-thing.teasing .sm-thing-dot { animation: none; }
}

/* ════════════════════════════════════════════════════════════════════════════
   DESKTOP — sidebar + fluid main content (≥ 900px)
   Below 900px the app is the untouched phone column with a bottom #nav. At ≥900px
   it becomes a true two-pane SPA: a persistent left rail for navigation + identity,
   and a main pane that grows with the window (the brief: "adjustable page size,
   especially on desktop"). Each surface gets a comfortable max width so a wide
   monitor reads as a designed app, not a stretched phone. Motion stays subtle and
   honours prefers-reduced-motion.
   ════════════════════════════════════════════════════════════════════════════ */

#sidebar { display: none; }   /* phones/tablets: the bottom #nav is the navigation */

@media (min-width: 900px) {
    /* App shell → two columns, full-bleed. */
    #app {
        max-width: none;
        display: grid;
        grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
        grid-template-rows: 100%;
        box-shadow: none;
        border-inline: 0;
        overflow: visible;            /* let the rail's floating avatar/menu escape the pane */
    }
    #stage { grid-column: 2; min-width: 0; }
    #nav   { display: none; }         /* the rail replaces the bottom nav */

    /* ── The rail ──────────────────────────────────────────────────────────── */
    #sidebar {
        grid-column: 1; min-width: 0;
        display: flex; flex-direction: column;
        height: 100dvh; min-height: 0; overflow-y: auto;   /* scroll, never clip, on short viewports */
        padding: var(--s-5) var(--s-4) var(--s-4);   /* avatar no longer folds into the foot */
        border-right: 1px solid var(--border-subtle);
        background:
            radial-gradient(120% 30% at 0% 0%, rgba(var(--brand-rgb), .12), transparent 60%),
            linear-gradient(180deg, var(--surface-1), var(--surface-0));
    }

    .dl-side-top { padding: var(--s-2) var(--s-2) var(--s-6); }
    .dl-side-brand {
        display: inline-flex; align-items: center; gap: var(--s-3);
        padding: 4px; margin: 0; background: none; border: 0; cursor: pointer;
        border-radius: var(--r-md); color: var(--ink-1); font-family: var(--font-sans);
        transition: opacity var(--dur-fast) var(--ease-out);
    }
    .dl-side-brand:hover { opacity: .82; }
    .dl-side-mark { width: 30px; height: 30px; filter: drop-shadow(0 0 12px var(--brand-ring)); }
    .dl-side-word { font-size: var(--fs-xl); font-weight: var(--fw-bold); letter-spacing: var(--ls-tight); }
    .dl-side-tag { margin: var(--s-3) 0 0 6px; font-size: var(--fs-sm); color: var(--ink-3); line-height: var(--lh-snug); }
    .dl-side-tag em { color: var(--brand); font-style: normal; }

    /* ── Nav + the sliding "comet" active indicator (the signature element) ─── */
    .dl-side-nav { position: relative; display: flex; flex-direction: column; gap: 2px; }
    .dl-side-indicator {
        position: absolute; left: 0; top: 0; width: 100%; height: 0;
        border-radius: var(--r-md); background: var(--brand-soft);
        box-shadow: inset 3px 0 0 var(--brand);
        opacity: 0; pointer-events: none;
        transition: transform var(--dur-base) var(--ease-spring),
                    height var(--dur-base) var(--ease-spring),
                    opacity var(--dur-fast) var(--ease-out);
    }
    .dl-side-nav button {
        position: relative; z-index: 1;
        display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
        padding: var(--s-3); background: none; border: 0; border-radius: var(--r-md); cursor: pointer;
        color: var(--ink-2); font-family: var(--font-sans); font-size: var(--fs-md); font-weight: var(--fw-medium);
        transition: color var(--dur-fast) var(--ease-out);
    }
    .dl-side-nav button svg { width: 20px; height: 20px; flex: 0 0 auto; }
    .dl-side-nav button:hover { color: var(--ink-1); }
    .dl-side-nav button.active { color: var(--brand); font-weight: var(--fw-semibold); }

    /* ── Foot: Support CTA (the avatar floats in via platform.css) ─────────── */
    .dl-side-foot { margin-top: auto; padding: 0 var(--s-2); }
    .dl-side-support {
        display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
        width: 100%; padding: var(--s-3); border-radius: var(--r-md);
        border: 1px solid var(--border-brand); background: var(--brand-soft);
        color: var(--brand); font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: var(--fw-semibold);
        cursor: pointer; transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
    }
    .dl-side-support:hover { background: rgba(var(--brand-rgb), .22); transform: translateY(-1px); }

    /* Light/dark toggle — quieter than Support; sits just below it. */
    .dl-side-theme {
        display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
        width: 100%; margin-top: var(--s-2); padding: var(--s-2) var(--s-3); border-radius: var(--r-md);
        border: 1px solid var(--border-subtle); background: var(--surface-2);
        color: var(--ink-2); font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: var(--fw-medium);
        cursor: pointer; transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
    }
    .dl-side-theme:hover { background: var(--surface-3); color: var(--ink-1); border-color: var(--border-brand); }
    .dl-side-theme .dl-theme-ic { font-size: 1.05em; line-height: 1; }

    /* ── Main pane: a comfortable max width per surface ────────────────────── */
    /* Feed: a centered "device" column, framed by hairlines, instead of stretching. */
    #feed { background: radial-gradient(80% 60% at 50% -5%, rgba(var(--brand-rgb), .055), transparent 60%); }
    .feed-card {
        width: min(100%, var(--feed-max)); margin-inline: auto;
        border-inline: 1px solid var(--border-subtle);
    }
    /* The right-edge rail + top-right More menu hug the feed column, not the far screen edge. */
    .fab-rail, .fab-more { right: max(var(--s-3), calc((100% - var(--feed-max)) / 2 + var(--s-2))); }

    /* Search + entity hub: cap line length, center via auto side padding.
       (Profile/.dl-set-wrap already centers at 560px; Map fills the pane.)
       #ask-scoped so this beats platform.css's .dl-search-* padding shorthand,
       which loads after app.css and would otherwise win the inline padding. */
    #ask .dl-search-head, #ask .dl-search-results { padding-inline: max(var(--s-5), calc((100% - 760px) / 2)); }
    .eh-sheet { padding-inline: max(var(--s-5), calc((100% - 820px) / 2)); }

    /* ── View transitions — a quiet cross-fade on the lean-forward surfaces ─── */
    #ask:not([hidden]), #profile:not([hidden]) { animation: dl-view-in var(--dur-base) var(--ease-out); }
    @keyframes dl-view-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

    /* Brand mark gently floats (echoes the landing page); quality-floor focus ring. */
    @media (prefers-reduced-motion: no-preference) {
        .dl-side-mark { animation: dl-side-float 7s var(--ease-in-out) infinite; }
        @keyframes dl-side-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
    }
    #sidebar button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
}

@media (min-width: 900px) and (prefers-reduced-motion: reduce) {
    .dl-side-indicator { transition: opacity var(--dur-fast) linear; }
    #ask:not([hidden]), #profile:not([hidden]) { animation: none; }
}
