/* Right2Rest preview — notify.css (owner 2026-11-11): sign-ups from any page.
   1. the home hero's own email form (.hv-sub), 2. the sign-up popup (dialog.ntf) opened by every "Notify me" link.
   updates.html stays the shareable page and the no-JS fallback; its form styles live in site.css (body[data-page="updates"]).
   Values are copied from that block, not redefined: input 14 radius / #141416 / var(--card-line) / focus outline 2px var(--text).
   Loaded after site.css and hero-layout.css on every public page. No new colours. */

/* ===== shared form look (hero + popup) ===== */
:is(.hv-sub, .ntf) .upd-form label { display: block; margin-bottom: 8px; font: 500 13px/18px var(--font-body); color: var(--sec); }
:is(.hv-sub, .ntf) .upd-row { display: flex; gap: 8px; }
:is(.hv-sub, .ntf) .upd-row input { flex: 1; min-width: 0; min-height: 46px; padding: 0 16px; border: 1px solid var(--line-2); border-radius: 14px; background: var(--raised); color: var(--text); font: 400 16px/1.4 var(--font-body); }
:is(.hv-sub, .ntf) .upd-row input::placeholder { color: var(--quiet); opacity: 1; }
/* App input (V3 04 §9.9): #1C1C1F, radius 14, height 46, no shadow; focus only brightens the border (white .55), no outer ring.
   Also applied to updates.html, whose base styles live in site.css. */
:is(.hv-sub, .ntf) .upd-row input:focus, body[data-page="updates"] .upd-row input:focus { outline: none; border-color: rgba(255,255,255,.55); }
body[data-page="updates"] .upd-row input { min-height: 46px; border-color: var(--line-2); background: var(--raised); }
:is(.hv-sub, .ntf) .upd-row input[aria-invalid="true"] { border-color: var(--line-2); }
:is(.hv-sub, .ntf) .upd-row .btn { flex: none; white-space: nowrap; }
:is(.hv-sub, .ntf) .upd-row .btn[aria-busy="true"] { opacity: .6; cursor: progress; }
:is(.hv-sub, .ntf) .upd-msg { min-height: 22px; margin: 10px 0 0; font-size: 14px; line-height: 22px; color: var(--sec); }
:is(.hv-sub, .ntf) .upd-msg:empty { min-height: 0; margin: 0; }   /* the live region stays in the page; it just takes no room while empty */
:is(.hv-sub, .ntf) .upd-msg.is-err { color: var(--body); }
:is(.hv-sub, .ntf) .upd-consent { margin: 6px 0 0; font-size: 13px; line-height: 18px; color: var(--quiet); }
:is(.hv-sub, .ntf) .upd-fine { margin: 10px 0 0; font-size: 13px; line-height: 18px; color: var(--quiet); }
:is(.hv-sub, .ntf) .upd-done-msg { margin: 0; font-size: var(--fs-lead); line-height: 1.65; color: var(--body); outline: none; }
:is(.hv-sub, .ntf) .upd-done .btn-row { margin-top: 24px; }

/* ===== home hero (owner 2026-11-11, "too big"): status line, ONE field with the button inside it, ONE quiet line under it.
   The full consent wording stays on the popup and updates.html; the hero line is the short form (consent version 2026-11-11-hero). ===== */
.hero-w .hero-v-bottom .hero-v-buy { display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; justify-content: flex-start; gap: 10px; margin-top: 20px; }
.hero-w .hero-v-bottom .hero-v-buy .small { flex: none; margin: 0; }
.hv-sub { width: 100%; }
/* App groove (V3 04 §9.9, the Ask After Light input; shadow table "凹槽"): #141416 base, card outline, inset shadow, radius 20;
   the outline does not brighten on focus and there is no outer ring. The button is the groove's raised block: #1C1C1F,
   radius 16 (20 - 4, concentric), no outline colour, no shadow; a keyboard-only 1px neutral ring (04 "键盘焦点"). */
.hv-sub .upd-row { display: flex; align-items: center; gap: 0; padding: 4px; border: 1px solid var(--card-line); border-radius: 14px; background: #141416; box-shadow: inset 0 2px 7px rgba(0,0,0,.5); }
.hv-sub .upd-row input, .hv-sub .upd-row input:focus { min-height: 36px; padding: 0 8px 0 14px; border: 0; border-radius: 0; background: transparent; outline: none; box-shadow: none; }
/* owner 2026-11-11 "too plain": the inner button keeps the raised grey and takes the App colour frame (04 §3.4, accent button):
   1px border in the page's light colour at .28, the same colour at .045 over the grey, neutral text; hover .45, press .85 (border only). */
.hv-sub .upd-row .btn, .hv-sub .upd-row .btn:hover, .hv-sub .upd-row .btn:active { min-height: 36px; padding-inline: 16px; border: 1px solid rgba(var(--accent-rgb),.28); border-radius: 12px; background: linear-gradient(rgba(var(--accent-rgb),.045), rgba(var(--accent-rgb),.045)), var(--raised); color: var(--body); box-shadow: none; transition: border-color .2s var(--ease), transform .12s var(--ease); }
.hv-sub .upd-row .btn:hover { border-color: rgba(var(--accent-rgb),.45); }
.hv-sub .upd-row .btn:active { transform: scale(.97); border-color: rgba(var(--accent-rgb),.85); }
.hv-sub .upd-row .btn:focus-visible { outline: 1px solid var(--text); outline-offset: 2px; }
.hv-sub .upd-msg { margin-top: 8px; font-size: 12px; line-height: 16px; }
.hv-sub .upd-fine { margin: 8px 0 0; font-size: 12px; line-height: 16px; }
.hv-sub .upd-done-msg { font-size: 14px; line-height: 1.5; }

/* medium (735-1068): a centred block under the centred sentence */
@media (min-width: 735px) and (max-width: 1068px) {
  .hero-w .hero-v-bottom .hero-v-buy { width: min(100%, 400px); margin-inline: auto; text-align: center; }
  .hero-w .hero-v-bottom .hero-v-buy .small { text-align: center; }
  .hero-w { --rb: 190px; }   /* room for the block under the two-line sentence */
}

/* desktop (>=1069): the block stays bottom right at the old button area's width and follows the hero's scale (--u) */
@media (min-width: 1069px) {
  .hero-w .hero-v-frame { grid-template-rows: calc(178 * var(--u)) minmax(0, 1fr) minmax(calc(102 * var(--u)), max-content); }
  .hero-w .hero-v-bottom { align-items: end; }
  /* owner 2026-11-11: STILL sat too close to the sign-up block. Room between the headline and the bottom row is ~430u and STILL
     is ~400u tall, so lifting alone pushes it into the headline: the clip is 6% smaller (588u -> 553u) and lifted 24u, leaving
     ~28u above and below (hero-layout.css places the clip 4u - .16 clip from the media top). */
  .hero-w-media video { --clip: calc(553 * var(--u)); top: calc(4 * var(--u) - .16 * var(--clip) - 24 * var(--u)); }
  .hero-w .hero-v-bottom .hero-v-buy { width: calc(400 * var(--u)); max-width: none; margin: 0 0 0 auto; gap: calc(10 * var(--u)); text-align: left; }
  .hero-w .hero-v-bottom .hero-v-buy .small { text-align: left; }
  .hv-sub .upd-row { padding: calc(4 * var(--u)); border-radius: calc(14 * var(--u)); }
  .hv-sub .upd-row input { min-height: max(32px, calc(36 * var(--u))); padding: 0 calc(8 * var(--u)) 0 calc(12 * var(--u)); font-size: max(14px, calc(15 * var(--u))); }
  .hv-sub .upd-row .btn, .hv-sub .upd-row .btn:hover, .hv-sub .upd-row .btn:active { min-height: max(32px, calc(36 * var(--u))); border-radius: calc(12 * var(--u)); }
  .hv-sub .upd-msg { margin-top: calc(8 * var(--u)); font-size: max(11px, calc(12 * var(--u))); line-height: 1.4; }
  .hv-sub .upd-fine { margin-top: calc(8 * var(--u)); font-size: max(11px, calc(12 * var(--u))); line-height: 1.4; }
  .hv-sub .upd-done-msg { font-size: max(12px, calc(14 * var(--u))); }
}

/* phone (<=734): same single field, centred under the sentence; 16px type keeps iOS from zooming in on focus */
@media (max-width: 734px) {
  .hero-w .hero-v-bottom .hero-v-buy { gap: 10px; }
  .hero-w .hero-v-bottom .hero-v-buy, .hero-w .hero-v-bottom .hero-v-buy .small { text-align: center; }
  .hv-sub .upd-row input { font-size: 16px; }
  .hero-w { --rb: 210px; }
}

/* the page behind does not shift when its scrollbar goes */
dialog.ntf { width: min(480px, calc(100% - 32px)); max-width: none; max-height: calc(100svh - 32px); margin: auto; padding: 0; border: 1px solid var(--card-line); border-radius: 28px; background: var(--card-display); color: var(--body); box-shadow: var(--shadow-card); overflow: auto; overscroll-behavior: contain; }
dialog.ntf::backdrop { background: rgba(0, 0, 0, .62); }
.ntf-card { position: relative; padding: 36px 32px 32px; }
.ntf-x { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; min-height: 40px; padding: 0; border-radius: 50%; }
.ntf-kicker { margin: 0 56px 14px 0; text-align: left; }
html:lang(zh) .ntf-kicker { font-family: var(--font-body); letter-spacing: .08em; }   /* a Chinese sentence, as on the updates page */
.ntf-h { margin: 0; font-size: 30px; line-height: 1.15; letter-spacing: -.045em; text-align: left; }
.ntf-h .hl { display: block; }
html:lang(zh) .ntf-h { font-size: 28px; letter-spacing: 0; }
.ntf-p { margin: 14px 0 0; font-size: 15px; line-height: 1.6; color: var(--sec); text-align: left; }
.ntf-p em { font-style: normal; color: var(--text); }
.ntf .upd-form, .ntf .upd-done { margin-top: 24px; }
.ntf .upd-done-msg { font-size: 15px; line-height: 1.6; }

@media (max-width: 734px) {
  /* bottom sheet: full width, rounded top corners, clear of the home indicator */
  dialog.ntf { width: 100%; max-height: calc(100svh - 24px); margin: auto 0 0; border-width: 1px 0 0; border-radius: 28px 28px 0 0; }
  .ntf-card { padding: 32px 22px calc(24px + env(safe-area-inset-bottom, 0px)); }
  .ntf-x { top: 12px; right: 12px; }
  .ntf-h { font-size: 26px; }
  html:lang(zh) .ntf-h { font-size: 24px; }
  .ntf .upd-row { flex-direction: column; }
  .ntf .upd-row input { flex: none; width: 100%; }
  .ntf .upd-row .btn { width: 100%; }
}

@media (prefers-reduced-motion: no-preference) {
  dialog.ntf[open] { animation: ntfIn .28s var(--ease); }
  dialog.ntf[open]::backdrop { animation: ntfFade .28s ease; }
  @media (max-width: 734px) { dialog.ntf[open] { animation-name: ntfSheet; } }
}
@keyframes ntfIn { from { opacity: 0; transform: translateY(12px) scale(.985); } }
@keyframes ntfSheet { from { transform: translateY(100%); } }
@keyframes ntfFade { from { opacity: 0; } }

/* App field label and note sizes (V3 04 §4.2 / §9.10) for the popup and updates.html: label = 11 mono, .1em, uppercase, quiet,
   12 above the input; consent, fine print and the form message = note 12. updates.html's base values live in site.css. */
:is(.ntf, body[data-page="updates"]) .upd-form label { margin-bottom: 12px; font: 500 11px/1.2 var(--font-ui); letter-spacing: .1em; text-transform: uppercase; color: var(--quiet); }
:is(.ntf, body[data-page="updates"]) :is(.upd-consent, .upd-fine) { font-size: 12px; line-height: 17px; }
:is(.ntf, body[data-page="updates"]) .upd-msg:not(:empty) { font-size: 12px; line-height: 17px; }
/* the popup lives outside <main>, so the site's Chinese phrase-break rule (hero-layout.css) is repeated for it */
html:lang(zh) dialog.ntf :is(p, label, h2) { word-break: keep-all; overflow-wrap: break-word; }

/* Popup size (owner 2026-11-11: "too small on the web; on phones use the App's size").
   Phone = App sheet values (V3 04 §4.2): sheet title 30 (ZH 28, site rule one step smaller), body 14, label 11, notes 12,
   input 46, full-width button 45 with 12 text. Tablet and desktop scale the same parts up, as the site does for its own type
   (desktop body = the page's lead size), keeping the App radii (sheet 28, input/button 14). */
@media (max-width: 734px) {
  .ntf-card { padding: 36px 20px calc(28px + env(safe-area-inset-bottom, 0px)); }
  .ntf-h { font-size: 30px; }
  html:lang(zh) .ntf-h { font-size: 28px; }
  .ntf-p { margin-top: 12px; font-size: 14px; line-height: 1.5; }
  .ntf .upd-form, .ntf .upd-done { margin-top: 28px; }
  .ntf .upd-row { gap: 12px; }
  .ntf .upd-row input { min-height: 46px; }
  .ntf .upd-row .btn { min-height: 45px; font-size: 12px; box-shadow: var(--shadow-ctrl); }
  .ntf .upd-done-msg { font-size: 14px; line-height: 1.5; }
}
@media (min-width: 735px) and (max-width: 1068px) {
  dialog.ntf { width: min(560px, calc(100% - 48px)); }
  .ntf-card { padding: 48px 40px 40px; }
  .ntf-x { top: 20px; right: 20px; width: 44px; height: 44px; }
  .ntf-kicker { font-size: 12px; margin-bottom: 16px; }
  .ntf-h { font-size: 34px; }
  html:lang(zh) .ntf-h { font-size: 30px; }
  .ntf-p { margin-top: 16px; font-size: 17px; line-height: 1.6; }
  .ntf .upd-form, .ntf .upd-done { margin-top: 32px; }
  dialog.ntf .upd-form label { font-size: 12px; }
  .ntf .upd-row { gap: 10px; }
  .ntf .upd-row input, .ntf .upd-row .btn { min-height: 52px; font-size: 16px; }
  .ntf .upd-row .btn { padding-inline: 24px; }
  dialog.ntf :is(.upd-consent, .upd-fine, .upd-msg:not(:empty)) { font-size: 13px; line-height: 19px; }
  .ntf .upd-done-msg { font-size: 17px; }
}
@media (min-width: 1069px) {
  dialog.ntf { width: min(640px, calc(100% - 64px)); }
  .ntf-card { padding: 56px 52px 48px; }
  .ntf-x { top: 22px; right: 22px; width: 44px; height: 44px; }
  .ntf-kicker { font-size: 13px; margin-bottom: 18px; }
  .ntf-h { font-size: 36px; }
  html:lang(zh) .ntf-h { font-size: 32px; }
  .ntf-p { margin-top: 18px; font-size: var(--fs-lead); line-height: 1.6; }
  .ntf .upd-form, .ntf .upd-done { margin-top: 36px; }
  dialog.ntf .upd-form label { font-size: 12px; margin-bottom: 14px; }
  .ntf .upd-row { gap: 12px; }
  .ntf .upd-row input { min-height: 56px; padding-inline: 20px; font-size: 17px; }
  .ntf .upd-row .btn { min-height: 56px; padding-inline: 28px; font-size: 16px; }
  dialog.ntf :is(.upd-consent, .upd-fine, .upd-msg:not(:empty)) { font-size: 14px; line-height: 21px; }
  .ntf .upd-consent { margin-top: 12px; }
  .ntf .upd-done-msg { font-size: var(--fs-lead); }
}
.ntf-h:focus { outline: none; }   /* focused by script on touch screens only, so the keyboard stays down */
/* phones: lift the sheet above the on-screen keyboard (--kb is set by site.js from visualViewport while the popup is open) */
@media (max-width: 734px) {
  dialog.ntf { margin-bottom: var(--kb, 0px); max-height: calc(100svh - 24px - var(--kb, 0px)); transition: margin-bottom .2s var(--ease); }
}

/* App sheet frame (V3 04 §9.9, globals.css .sheet / .sheetHead), owner 2026-11-11 "check the side spacing":
   every size: border #37373C, sheet colour #121214 (= page), radius 28.
   phones: the sheet is inset 8 from each screen edge, padding 29 / 24; the 44 close button sits in the header row,
   top-right on the content edge (top 29, right 24), level with the eyebrow. */
dialog.ntf { border-color: #37373c; background: #121214; }
@media (max-width: 734px) {
  dialog.ntf { width: calc(100% - 16px); margin: auto 8px var(--kb, 0px); border-width: 1px 1px 0; }
  .ntf-card { padding: 29px 24px calc(28px + env(safe-area-inset-bottom, 0px)); }
  .ntf-x { top: 29px; right: 24px; width: 44px; height: 44px; min-height: 44px; }
  .ntf-kicker { margin-right: 60px; }   /* App .sheetHead: header text keeps 16 clear of the button; button top = eyebrow top */
}
