/* ==========================================================================================
   screens/title.css — title screen: radar + ridgeline backdrop, dot-matrix emblem, big title,
   nickname console. Pure CSS/SVG art; an optional backdrop image fades in underneath.
   ========================================================================================== */

.title-screen { align-items: center; justify-content: center; }

/* ---- backdrop ----------------------------------------------------------------------------------- */
.title-bg { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.title-bg__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  object-position: center 30%;
  filter: saturate(.8) brightness(.9);
  transition: opacity 600ms ease;
}
.title-bg.has-art .title-bg__art { opacity: .8; }
/* The real backdrop already carries a radar + target point; keep only the sweep over it. */
.title-bg.has-art .title-bg__target { display: none; }
.title-bg.has-art .title-bg__radar { opacity: .35; }
.title-bg__ridge-art {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -.1rem;
  height: 3.3rem;
  background-repeat: repeat-x;
  background-position: center bottom;
  background-size: auto 100%;
  opacity: 0;
  transition: opacity 600ms ease;
}
.title-bg.has-ridges .title-bg__ridge-art { opacity: 1; }
.title-bg__ridges { animation: fade-in 600ms ease backwards; }
@keyframes fade-in { from { opacity: 0; } }
.title-bg__glow {
  position: absolute;
  left: -10%;
  right: -10%;
  bottom: 0;
  height: 6rem;
  background:
    radial-gradient(48% 42% at 50% 78%, rgba(23, 249, 183, .40), rgba(23, 249, 183, .08) 62%, transparent 76%),
    radial-gradient(26% 26% at 50% 80%, rgba(120, 255, 215, .30), transparent 70%);
  filter: blur(6px);
  animation: glow-breathe 7s ease-in-out infinite;
}
@keyframes glow-breathe { 50% { opacity: .78; } }

.title-bg__radar {
  position: absolute;
  left: 17%;
  top: 40%;
  width: 5.6rem;
  height: 5.6rem;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background:
    radial-gradient(circle, transparent 0 .05rem, rgba(78, 216, 175, .5) .05rem .065rem, transparent .065rem),
    repeating-radial-gradient(circle, transparent 0 .69rem, rgba(78, 216, 175, .16) .69rem .7rem),
    linear-gradient(rgba(78, 216, 175, .12), rgba(78, 216, 175, .12)) center / 100% 1px no-repeat,
    linear-gradient(rgba(78, 216, 175, .12), rgba(78, 216, 175, .12)) center / 1px 100% no-repeat;
  -webkit-mask-image: radial-gradient(circle, #000 55%, transparent 71%);
  mask-image: radial-gradient(circle, #000 55%, transparent 71%);
  opacity: .8;
}
.title-bg__sweep {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  inset: 0;
  border-radius: 50%;
  /* The bright edge must LEAD and the glow must trail BEHIND it. A conic gradient's angle grows
     clockwise from 0deg (12 o'clock), and radar-sweep rotates clockwise too — so the bright end has
     to sit at 100% (== 0deg) and fade counter-clockwise from there. Written the other way round
     (bright at 0% fading to 22%) the glow fans out AHEAD of the beam and the sweep reads backwards. */
  background: conic-gradient(from 0deg, transparent 0 78%, rgba(23, 249, 183, .28) 100%);
  animation: radar-sweep 6s linear infinite;
}
@keyframes radar-sweep { to { transform: rotate(360deg); } }

.title-bg__target {
  position: absolute;
  right: 12%;
  top: 22%;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 50%;
  background:
    radial-gradient(circle, rgba(246, 163, 41, .9) 0 .06rem, transparent .065rem),
    radial-gradient(circle, transparent 0 .2rem, rgba(246, 163, 41, .5) .2rem .215rem, transparent .215rem),
    radial-gradient(circle, transparent 0 .5rem, rgba(246, 163, 41, .22) .5rem .51rem, transparent .51rem),
    radial-gradient(circle, rgba(246, 163, 41, .18), transparent 70%);
  animation: target-pulse 3.2s ease-in-out infinite;
}
.title-bg__target::after {
  content: 'TARGET POINT';
  position: absolute;
  left: 110%;
  top: 50%;
  transform: translateY(-50%);
  padding: .02rem .08rem;
  border: 1px solid rgba(246, 163, 41, .35);
  font-family: var(--font-display);
  font-size: .1rem;
  letter-spacing: .2em;
  color: rgba(246, 163, 41, .7);
  white-space: nowrap;
}
@keyframes target-pulse { 50% { transform: scale(1.06); opacity: .75; } }

.title-bg__ridges { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: 40%; }
.title-bg__ridges .ridge { stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.title-bg__ridges .ridge--far { opacity: .95; }
.title-bg__haze {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(12, 15, 14, .6) 0%, transparent 25%, transparent 70%, rgba(6, 8, 7, .7) 100%),
    radial-gradient(46% 42% at 50% 44%, rgba(10, 13, 12, .82), rgba(10, 13, 12, .4) 60%, transparent 80%);
}

/* ---- corners ------------------------------------------------------------------------------------- */
.title-corner { position: absolute; z-index: 2; display: flex; align-items: flex-start; gap: .12rem; line-height: 1.7; }
.title-corner--tl { left: .44rem; top: .38rem; }
.title-corner--tr { right: .44rem; top: .38rem; text-align: right; }
.title-corner__mark {
  width: .32rem;
  height: .32rem;
  margin-top: .02rem;
  border: 1px solid var(--mint-700);
  background:
    linear-gradient(var(--mint-500), var(--mint-500)) center / 40% 2px no-repeat,
    linear-gradient(var(--mint-500), var(--mint-500)) center / 2px 40% no-repeat;
  clip-path: polygon(25% 0, 75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%);
}

/* ---- centre column ------------------------------------------------------------------------------- */
.title-main {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: -.3rem;
}

.emblem { position: relative; display: flex; align-items: center; gap: .26rem; margin-bottom: .26rem; animation: rise-in 600ms var(--ease-out) backwards; }
.emblem__svg { width: 1.3rem; height: 1.4rem; overflow: visible; filter: drop-shadow(0 0 .12rem rgba(210, 255, 240, .25)); }
.emblem__svg circle { fill: #dfe6e2; animation: dot-twinkle 4.8s ease-in-out infinite; }
.emblem__svg circle.d1 { animation-delay: -.7s; }
.emblem__svg circle.d2 { animation-delay: -1.4s; }
.emblem__svg circle.d3 { animation-delay: -2.1s; }
.emblem__svg circle.d4 { animation-delay: -2.8s; }
.emblem__svg circle.d5 { animation-delay: -3.5s; }
.emblem__svg circle.d6 { animation-delay: -4.2s; }
.emblem__svg circle.is-accent { fill: var(--mint-glow); filter: drop-shadow(0 0 .04rem var(--mint-glow)); animation: none; }
@keyframes dot-twinkle { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.emblem__bracket { width: .16rem; height: 1.7rem; border: 2px solid rgba(223, 230, 226, .45); }
.emblem__bracket--l { border-right: 0; }
.emblem__bracket--r { border-left: 0; }

.title-en {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .02rem;
  font-family: var(--font-display);
  text-transform: uppercase;
  line-height: 1;
  animation: rise-in 600ms 80ms var(--ease-out) backwards;
}
.title-en__a { font-size: .34rem; font-weight: 500; letter-spacing: .3em; padding-left: .3em; color: #cdd6d1; }
.title-en__b {
  font-size: .38rem;
  font-weight: 700;
  letter-spacing: .34em;
  padding-left: .34em;
  color: var(--mint-500);
  text-shadow: 0 0 .18rem rgba(23, 249, 183, .45);
}
.title-cn {
  margin-top: .14rem;
  font-size: 1.02rem;
  font-weight: 900;
  line-height: 1.12;
  letter-spacing: .06em;
  color: #f4f6f5;
  text-shadow: 0 .04rem .2rem rgba(0, 0, 0, .7);
  animation: rise-in 600ms 140ms var(--ease-out) backwards;
}
.title-cn__colon { color: #f4f6f5; }
/* a title in an alphabetic script (English …; screens/title.js): the display face, smaller so "Stronghold Protocol: Alliance" fits one line */
.title-cn--latin { font-family: var(--font-display); font-size: .6rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; }
.title-cn em { font-style: normal; color: var(--mint-500); text-shadow: 0 0 .26rem rgba(23, 249, 183, .45); }
.title-tag {
  margin-top: .12rem;
  font-size: .19rem;
  color: var(--text-lo);
  letter-spacing: .1em;
  animation: rise-in 600ms 200ms var(--ease-out) backwards;
}
@keyframes rise-in { from { opacity: 0; transform: translateY(.14rem); } }

.title-login {
  --bk-c: var(--mint-500);
  position: relative;
  width: 4.9rem;
  margin-top: .42rem;
  display: flex;
  flex-direction: column;
  gap: .16rem;
  padding: .24rem .28rem .2rem;
  background: linear-gradient(180deg, rgba(20, 25, 23, .82), rgba(10, 13, 12, .88));
  border: 1px solid var(--line-2);
  box-shadow: 0 .2rem .5rem rgba(0, 0, 0, .5), 0 0 .5rem rgba(23, 249, 183, .06);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  animation: rise-in 600ms 260ms var(--ease-out) backwards;
}
.title-login::before {
  content: '';
  position: absolute;
  left: -1px;
  right: -1px;
  top: -1px;
  height: 2px;
  background: linear-gradient(90deg, var(--mint-500), transparent 60%);
}
.title-login .btn--xl { letter-spacing: .6em; padding-left: calc(.48rem + .3em); }
.title-invite {
  display: flex;
  align-items: center;
  gap: .08rem;
  padding: .08rem .12rem;
  background: rgba(246, 163, 41, .08);
  border: 1px solid rgba(246, 163, 41, .35);
  color: var(--amber);
  font-size: .16rem;
}
.title-invite .icon { width: .2rem; height: .2rem; }
.title-invite b { font-size: .2rem; letter-spacing: .2em; color: #ffd08a; }
.title-conn { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .08rem .1rem; min-height: .32rem; font-size: .14rem; color: var(--text-lo); }
.title-conn__status, .title-conn__metrics, .title-conn__actions { display: inline-flex; align-items: center; gap: .08rem; white-space: nowrap; }
/* language menu (中文 | English | …, ui/lang.js) in the top-right corner; more than four languages make it a list */
.title-lang { display: inline-flex; margin-bottom: .1rem; }
.title-lang button { min-width: .74rem; height: .3rem; font-size: .14rem; cursor: pointer; }
.lang-select select { height: .38rem; min-width: 1.6rem; padding: 0 .12rem; background: #0a0d0c; border: 0; color: var(--text-hi); font-size: .16rem; cursor: pointer; }
.title-lang.lang-select select { height: .3rem; font-size: .14rem; }
html[data-script="alphabetic"] .title-login .btn--xl { letter-spacing: .3em; }
.title-conn .ping { height: .26rem; font-size: .15rem; }
.title-conn .online-pill { height: .26rem; }
.title-conn .online-pill__value { font-size: .15rem; }

.title-foot {
  position: absolute;
  z-index: 2;
  left: .44rem;
  right: .44rem;
  bottom: .3rem;
  display: flex;
  flex-wrap: wrap;
  gap: .06rem .24rem;
  justify-content: space-between;
  align-items: flex-end;
  font-size: .13rem;
  color: var(--text-dim);
}
/* a development build (shared/constants.js DEV_BUILD): an unmissable tag in the footer */
.title-dev {
  padding: .03rem .1rem;
  border: 1px solid #ff9f43;
  border-radius: .04rem;
  color: #ffb066;
  background: rgba(255, 159, 67, .14);
  font-weight: 700;
  letter-spacing: .02em;
}
/* the operator's own notice sits above the required credit line */
.title-foot__legal { display: flex; flex-direction: column; gap: .03rem; align-items: flex-start; line-height: 1.5; }
.title-foot__link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: .025rem;
  transition: color .15s ease, text-shadow .15s ease;
}
.title-foot__link:hover, .title-foot__link:focus-visible {
  color: var(--amber);
  text-shadow: 0 0 .09rem rgba(246, 163, 41, .5);
}

/* ---- 公告 (announcement; js/ui/notice.js) -------------------------------------------------------- */
/* The trigger is GuideButton's twin (ghost/sm Button, mint icon) and the panel is the shared Modal
   (.modal__box / .modal__body / .modal__actions in components.css), so only its content lives here: the small dim
   section labels and their lines from data/notice.json, scrolled by .modal__body when the body is long. */
.notice-btn .btn__icon { color: var(--mint-500); }
.notice__body { display: flex; flex-direction: column; gap: .18rem; flex: 1 1 auto; min-width: 0; }
/* One section of the notice: the label row, then its lines. The flat legacy `body` form is one unlabelled section. */
.notice__section { display: flex; flex-direction: column; gap: .06rem; }
/* The section label: the project's .micro idiom (theme.css) — small, dim, letter-spaced — as a row of its own above
   the content it names. No box, no bar: the tone alone separates it. */
.notice__label {
  margin: 0;
  font-family: var(--font-display);
  font-size: .12rem;
  line-height: 1.4;
  letter-spacing: .18em;
  color: var(--text-dim);
}
.notice__line { margin: 0; font-size: .18rem; line-height: 1.75; color: var(--text-md); }
/* A grouping blank line ({"spacer":true} in data/notice.json): taller than the flex gap so the groups it separates
   read as groups. aria-hidden in notice.js — it carries no text. */
.notice__line--spacer { height: .1rem; }
/* An inline link inside a line. The href was whitelisted by notice.js safeNoticeHref() before this element ever
   existed, so this rule only sets the tone: mint text with a plain underline. NO fill, NO background, NO border, NO
   box-shadow, NO padding — nothing that would draw a box around the text. It opens in a new tab without handing the
   opened page a window.opener handle. */
.notice__link {
  color: var(--mint-500);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .03rem;
  overflow-wrap: anywhere;
  transition: color .15s ease;
}
.notice__link:hover, .notice__link:focus-visible { color: var(--mint-glow); }
.notice__hint { margin: 0 0 .04rem; font-size: .15rem; color: var(--text-lo); }
.notice__updated { margin: 0; font-family: var(--font-num); font-size: .14rem; letter-spacing: .08em; color: var(--text-dim); }
@media (max-height: 560px) {
  .notice__line { font-size: .16rem; }
}

/* ---- 赞助 (support; js/ui/sponsor.js) -------------------------------------------------------------- */
/* The 公告 dialog is two columns: the operator's text on the left, the sponsorship QR on the right. The QR is the
   operator's own screenshot (two panels side by side), scaled to its column and never cropped or distorted; on a
   narrow screen the dialog stacks again, text first. The column is wide on purpose (operator, 2026-10-07: 「图片大一点，
   太小了」) — the dialog width in ui/notice.js is sized so the text column does not lose anything to it. */
.notice__layout { display: flex; align-items: flex-start; gap: .32rem; }
.notice__side { flex: 0 0 5.6rem; min-width: 0; }
.sponsor { display: flex; flex-direction: column; gap: .12rem; }
.sponsor__qr {
  display: block;
  width: 100%;
  height: auto;
  border-radius: .06rem;
  background: #fff; /* the QR is drawn on white in the screenshot; keep the edges clean while it loads */
}
.sponsor__hint { margin: 0; font-size: .15rem; line-height: 1.7; color: var(--text-md); text-align: center; }
@media (max-width: 760px) {
  .notice__layout { flex-direction: column; }
  .notice__side { flex: none; width: 100%; max-width: 6.6rem; }
}

/* preload: the home screen entry (public/js/ui/resourcePanel.js) */
.title-preload { position: absolute; z-index: 3; right: .44rem; bottom: .86rem; }
.res-pill { width: 2.7rem; padding: .1rem .12rem; background: rgba(10, 14, 12, .74); border: 1px solid var(--line-2); }
.res-pill.is-on { border-color: var(--mint-800); background: rgba(13, 20, 17, .86); }
.res-pill__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: .12rem; width: 100%;
  padding: 0; background: none; border: 0; color: var(--text-hi); font-size: .15rem; text-align: left; cursor: pointer;
}
.res-pill__head:disabled { cursor: default; }
.res-pill__label { display: flex; align-items: baseline; gap: .06rem; }
.res-pill.is-on .res-pill__label { color: var(--mint-400); }
.res-pill__label .micro { color: var(--text-dim); }
.res-pill__state { font-size: .14rem; color: var(--mint-400); white-space: nowrap; }
.res-pill__body { display: flex; flex-direction: column; gap: .07rem; margin-top: .09rem; }
.res-pill__body .pbar { min-width: 0; }
.res-pill__text { margin: 0; font-size: .13rem; line-height: 1.6; color: var(--text-md); }
.res-pill__text.is-dim { color: var(--text-dim); }
.res-pill__text.is-warn { color: var(--amber); }
.res-pill__hint { margin: .06rem 0 0; font-size: .13rem; line-height: 1.6; color: var(--text-dim); }
.res-pill:hover .res-pill__hint { color: var(--text-md); }
