/* ==========================================================================
   theme-zhihu — breakpoints.
   ≥1024 three-part shell, 901–1023 single column with drawer, ≤900 drawer,
   ≤768 mobile feed + bottom tab bar.
   ========================================================================== */

@media (max-width: 1279px) {
  .topbar__search {
    flex: none;
    width: 34px;
    height: 34px;
    padding: 0;
    justify-content: center;
    border-radius: 50%;
  }

  .topbar__search-label,
  .topbar__search-kbd {
    display: none;
  }
}

@media (max-width: 1023px) {
  :root {
    --container: 720px;
  }

  /* The search button is a sibling of .topbar__actions rather than a child, so
     the bar's own gap has to match the actions gap or search reads as an
     outlier pushed away from the rest of the row. */
  .topbar__inner {
    gap: 4px;
  }

  .sidebar {
    display: none;
  }

  .topnav {
    display: none;
  }

  .nav-toggle {
    display: inline-flex;
  }
}

@media (max-width: 768px) {
  :root {
    --gutter: 0px;
  }

  /* A short page (the gallery, an empty archive) stopped well above the bottom
     of the viewport, while the tab bar is fixed to that bottom: the copyright
     kept 22px from the card above it and 52 from the bar below, so it read as
     hanging in mid-air. Filling the viewport puts the footer's bottom edge on
     the reserve's top edge, which is exactly where the bar starts, so the only
     air under the copyright is its own 12px — the same number a scrolled page
     gives at the end of the scroll. */
  body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
  }

  .shell {
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
  }

  .site-footer {
    margin-top: auto;
  }

  body.has-tabbar {
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  }

  .topbar__inner {
    gap: 2px;
    height: var(--topbar-h);
    padding: 0 12px;
  }

  .brand__name {
    max-width: 120px;
    font-size: 16px;
  }

  .brand__logo,
  .brand__mark {
    width: 28px;
    height: 28px;
    font-size: 16px;
  }

  .topbar__search {
    flex: none;
    width: 34px;
    height: 34px;
    margin-left: auto;
    padding: 0;
    justify-content: center;
    border-radius: 50%;
    background: transparent;
    color: var(--muted-strong);
    transition: background-color 0.15s ease, color 0.15s ease;
  }

  .topbar__search:hover {
    background: var(--surface-3);
    color: var(--text);
  }

  /* Bare at rest like the neighbouring icon buttons, but it answers the pointer
     with the same tonal circle they use, glass on or off. */
  html[data-glass="on"] .topbar__search {
    background: transparent;
  }

  html[data-glass="on"] .topbar__search:hover {
    background: var(--surface-3);
  }

  .topbar__search .icon {
    font-size: 18px;
  }

  .topbar__search-label,
  .topbar__search-kbd {
    display: none;
  }

  .topbar__create {
    display: none;
  }

  .topbar__actions {
    gap: 2px;
  }

  .theme-toggle {
    display: inline-flex;
  }

  /* full-bleed cards */
  .shell__inner {
    display: block;
    padding: 8px 0 0;
    /* The shell is a column flex container now (see the footer fill above),
       which puts margin: 0 auto on the cross axis — auto margins there absorb
       the free space and the box collapses to its max-content width. A definite
       width keeps it full-bleed, and max-width still centres it on a tablet. */
    width: 100%;
  }

  .page-head,
  .feed-head,
  .post-card,
  .moment-card,
  .moment-detail,
  .article,
  .archive,
  .term-cloud,
  .category-tree,
  .author-card,
  .douban-page,
  .bangumi-page,
  .equipment-group,
  .filter-card,
  .empty-state,
  .error-page {
    border-radius: 0;
    box-shadow: none;
  }

  .page-head {
    padding: 18px 16px;
    margin-bottom: 8px;
  }

  .page-head__title {
    font-size: 21px;
  }

  /* 手机同样钉在页头右上角；标题按工具宽度让位。 */
  .page-head__tools {
    top: 18px;
    right: 16px;
  }

  .page-head__left {
    top: 18px;
    left: 16px;
  }

  .page-head:has(.page-head__left) {
    padding-top: 60px;
  }

  .page-head:has(.page-head__tools) {
    --tools-reserve: 112px;
  }

  .page-head--home:has(.page-head__tools) {
    --tools-reserve: 224px;
  }

  /* The drawing app paints nothing of its own outside the shadow tree, so the
     card it stands on is the theme's job; on the phone that card joins the
     full-bleed rest and keeps the 16px inset the other blocks use, which is
     also what lines the app's own tabs up with the page head above it. */
  body.page-drawing .drawing-stage {
    margin-bottom: 8px;
    padding: 16px;
    border-radius: 0;
    box-shadow: none;
  }

  .feed-head {
    padding: 0;
    margin-bottom: 8px;
  }

  .feed-tabs {
    --cap-gap: 2px;
  }

  .feed-tab {
    padding: 0 14px;
    font-size: 13px;
  }

  /* 手机页头内边距 18px 16px；描述在上、胶囊 tab 在下，左缩进与描述一致。 */
  .feed-head--inline {
    height: auto;
    margin: 6px 0 0;
    padding: 0;
  }

  .feed-head--inline .feed-tabs {
    height: auto;
  }

  .chips--filter {
    padding: 10px 16px;
    margin: 0 0 8px;
  }

  .filter-card {
    padding: 8px 16px;
    margin: 0 0 8px;
  }

  .filter-card .chips--filter {
    padding: 0;
    margin: 0;
  }

  .post-list,
  .moment-list {
    gap: 8px;
  }

  .post-card {
    gap: 12px;
    padding: 14px 16px;
    margin-bottom: 8px;
  }

  .post-card:last-child {
    margin-bottom: 0;
  }

  .post-card__title {
    font-size: 17px;
  }

  .post-card__excerpt {
    font-size: 14px;
    -webkit-line-clamp: 2;
  }

  .post-card__meta {
    margin-top: 10px;
  }

  .post-card__cover {
    width: 110px;
    height: 74px;
    margin-top: 1px;
  }

  .post-card__author {
    max-width: 120px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .moment-card {
    padding: 16px;
    margin-bottom: 8px;
  }

  .moment-card:last-child {
    margin-bottom: 0;
  }

  .moment-card__body {
    font-size: 15px;
  }

  .moment-card__actions {
    gap: 20px;
  }

  .media-grid {
    border-radius: var(--radius);
  }

  /* article */
  .article {
    --card-pad-top: 18px;
    --card-pad-x: 16px;
  }

  .article__title {
    font-size: 22px;
  }

  .article__byline {
    margin-top: 14px;
  }

  .prose {
    font-size: 16.5px;
    line-height: 1.85;
  }

  .prose pre {
    margin-right: -16px;
    margin-left: -16px;
    border-radius: 0;
  }

  .article__actions {
    display: none;
  }

  .mobile-action-bar {
    display: flex;
  }

  /* The room the bottom chrome needs at the end of a detail page used to be a
     flat 60 on #main. It is now spelled out from the chrome itself, because the
     capsule only looks balanced when the air above it equals the 12px it keeps
     above the tab bar below it:
       --chrome-top  the capsule's top edge = 12 of gap + 40 of box, plus the 52
                     tab bar when one is rendered. The 整行 strip is one row too,
                     so the same two numbers cover all three forms.
       --chrome-air  that matching 12px — dropped to 0 when the footer is on
                     stage, since the footer carries its own 12 of bottom
                     padding and would otherwise double it.
     The total is also what main.js reads back as the reveal reserve, so the tab
     bar still comes back exactly when the blank it vacated is about to show. */
  body.has-action-bar {
    --chrome-top: 52px;
    --chrome-air: 12px;
    padding-bottom: calc(var(--chrome-top) + var(--chrome-air) + env(safe-area-inset-bottom));
  }

  body.has-tabbar.has-action-bar {
    --chrome-top: calc(var(--tabbar-h) + 52px);
  }

  html:not([data-footer-mobile="none"]) body.has-action-bar {
    --chrome-air: 0px;
  }

  .post-nav {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .post-nav__item--next {
    grid-column: auto;
    text-align: left;
  }

  .post-nav__item--next .post-nav__title {
    align-self: flex-start;
  }

  .comments {
    margin-top: 22px;
  }

  /* feeds & archives */
  .archive {
    padding: 6px 16px 14px;
  }

  .archive-list__item a {
    font-size: 14px;
  }

  /* search: full screen */
  .search-dialog {
    padding: 0;
  }

  .search-dialog__panel {
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    border-radius: 0;
  }

  .search-dialog__bar {
    padding: 10px 12px;
    padding-top: calc(10px + env(safe-area-inset-top));
  }

  .search-dialog__field {
    height: 38px;
  }

  .search-dialog__esc {
    display: none;
  }

  .search-dialog__cancel {
    display: inline-flex;
  }

  .search-dialog__footer {
    padding-bottom: calc(10px + env(safe-area-inset-bottom));
  }

  .search-dialog__keys {
    display: none;
  }

  /* share: the panel keeps its card shape (a full-screen sheet would leave a
     lot of dead area around a 216px code), it just hugs the edges */
  .share-dialog {
    padding: 12px;
  }

  .share-dialog__panel {
    width: 100%;
    max-height: calc(100vh - 24px);
  }

  .share-dialog__head {
    padding: 8px 12px;
  }

  .share-dialog__body {
    padding: 12px 12px calc(14px + env(safe-area-inset-bottom));
  }

  .share-tile {
    height: 60px;
  }

  /* the viewer shares the panel shape, so it has to give up its 340px too */
  .share-viewer .share-dialog__panel {
    width: 100%;
  }

  /* pager */
  .pager {
    gap: 8px;
    padding: 14px 12px calc(14px + env(safe-area-inset-bottom));
  }

  .pager__btn {
    height: 32px;
    padding: 0 13px;
  }

  .pager__status {
    height: 32px;
  }

  /* footer. Desktop always rendered it; on the phone it was switched off as a
     whole, which also took the theme's only plugin injection slot with it. The
     shape is a server-side attribute on <html>, so the first paint is already
     the chosen one. 精简 drops the links row — every entry in it is one of the
     tabs the thumb is already resting on — and keeps the copyright, the filing
     numbers and whatever a plugin injects; 完整 keeps the row; 不显示 is the old
     behaviour. The text lines up with the 16px the cards inset their own content
     by, there is no hairline above it (removed from the desktop rule it inherits,
     so both surfaces agree), and the 12 below it is the same air the capsule
     keeps off the tab bar — so the footer is what sets the gap on detail pages
     and the page reserve drops to the capsule's edge. */
  .site-footer {
    padding: 0 16px 12px;
    /* same cross-axis auto-margin trap as .shell__inner above: without a
       definite width the footer shrinks to the copyright's own width and the
       line drifts off the 16px the cards inset their content by */
    width: 100%;
  }

  .site-footer__inner {
    gap: 6px;
    padding-top: 14px;
  }

  html[data-footer-mobile="none"] .site-footer {
    display: none;
  }

  html[data-footer-mobile="slim"] .site-footer__links {
    display: none;
  }

  /* display:contents rather than :empty — the template keeps a newline inside
     this div, so it is never literally empty even when no plugin injects, and
     that ghost box was taking a 6px slice of the column gap and pushing the
     copyright line to 18px above the capsule. With no box of its own an empty
     slot costs nothing, and whatever a plugin does inject becomes a row of the
     footer directly (overflow-wrap inherits, so long strings still break). */
  .site-footer__injected {
    display: contents;
  }

  .sidebar {
    display: none;
  }

  /* tab bar */
  .tabbar {
    display: flex;
  }

  /* The chrome panel shows exactly when at least one of the bars it backs
     shows: without the tab bar and without an article action strip it would
     paint an empty band across the bottom of the page. The article page is
     known from the body class rather than from :has(.mobile-action-bar): the
     panel is parsed at the top of <body> while the strip is the last thing in
     the article markup, so :has() only became true after the sheet had already
     painted once at tab-bar height.
     has-action-stack, not has-action-bar: the 悬浮 capsule detaches itself from
     this panel, so on a page with no tab bar there would be nothing left inside
     the band it reserves. */
  body.has-tabbar .mobile-chrome,
  body.has-action-stack .mobile-chrome {
    display: block;
  }

  /* Below the tab bar breakpoint the container fills the whole width, so there
     is no margin left to hang the disc in and the rail gives up tracking it:
     it becomes a corner anchor again. What it keeps is the lift — the disc
     floats above the bottom chrome instead of beside it, by the exact height of
     the sheet behind the bars, one row for the tab bar or the 赞同/评论/分享
     strip alone and two for both, and it comes back down when the tab bar
     slides away on scroll instead of hanging over the slot the chrome just
     vacated. Same property, same 0.18s, same class as the bars, so all of it
     runs on one clock.
     These live here and not in layout.css because has-tabbar is a server-side
     body class: on a desktop, where no tab bar is rendered, it would push the
     button 52px into the air for nothing. */
  .to-top-rail {
    right: 8px;
    bottom: calc(12px + env(safe-area-inset-bottom) + var(--chrome-clear, 0px));
    left: auto;
    margin: 0;
    max-width: none;
    padding-right: 0;
    transition: bottom 0.18s ease;
  }

  body.has-tabbar .to-top-rail,
  body.has-action-bar .to-top-rail {
    --chrome-clear: var(--tabbar-h);
  }

  body.has-tabbar.has-action-bar .to-top-rail {
    --chrome-clear: calc(2 * var(--tabbar-h));
  }

  html[data-tabbar-scroll="auto"].tabbar-hidden body.has-tabbar .to-top-rail {
    --chrome-clear: 0px;
  }

  html[data-tabbar-scroll="auto"].tabbar-hidden body.has-tabbar.has-action-bar .to-top-rail {
    --chrome-clear: var(--tabbar-h);
  }

  /* 居中胶囊 shares the capsule's row instead of climbing above it: the strip no
     longer costs a second row (has-action-stack in layout.html is false for it),
     so the clearance drops back to the chrome the capsule floats over, and the
     -2px is what puts the 44px disc on the 40px capsule's centre line — both sit
     12px off that chrome, so half the height difference is the whole offset.
     右下悬浮 keeps the lift above it: the capsule owns the right edge, which is
     exactly where the disc was heading. When the tab bar slides away the capsule
     drops into the slot it vacated, so the disc is restated to follow it onto the
     same row; while an overlay is open the disc is behind it anyway (drawer 90,
     search and share 110 against the rail's 64), so the pin the two bars honour
     needs no twin here. */
  html[data-action-bar="pill"] body.has-action-bar .to-top-rail {
    --chrome-clear: -2px;
  }

  html[data-action-bar="pill"] body.has-tabbar.has-action-bar .to-top-rail {
    --chrome-clear: calc(var(--tabbar-h) - 2px);
  }

  html[data-tabbar-scroll="auto"].tabbar-hidden[data-action-bar="pill"] body.has-tabbar.has-action-bar .to-top-rail {
    --chrome-clear: -2px;
  }

  /* 返回顶部并入胶囊: on the two detail templates the strip carries its own
     arrow chip (post.html / page.html), so the shell disc stands down there —
     and only there, since has-action-bar is the detail pages. Every other page
     keeps the disc and its clearance rules above untouched, and the desktop
     keeps it everywhere: this whole block is the phone media query. */
  html[data-action-back="on"][data-action-bar="pill"] body.has-action-bar .to-top-rail,
  html[data-action-back="on"][data-action-bar="float"] body.has-action-bar .to-top-rail {
    display: none;
  }

  /* links: the wall and the apply panel live in the page card, so the card keeps
     its dressing here and only tightens its padding. */
  .links-page {
    padding: 14px 12px;
    margin-bottom: 8px;
  }

  .link-grid {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .link-apply {
    margin-top: 12px;
  }

  .link-apply__hint {
    font-size: 12px;
  }

  /* The apply row and body bleed to the card's inner edge, which is 12px here
     instead of 20. */
  .link-apply__summary {
    margin-inline: -12px;
    padding: 14px 12px;
  }

  .link-apply__body {
    margin-inline: -12px;
    padding: 4px 12px 12px;
  }

  .apply-form {
    grid-template-columns: 1fr;
  }

  .apply-captcha input {
    flex: 1 1 auto;
    min-width: 0;
  }

  .apply-captcha__tip {
    display: none;
  }

  /* photos */
  .photo-grid {
    column-count: 2;
    column-gap: 4px;
    padding: 8px 4px;
    background: var(--surface);
  }

  .photo-card {
    margin-bottom: 4px;
    border-radius: var(--radius);
    background: var(--surface-2);
  }

  .photo-card__caption {
    padding: 24px 8px 7px;
  }

  .photo-card__title {
    font-size: 12px;
  }

  .photo-card__description {
    max-height: 1.5em;
    margin-top: 2px;
    opacity: 1;
    font-size: 11px;
    -webkit-line-clamp: 1;
  }

  .photo-detail {
    padding: 16px;
    border-radius: 0;
    box-shadow: none;
    margin-bottom: 8px;
  }

  .info-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 14px;
  }

  .neighbor-strip {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  /* douban */
  .douban-page {
    padding: 14px 12px;
    margin-bottom: 8px;
  }

  /* bangumi: the wall lives inside the page card, so only the filter row and
     the row-mode metrics need a mobile layout. */
  .bangumi-page {
    padding: 14px 12px;
    margin-bottom: 8px;
  }

  .bangumi-filters {
    gap: 8px;
    margin-bottom: 12px;
    padding-bottom: 10px;
  }

  .bangumi-filters__sep {
    display: none;
  }

  .bangumi-filters .chips {
    flex: 1 1 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .bangumi-filters .chips::-webkit-scrollbar {
    display: none;
  }

  .bangumi-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px 12px;
  }

  .bangumi-grid[data-layout="list"] {
    gap: 6px;
  }

  .bangumi-grid[data-layout="list"] .bangumi-card {
    grid-template-columns: 48px minmax(0, 1fr);
    column-gap: 12px;
    padding: 8px 10px;
    --bangumi-chip-gap: 12px;
  }

  /* The chip is absolutely positioned, so it follows the smaller padding by hand
     and the title reserve shrinks with --bangumi-chip-gap above. */
  .bangumi-grid[data-layout="list"] .bangumi-card__score {
    top: 8px;
    right: 10px;
  }

  .bangumi-grid[data-layout="list"] .bangumi-card__cover {
    width: 48px;
  }

  /* equipments */
  .equipment-group {
    padding: 16px 12px 4px;
    margin-bottom: 8px;
  }

  .equipment-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
  }

  .equipment-card {
    border-radius: var(--radius);
  }

  .equipment-card__body {
    padding: 10px 12px 12px;
  }

  .equipment-card__name {
    font-size: 14px;
  }

  .equipment-card__description {
    display: none;
  }

  /* terms & profiles */
  .term-cloud {
    padding: 16px 12px;
  }

  .category-tree {
    padding: 4px 16px;
    margin-bottom: 8px;
  }

  .term-pill {
    height: 32px;
    padding: 0 12px;
    font-size: 13px;
  }

  /* two tag cards per row, the same way 装备 and 追番 collapse on phones */
  .term-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
  }

  .term-card {
    height: 64px;
    padding: 0 12px;
  }

  .term-card__name,
  .term-row__name {
    font-size: 14px;
  }

  .term-row {
    padding: 12px;
  }

  .author-card {
    --author-overlap: 30px;
    margin-bottom: 8px;
  }

  .author-card__cover {
    height: 84px;
  }

  .author-card__main {
    gap: 14px;
    padding: 0 16px 16px;
  }

  .author-card__avatar {
    width: 72px;
    height: 72px;
    border-width: 3px;
  }

  .author-card__avatar--fallback {
    font-size: 28px;
  }

  .author-card__name {
    font-size: 19px;
  }

  /* comments & error */
  .error-page {
    padding: 64px 24px;
    min-height: calc(100vh - var(--topbar-h) - 60px);
  }

  .mobile-nav {
    width: min(320px, 86vw);
  }
}

@media (max-width: 360px) {
  .brand__name {
    display: none;
  }

  .post-card__cover {
    display: none;
  }
}

/* ---------- 文章目录：三个入口的分工 ---------- */

/* 有侧栏的桌面由侧栏卡片承担目录，顶部那条轨道收掉，免得同一件事有两个入口。
   1024 以下侧栏本身 display:none，轨道接回来。 */
@media (min-width: 1024px) {
  body.has-sidebar .toc-rail {
    display: none;
  }
}

@media (max-width: 768px) {
  /* 手机上目录入口在底部操作条里（分享右边那颗芯片），所以顶部轨道让位。详情页
     一定带 has-action-bar，也就是说这里等于「手机详情页无盘子」。 */
  body.has-action-bar .toc-rail {
    display: none;
  }

  /* 同一块面板换成从底部升起的目录单：占满宽度、贴底、上圆角，遮罩回来。
     位移用 translateY(100%) 而不是淡入，和抽屉、分享单同一个方向感。 */
  .toc-pop {
    inset: auto 0 0 0;
    max-height: 72vh;
  }

  /* 遮罩逐档照抄搜索：不开玻璃时两种配色都是 .42，开玻璃后浅色 .24、深色 .36。
     深色不另压一档，否则同一块材质在两个面板上又是两个浓度。 */
  .toc-pop__scrim {
    position: fixed;
    inset: 0;
    display: block;
    background: rgba(18, 18, 18, 0.42);
    opacity: 0;
    transition: opacity 0.18s ease;
  }

  .toc-pop.is-open .toc-pop__scrim {
    opacity: 1;
  }

  html[data-glass="on"] .toc-pop__scrim {
    background: rgba(18, 18, 18, 0.24);
  }

  html.dark[data-glass="on"] .toc-pop__scrim {
    background: rgba(0, 0, 0, 0.36);
  }

  .toc-pop__panel {
    width: 100%;
    max-width: none;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    padding-bottom: env(safe-area-inset-bottom);
    opacity: 1;
    transform: translateY(100%);
  }

  .toc-pop.is-open .toc-pop__panel {
    transform: none;
  }

  .toc-pop__head {
    padding: 12px 12px 10px 16px;
  }

  /* 手指比鼠标粗：条目行距放宽，右缘留出滚动条的位置。 */
  .toc__link {
    padding: 8px 16px;
    font-size: 14px;
  }

  .toc__item[data-level="1"] > .toc__link {
    padding-left: 30px;
    font-size: 13.5px;
  }

  .toc__item[data-level="2"] > .toc__link {
    padding-left: 44px;
    font-size: 13.5px;
  }
}
