/* ============================================================
   天气 · 极简排版页
   ------------------------------------------------------------
   图层从下到上（2026-09-29 定案；用户当日下午追加：「字体放在水珠图层上」）：

     ① 内容层        .brand-bar(50) / .sheet(50)      ← 文字、logo、搜索框
                     搜索框在 .sheet 之内，跟着一起浮在玻璃之上
     ② 玻璃水珠      #glassLayer      z-index 40   ← 镜头前方的近景雨珠
     ③ 背景          .sky-edge-tint(-1) / .weather-effects(-1) / .sky-backdrop(-2)

   为什么文字提到水珠之上仍然看得到水珠：`.sheet` 与 `.brand-bar` 都是**透明底**，
   水珠画在它们后面照旧满屏可见 —— 只是不再压在笔画上面糊字。
   （早先的版本是「水珠盖正文、只放搜索框出来」，改用这一版：
     水珠糊在字上会让报告正文和 logo 发虚，可读性优先。）

   🔴 想回到旧效果：把 .brand-bar / .sheet 的 z-index 去掉即可，
     顺序自动复原成「水珠盖文字」——`test/layers.mjs` 会立刻变红，那是预期。

   两条实现上的硬约束：
   · 整块内容层（.sheet / .brand-bar）自己声明 z-index，不能让里面某个子元素
     单独去翻：父级只要形成层叠上下文，子元素写多大都被困在它那一层里。
   · 玻璃层与背景层都是 fixed 且不动、不吃点击，只有内容层随页面滚动 ——
     所以「水珠铺满全屏却不随滚动、不挡操作」是画上去的顺序决定的，不是位置决定的。
   ============================================================ */

:root {
  /* 节奏（8px 基准） */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s8: 32px; --s10: 40px;
  --s12: 48px; --s16: 64px;

  --serif: 'Fraunces', Georgia, 'Songti SC', serif;
  --sans:  'Inter', -apple-system, 'PingFang SC', 'Helvetica Neue', sans-serif;
  --mono:  'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --warm:       #ff9a76;
  --cool:       #7fb3d5;

  /* 页面宽度：容纳 6 项指标一行放完 */
  --page-max: 1000px;

  /* ---- 墨色：深色天空（夜间 / 黄昏 / 黎明）默认 ---- */
  --ink:        #ffffff;
  --ink-2:      rgba(255, 255, 255, 0.88);
  --ink-3:      rgba(255, 255, 255, 0.64);
  --ink-4:      rgba(255, 255, 255, 0.44);

  --rule:       rgba(255, 255, 255, 0.14);
  --rule-soft:  rgba(255, 255, 255, 0.07);

  --glass:        rgba(255, 255, 255, 0.09);
  --glass-hover:  rgba(255, 255, 255, 0.16);
  --glass-strong: rgba(20, 28, 44, 0.72);
  --glass-border: rgba(255, 255, 255, 0.18);
  --shadow:       rgba(0, 0, 0, 0.34);

  --toast-bg:   rgba(255, 255, 255, 0.94);
  --toast-fg:   #101a24;

  /* 闪电边缘高光：由 js/atmospheric-effects.js 注入 */
  --lightning-rim: 0;
}

/* ---- 墨色：浅色天空（早晨 / 正午 / 下午）---- */
:root[data-ink="light"] {
  --ink:        #141f2b;
  --ink-2:      rgba(20, 31, 43, 0.84);
  --ink-3:      rgba(20, 31, 43, 0.62);
  --ink-4:      rgba(20, 31, 43, 0.44);

  --rule:       rgba(16, 30, 45, 0.16);
  --rule-soft:  rgba(16, 30, 45, 0.08);

  --glass:        rgba(255, 255, 255, 0.42);
  --glass-hover:  rgba(255, 255, 255, 0.66);
  --glass-strong: rgba(255, 255, 255, 0.86);
  --glass-border: rgba(255, 255, 255, 0.68);
  --shadow:       rgba(10, 26, 46, 0.16);

  --toast-bg:   rgba(20, 31, 43, 0.92);
  --toast-fg:   #ffffff;
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  min-height: 100vh;
  background: transparent;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  font-feature-settings: 'ss01', 'cv05';
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  position: relative;
  overflow-x: hidden;
  /* 天空换场时墨色跟着一起过渡，避免硬切 */
  transition: color 1.1s ease;
}

/* 墨色随天空明暗切换时，页面内所有着色属性一起过渡。
   用 :where() 把优先级压到 0，让组件自己的 transition（toast、gauge 游标等）照常生效。 */
.brand-bar :where(*),
.sheet :where(*) {
  transition: color 1.1s ease, background-color 1.1s ease,
              border-color 1.1s ease, box-shadow 1.1s ease;
}

/* 天空背景已交给 js/sky-gradient.js 在运行时逐帧插值绘制（.sky-backdrop），
   这里原先写死的那套 body::before 渐变属于历史残留，已移除。 */

/* 窗外天气场景画布（js/scene-weather.js）
   雨滴 / 雪花 / 闪电原先是一堆 DOM 元素配 CSS keyframes，已整体换成这张
   canvas —— CSS 动画只能让元素整体平移，做不出逐粒子的景深、柔和雪花球
   和分叉闪电路径。这里只负责把它固定铺满视口、压在内容之下。 */
.weather-effects {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: block;         /* canvas 是行内元素，不写会多出一条基线间隙 */
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}

.sheet {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--s8) var(--s6) var(--s16);
  position: relative;
  /* 图层 ①：正文整块浮在玻璃水珠之上（50 > 40）。带上 z-index 会形成层叠
     上下文，里面的 .masthead / .results 就都在这一层里，跟着一起压过水珠 ——
     这正是要的效果。但要往**更低**的方向放东西就不可能了（子元素出不去），
     所以别在这里调层号，要动就整体动。
     z-index 50 而非 41：留出与 .brand-bar 同层、以及和 toast(60) 的间距。 */
  z-index: 50;
}

h1, h2 { margin: 0; font-weight: 400; }
p, dl, dd, dt { margin: 0; }

.mark-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ink-3);
  flex-shrink: 0;
  transition: background .6s ease;
}

/* ---------- 品牌标识（贴视口左上角） ----------

   版式与几何**逐项对齐 start.abobb.site 的顶栏 brand**（那边的源在
   /Volumes/Abobb-disk/startpage，对比脚本见 test/brand-probe.mjs）：

     图标 28×28 · 间隙 10 · 主行 14px/700 · 行高 1.1
     副行 10px/400 · 距主行 4px · 字距 .04em

   早先这里是「36px 图标 + 21px 衬线主行 + 0.22em 散字距副行」，
   视觉重心明显比参考重，而且和 start 页放在一起时字号对不上。

   保留的差异只有两处，都是有意的：
     1. 图标换成天气线稿（assets/logo-weather.png），仍走 mask 跟随墨色 ——
        start 页用的是房子，天气页自然该是天气。
     2. 图标尺寸写 32px 而不是参考的 28px：我们的图标**画满画布**
        （内容框 160×133，就是一张 160 方图），参考那张房子四周留白
        （内容框 360×330 / 画布 480），实际墨迹只有 75%。
        28 / 0.75 ≈ 37，取 32 是折中值 —— 若直接照搬 28px，
        我们的图标会比参考看起来小一圈，反而对不齐。
     3. 字体与 start 完全同一套（2026-09-27 定案「这是一套作品」）：
        主行 Manrope 700、副行 DM Mono —— 就是 start 顶栏用的那两族
        （weather.html 的 Google Fonts 链接里已补上）。正文仍是 Fraunces，
        只有 brand 这一小块换过去。 */
.brand-bar {
  position: relative;
  /* 图层 ①：logo 与站名同样浮在玻璃水珠之上（与 .sheet 同层 50）。
     与 .sheet 同为 50 时按 DOM 顺序绘制，brand 在前 → 在下，
     两者不重叠，谁上谁下无所谓。 */
  z-index: 50;
  width: 100%;
  /* 与 start 页 .topbar 逐字一致：27px clamp(22px,5vw,76px)。
     两站放在一起时 logo 离屏幕左缘的距离一模一样，「一套作品」。 */
  padding: 27px clamp(22px, 5vw, 76px) 0;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

/* 图标走 mask，颜色继承 currentColor —— 深色天空自动变白，浅色天空自动变墨 */
.brand-logo {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  background: currentColor;
  color: var(--ink);
  /* ?v= 是必须手动改的缓存指纹（本项目无构建流程）：只换文件不改 URL，
     浏览器会一直拿旧的 logo —— 与 favicon 同理，见 weather.html 顶部注释。
     2026-10-09 换图（pulsar-line / partly-cloudy-day）时由 v=1 提到 v=2。 */
  -webkit-mask: url('../assets/logo-weather.png?v=2') center / contain no-repeat;
          mask: url('../assets/logo-weather.png?v=2') center / contain no-repeat;
  /* 不加任何阴影（用户定案，别再往回加）。
     参考页 start.abobb.site 的 brand-mark 也是纯色 mask，没有 filter。 */
}

.brand-words {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
  min-width: 0;
}

.brand-name {
  font-family: 'Manrope', var(--sans);   /* 与 start 顶栏主行同族（那边继承 body 的 Manrope） */
  font-size: 14px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: .02em;
  color: var(--ink);
  /* 顶部品牌区整体不加阴影（图标 / 标题 / 副标题一致），
     避免在浅色天空上出现一圈灰雾。 */
}

.brand-sub {
  margin-top: 4px;
  font-family: 'DM Mono', var(--mono);   /* 与 start 顶栏副行同族（font:10px 'DM Mono'） */
  font-size: 10px;
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: .04em;
  text-transform: lowercase;
  color: var(--ink-3);
}

/* ---------- 顶栏：搜索 ---------- */

/* 图层 ①：搜索框浮在玻璃水珠之上，水珠不糊住输入框与下拉结果。
   它本身压过水珠靠的是父级 .sheet 整块 50（父级是层叠上下文，子元素出不去）；
   这里再写一个 50 是为了在同一层里压住绝对定位的 .results(20)；
   toast 是 60，仍在它之上。 */
.masthead {
  position: relative;
  z-index: 50;
  padding-bottom: var(--s12);
}

.masthead-search {
  position: relative;
  min-width: 0;
}

.search-field {
  display: flex;
  align-items: center;
  gap: var(--s3);
  height: 48px;
  padding: 0 var(--s4) 0 var(--s5);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  background: var(--glass);
  box-shadow: 0 1px 2px var(--shadow), 0 14px 30px -22px var(--shadow);
  transition: color 1.1s ease, background-color .22s ease,
              border-color .22s ease, box-shadow .22s ease;
}

/* 闪电边缘高光：背景画布打闪的几十毫秒里，玻璃件的顶边被同一道冷白光擦亮。
   --lightning-rim（0~1）由 js/atmospheric-effects.js 写入，只在值变化时写。
   用伪元素 + inset 阴影，不动 border-color：原有的 .22s 边框过渡会把一闪拖成慢慢亮起。 */
.search-field { position: relative; }   /* .results 本身已是 absolute */
.search-field::after, .results::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 1px 0 rgba(226, 238, 255, 0.9), 0 -1px 10px -2px rgba(210, 228, 255, 0.55);
  -webkit-mask: linear-gradient(#000, transparent 55%);
          mask: linear-gradient(#000, transparent 55%);
  opacity: var(--lightning-rim, 0);
}

.search-field:hover { background: var(--glass-hover); }

.search-field:focus-within {
  background: var(--glass-hover);
  border-color: var(--rule);
  box-shadow: 0 1px 2px var(--shadow), 0 18px 40px -20px var(--shadow);
}

/* 搜索框里的两枚 PNG 图标（icons8，黑色墨迹 + 透明底）。
   走 mask + currentColor：黑色像素当遮罩，background 填 currentColor，
   墨色一变它跟着变 —— 与左上角 logo 同一套机制。 */
.icon-glyph {
  display: block;
  flex-shrink: 0;
  width: 18px; height: 18px;
  background: currentColor;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

.search-glyph {
  width: 18px; height: 18px;
  color: var(--ink-3);
  -webkit-mask-image: url('../assets/icon-search.png');
          mask-image: url('../assets/icon-search.png');
}

#searchInput {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  padding: var(--s1) 0;
  outline: none;
}

#searchInput::placeholder { color: var(--ink-4); }

.locate {
  flex-shrink: 0;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border: 0;
  background: transparent;
  border-radius: 50%;
  color: var(--ink-3);
  cursor: pointer;
  transition: color .18s ease, background-color .18s ease;
}

/* 罗盘是圆环图形，同框下视觉比实心笔画多的放大镜小一圈，
   放大到 22px 补偿（30px 圆形按钮内居中） */
.locate-glyph {
  width: 22px; height: 22px;
  -webkit-mask-image: url('../assets/icon-compass.png');
          mask-image: url('../assets/icon-compass.png');
}
.locate:hover { color: var(--ink); background: transparent; }

/* ---------- 搜索结果 ---------- */

.results {
  position: absolute;
  top: calc(100% + var(--s2));
  left: 0; right: 0;
  z-index: 20;
  padding: var(--s2);
  border: 1px solid var(--glass-border);
  border-radius: 22px;
  background: var(--glass-strong);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
          backdrop-filter: blur(22px) saturate(150%);
  box-shadow: 0 2px 6px var(--shadow), 0 22px 48px -20px var(--shadow);
  overflow: hidden;
  display: none;
}

.results.open { display: block; }

.result {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  width: 100%;
  padding: var(--s3) var(--s4);
  border: 0;
  border-radius: 15px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.result:hover, .result:focus-visible { background: var(--rule-soft); outline: none; }
.result-name { font-size: 14px; }
.result-region { font-size: 12px; color: var(--ink-3); }
.result-empty {
  padding: var(--s3) var(--s4);
  font-size: 13px;
  color: var(--ink-3);
}

/* ---------- 主报告 ---------- */

.report {
  padding: 0 0 var(--s10);
  border-bottom: 1px solid var(--rule);
}

.place {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
  min-height: 1.4em;
}

.city {
  font-family: var(--serif);
  font-size: 30px;
  font-weight: 300;
  letter-spacing: -.005em;
  margin-top: var(--s1);
}

.reading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s6);
  margin-top: var(--s6);
}

.reading-temp {
  display: flex;
  align-items: flex-start;
  font-family: var(--serif);
  font-weight: 300;
  font-size: 118px;
  line-height: .86;
  letter-spacing: -.045em;
  font-variant-numeric: tabular-nums lining-nums;
}

.reading-temp .deg {
  font-size: .32em;
  line-height: 1;
  margin-top: .22em;
  color: var(--ink-3);
  letter-spacing: 0;
}

.reading-side {
  text-align: right;
  padding-bottom: var(--s2);
}

.glyph {
  display: flex;
  justify-content: flex-end;
  color: var(--ink-2);
  margin-bottom: var(--s2);
}

.glyph svg { width: 34px; height: 34px; }

.condition {
  font-size: 16px;
  color: var(--ink);
}

.extremes {
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 300;
  color: var(--ink-3);
  margin-top: var(--s1);
  font-variant-numeric: tabular-nums;
}

/* ---------- 指标网格 ---------- */

/* 列数按断点写死，保证每行都是整行、不会有指标落单 */
.facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s5) var(--s4);
  margin-top: var(--s10);
}

@media (min-width: 640px) {
  .facts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
  .facts { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s5); }
}

.fact {
  min-width: 0;
  padding: var(--s3) 0;
}

.fact dt {
  font-size: 11px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.fact dd {
  margin-top: 5px;
  font-family: var(--mono);
  font-size: 19px;
  font-weight: 300;
  line-height: 1.2;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: baseline;
  gap: 3px;
  white-space: nowrap;
}

.fact dd i {
  font-family: var(--sans);
  font-style: normal;
  font-size: 11px;
  color: var(--ink-3);
}

/* 补充说明单独一行，避免把整行网格撑高 */
.fact-note {
  margin-top: 3px;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--ink-3);
  min-height: 1.4em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- 板块通用 ---------- */

.panel {
  padding: var(--s10) 0;
  border-bottom: 1px solid var(--rule);
}

.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  margin-bottom: var(--s6);
}

.panel-head h2 {
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.panel-note {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 300;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}

/* ---------- 24 小时 ---------- */

/* 24 小时是横向滚动区，两端用遮罩淡出提示「还有内容」。
   背景是动态渐变，没法用纯色做淡出，所以走 mask。
   淡出宽度由 --fade-l/--fade-r 控制，JS 按滚动位置开关：
   已经在最左就不淡出左边，已经在最右就不淡出右边（否则会白吃掉一截内容）。 */
.timeline-wrap { position: relative; }

.timeline {
  --fade-l: 0px;
  --fade-r: 0px;
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  -webkit-mask-image: linear-gradient(90deg,
    transparent 0, #000 var(--fade-l),
    #000 calc(100% - var(--fade-r)), transparent 100%);
          mask-image: linear-gradient(90deg,
    transparent 0, #000 var(--fade-l),
    #000 calc(100% - var(--fade-r)), transparent 100%);
}

.timeline-wrap:not(.at-start) .timeline { --fade-l: 46px; }
.timeline-wrap:not(.at-end)   .timeline { --fade-r: 46px; }

.timeline::-webkit-scrollbar { display: none; }

.curve {
  position: absolute;
  top: 0;            /* 由 JS 对齐到 .hour-slot 实际位置 */
  left: 0;
  height: 54px;
  color: var(--ink-3);
  pointer-events: none;
}

.hours {
  display: flex;
  gap: 0;
  min-width: max-content;
  position: relative;
}

.hour {
  width: 58px;
  flex: 0 0 58px;
  text-align: center;
  padding-bottom: var(--s1);
}

.hour-time {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 300;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.hour.is-now .hour-time {
  color: var(--ink);
  font-weight: 500;
}

.hour-icon {
  height: 24px;
  margin-top: var(--s2);
  display: grid;
  place-items: center;
  color: var(--ink-2);
}

.hour-icon svg { width: 18px; height: 18px; }

/* 温度数字浮在曲线节点正上方，--y 由 JS 按温度换算 */
.hour-slot { height: 54px; position: relative; }

.hour-temp {
  position: absolute;
  left: 0; right: 0;
  top: var(--y, 50%);
  transform: translateY(-100%);
  margin-top: -5px;
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.hour-pop {
  margin-top: var(--s1);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 300;
  color: var(--cool);
  min-height: 1.3em;
  font-variant-numeric: tabular-nums;
}

/* ---------- 7 天 ---------- */

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

.day {
  display: grid;
  grid-template-columns: 54px 24px 1fr 148px;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule-soft);
}

.day:first-child { border-top: 0; }

/* 宽屏把温区拉长，读温差区间更直观 */
@media (min-width: 900px) {
  .day { grid-template-columns: 62px 26px 1fr 240px; gap: var(--s4); }
}

.day-name {
  font-size: 13px;
  color: var(--ink-2);
}

.day.is-today .day-name { color: var(--ink); font-weight: 500; }

.day-icon {
  display: grid;
  place-items: center;
  color: var(--ink-2);
}

.day-icon svg { width: 18px; height: 18px; }

.day-desc {
  font-size: 13px;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.day-temps {
  display: grid;
  grid-template-columns: 30px 1fr 30px;
  align-items: center;
  gap: var(--s2);
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 300;
  font-variant-numeric: tabular-nums;
}

.day-lo { color: var(--ink-3); text-align: right; }
.day-hi { color: var(--ink); text-align: left; }

.day-bar {
  position: relative;
  height: 3px;
  border-radius: 2px;
  background: var(--rule);
  overflow: hidden;
}

.day-bar span {
  position: absolute;
  top: 0; bottom: 0;
  left: var(--from, 0%);
  width: var(--span, 100%);
  border-radius: 2px;
  background: linear-gradient(90deg, var(--cool), var(--warm));
}

/* ---------- 空气质量 ---------- */

.air-figures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s4);
}

/* 宽屏下让三项污染物与上方「体感…紫外线」6 列同栅格，
   每项各占 2 列，上下两排数字严丝合缝对齐 */
@media (min-width: 900px) {
  .air-figures {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--s5);
  }
  .air-figures .figure { grid-column: span 2; }
}

.figure dt {
  font-size: 11px;
  letter-spacing: .07em;
  color: var(--ink-3);
}

.figure dd {
  margin-top: 4px;
  font-family: var(--mono);
  font-size: 24px;
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.figure dd i {
  font-family: var(--sans);
  font-style: normal;
  font-size: 11px;
  color: var(--ink-3);
}

.gauge { margin-top: var(--s8); }

.gauge-track {
  position: relative;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    #4ea36b 0%, #9dbd52 18%, #e0b341 36%,
    #dd8340 54%, #cf5a52 72%, #8c4a7a 100%);
  opacity: .82;
}

/* AQI 游标：实心小圆点，颜色**取轨道渐变上它所在位置的颜色**
   （由 js/weather.js 的 gaugeColorAt() 按 percent 插值后写成内联 background）。
   曾经是「--paper-solid 填充 + 2px --ink 描边」——夜里 --paper-solid 是 #101a24，
   于是变成一个带白边的黑圈（用户否掉了）。这里只留兜底色，
   数据没到之前是「优」段绿，一到数据就被内联色覆盖。 */
.gauge-pin {
  position: absolute;
  top: 50%;
  left: var(--at, 0%);
  width: 10px; height: 10px;
  margin-left: -5px;
  border-radius: 50%;
  background: var(--pin, #4ea36b);
  transform: translateY(-50%);
  transition: left .55s cubic-bezier(.22,.7,.3,1),
              background-color .55s ease, box-shadow .55s ease;
}

.gauge-scale {
  display: flex;
  justify-content: space-between;
  margin-top: var(--s2);
  font-size: 10.5px;
  letter-spacing: .04em;
  color: var(--ink-4);
}

.air-note {
  margin-top: var(--s5);
  font-size: 13px;
  line-height: 1.7;
  color: var(--ink-2);
  max-width: 54ch;
}

/* ---------- 页脚 ---------- */

.colophon {
  display: flex;
  /* 允许换行：版权行靠 flex-basis:100% 独占第二行，
     窄屏不会把「数据源」和「时间戳」挤断。 */
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s4);
  padding-top: var(--s6);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--ink-4);
}

#stamp { font-family: var(--mono); font-weight: 300; }

/* 版权行：与站点其它文字同一套墨色（--ink-4），随天空明暗自动转白/转墨。
   对齐：flex-basis:100% 已让它独占整行，再靠 text-align 锚到**页面中轴**
   （.colophon 在 .sheet 之内，而 .sheet 是 margin:0 auto 的定宽块，
   所以这一行的几何中心就是版面中心，不是视口中心 —— 两者在大屏下一致）。
   间距：margin-top 叠在 .colophon 的 row-gap 之上，把它从「数据源那一行的
   附注」拉开成独立的页脚落款，落点在整页最下方。 */
.credit {
  flex-basis: 100%;
  margin-top: var(--s10);
  text-align: center;
  font-family: var(--mono);
  font-weight: 300;
  letter-spacing: .06em;
}

/* 玻璃面水珠（js/glass-layer.js）  —— 图层 ②
   这一层贴在内容**后面** —— 它是「镜头前方」的近景雨珠，不是窗外的雨。
   越靠近镜头的雨珠越锐利、完全不失焦，这正是它和 .weather-effects 的区别：
   后者画的是窗外，前者画的是糊在眼前的那一层水膜。

   z-index 40 的落位（2026-09-29 定案，当日下午调整过一次）：
     本层 40  <  内容层 .brand-bar(50) / .sheet(50)  <  toast(60)
   也就是「水珠只糊在空处，不糊字」。内容层是透明底，所以水珠照旧满屏可见。
   反过来若把内容层降回 40 以下，就变回「水珠盖文字」，可读性会明显变差。 */
.glass-layer {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: block;
  width: 100%;
  height: 100%;
  z-index: 40;
  pointer-events: none;
}

/* ---------- Toast ---------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: var(--s6);
  transform: translate(-50%, 8px);
  z-index: 60;
  max-width: calc(100vw - 32px);
  padding: 9px var(--s4);
  border-radius: 999px;
  background: var(--toast-bg);
  color: var(--toast-fg);
  box-shadow: 0 10px 28px -12px var(--shadow);
  font-size: 12.5px;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity .22s ease, transform .22s ease, visibility .22s;
}

.toast.show {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}

/* ---------- 载入过渡 ---------- */

.report, .panel { transition: opacity .3s ease; }
body.is-loading .report,
body.is-loading .panel { opacity: .45; }

/* ---------- 窄屏 ---------- */

@media (max-width: 640px) {
  .sheet { padding: var(--s8) var(--s5) var(--s12); }

  .brand-bar { padding: var(--s4) var(--s5) 0; }
  .brand-logo { width: 28px; height: 28px; }
  .brand-name { font-size: 14px; }

  .masthead { padding-bottom: var(--s8); }
  .search-field { height: 44px; padding: 0 var(--s3) 0 var(--s4); }

  .report { padding: 0 0 var(--s8); }
  .city { font-size: 25px; }
  .reading-temp { font-size: 86px; }
  .glyph svg { width: 28px; height: 28px; }
  .condition { font-size: 15px; }

  .facts { margin-top: var(--s8); }

  .panel { padding: var(--s8) 0; }

  .day { grid-template-columns: 46px 22px 1fr; }
  .day-desc { display: none; }
  .day-temps { grid-column: 3; }

  .air-figures { gap: var(--s3); }
  .figure dd { font-size: 20px; }
  .gauge-scale span:nth-child(3),
  .gauge-scale span:nth-child(4) { display: none; }
}

@media (max-width: 380px) {
  .facts { grid-template-columns: repeat(2, 1fr); }
  .reading-temp { font-size: 74px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
}

