/* Rainsong Guild Dashboard — "The Deep Culvert" (see DESIGN.md).
   Dark-only by decision; data is the light source. */

@font-face {
  font-family: 'TCF Display';
  src: url('/static/fonts/TCFDisplay.ttf') format('truetype');
  font-weight: normal; font-style: normal; font-display: swap;
}

:root { color-scheme: dark; }
html, body { margin: 0; padding: 0; }
table { border-collapse: collapse; width: 100%; }
.num { font-variant-numeric: tabular-nums; }

body.dv {
  --panel-a: rgba(24,36,62,0.72); --panel-b: rgba(14,22,40,0.72);
  --panel-head: rgba(12,20,38,0.65);
  --line: rgba(140,180,255,0.28); --line-soft: rgba(140,180,255,0.09);
  --line-mid: rgba(140,180,255,0.2);
  --text: #e8eefc; --muted: #a6bbde; --faint: #85a0c8; --dim: #6d84ab;
  --accent: #3ba7e6; --accent-hi: #6cc4ef;
  --gold: #ffd95e; --silver: #d7e3f4; --bronze: #e8a566; --up: #7fe0a8;
  --radius: 16px;
  --head-font: 'TCF Display', Arial, sans-serif;
  font-family: 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  background:
    radial-gradient(1200px 500px at 50% -100px, rgba(56,110,190,0.22), transparent 65%),
    radial-gradient(900px 700px at 85% 108%, rgba(30,60,110,0.18), transparent 60%),
    linear-gradient(180deg, #0a0d14 0%, #0d1220 55%, #0a0e18 100%);
  background-color: #0b0e14; background-attachment: fixed;
  color: var(--text); min-height: 100vh; padding-bottom: 72px;
}
.wrap { max-width: 1100px; margin: 0 auto; padding: 0 24px; }

a { color: var(--accent); }
a:focus-visible, button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* --- masthead ------------------------------------------------------------ */
.mast { padding-top: 32px; display: flex; align-items: baseline; gap: 26px; flex-wrap: wrap; }
.wordmark, .wordmark a {
  font-family: var(--head-font); font-size: clamp(34px, 4.5vw, 48px);
  line-height: 1; letter-spacing: 0.01em; text-decoration: none;
  background: linear-gradient(180deg, #a9d5f5 0%, #55a0e0 48%, #2f66b5 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.mast nav { margin-left: auto; display: flex; gap: 22px; flex-wrap: wrap; }
.mast nav a { color: var(--muted); text-decoration: none; font-size: 14.5px; font-weight: 700; padding: 4px 0; border-bottom: 2px solid transparent; }
.mast nav a.here { color: #fff; border-bottom-color: var(--accent); }
.mast nav a:hover { color: #fff; }
.officer-mark {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--faint); border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px;
  align-self: center;
}
.subbar {
  margin-top: 16px; padding: 12px 0; border-top: 1px solid var(--line-mid); border-bottom: 1px solid var(--line-mid);
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}
.subbar .week { font-size: 14px; color: var(--muted); }
.subbar .week b { color: var(--text); font-weight: 600; }
.chips { margin-left: auto; display: flex; gap: 10px; flex-wrap: wrap; }
.chip {
  display: flex; align-items: baseline; gap: 7px; padding: 6px 13px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--panel-b);
  font-size: 13px; color: var(--faint);
}
.chip b { color: var(--accent-hi); font-size: 14.5px; font-weight: 600; }
.chip b.gold { color: var(--gold); }

/* --- panels -------------------------------------------------------------- */
.grid { display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 22px; }
.rail { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; }
.rail2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 900px) { .rail, .rail2 { grid-template-columns: 1fr; } }

.panel {
  background: linear-gradient(180deg, var(--panel-a), var(--panel-b));
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 10px 30px rgba(0,0,0,0.42); overflow: hidden;
}
.phead {
  display: flex; align-items: baseline; gap: 14px; padding: 12px 18px;
  background: var(--panel-head); border-bottom: 1px solid var(--line-mid);
}
.phead h1, .phead h2 { margin: 0; font-family: var(--head-font); font-size: 17px; letter-spacing: 0.08em; color: #cfe2ff; font-weight: normal; }
.phead .meta { font-size: 12.5px; color: var(--faint); }
.phead .right { margin-left: auto; font-size: 13px; color: var(--accent-hi); font-weight: 600; }
.pad { padding: 12px 18px; }

/* --- tables -------------------------------------------------------------- */
th { text-align: left; padding: 0; border-bottom: 1px solid var(--line-mid); }
th .colhead, th .sort {
  display: inline-flex; align-items: center; gap: 5px; width: 100%; box-sizing: border-box;
  padding: 9px 18px;
  font: 600 10.5px/1 'Segoe UI', Arial, sans-serif; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--faint);
}
th .sort { background: none; border: none; cursor: pointer; }
th .sort:hover { color: var(--text); }
th .sort:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
th .arr { font-size: 9px; opacity: 0.45; }
th[aria-sort] .sort { color: var(--accent-hi); }
th[aria-sort] .arr { opacity: 1; }
th.num-h .colhead, th.num-h .sort { justify-content: flex-end; text-align: right; }
td { padding: 11px 18px; border-bottom: 1px solid var(--line-soft); font-size: 14.5px; }
tr:last-child td { border-bottom: 0; }
td.n { text-align: right; }
.rank { font-family: var(--head-font); font-size: 17px; width: 40px; color: #6b82a8; }
.r1 .rank { color: var(--gold); } .r2 .rank { color: var(--silver); } .r3 .rank { color: var(--bronze); }
.r1 td { background: rgba(255,255,255,0.03); }
.ign { font-weight: 600; color: #fff; }
td.ign a, .ign a { color: #fff; text-decoration: none; }
td.ign a:hover, .ign a:hover { color: var(--accent-hi); }
.liberation-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-left: 7px; vertical-align: -5px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 28%, rgba(255, 236, 175, 0.9), rgba(255, 217, 94, 0.12) 70%),
    rgba(255, 217, 94, 0.06);
  border: 1px solid rgba(255, 217, 94, 0.6);
  box-shadow:
    0 0 6px rgba(255, 217, 94, 0.45),
    0 2px 8px rgba(0, 0, 0, 0.3),
    inset 0 0 4px rgba(255, 236, 175, 0.4);
  transition: box-shadow 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.liberation-badge img { display: block; width: 18px; height: 18px; image-rendering: auto; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5)); }
.liberation-badge:hover {
  border-color: var(--gold);
  box-shadow:
    0 0 10px rgba(255, 217, 94, 0.7),
    0 2px 10px rgba(0, 0, 0, 0.32),
    inset 0 0 5px rgba(255, 236, 175, 0.55);
  transform: scale(1.08);
}
/* A liberation whose class has no Destiny weapon mapped yet: the ring alone
   still marks the achievement, filled so it doesn't read as a loading state. */
.liberation-badge-bare {
  background:
    radial-gradient(circle at 32% 28%, rgba(255, 236, 175, 0.55), rgba(255, 217, 94, 0.28) 75%);
}
.cls { color: var(--muted); font-size: 13px; }
.lv { color: var(--muted); font-size: 13.5px; text-align: right; width: 44px; }
.score { text-align: right; font-weight: 600; color: var(--accent-hi); }
.delta { text-align: right; font-size: 12.5px; color: var(--faint); }
.delta.up { color: var(--up); }
.mutecell { color: var(--muted); font-size: 13.5px; }
.gapcell { color: var(--dim); font-size: 12.5px; }
.goldcell { color: var(--gold); font-weight: 600; text-align: right; }

/* zero-group: present but didn't run — information, not filler */
.zerohead { padding: 12px 18px 4px; color: var(--muted); font-size: 13px; border-top: 1px dashed var(--line); margin: 0; }
.zerohead b { color: var(--text); }
.zeronames { padding: 0 18px 14px; margin: 0; color: var(--dim); font-size: 12.5px; line-height: 1.8; }
.zeronames a { color: var(--accent); text-decoration: none; }
.zeronames a:hover { text-decoration: underline; }
.zeronames details { display: inline; }
.zeronames summary { display: inline; cursor: pointer; color: var(--accent); list-style: none; }
.zeronames summary::-webkit-details-marker { display: none; }
.zeronames details[open] summary { display: none; }

/* --- notables ------------------------------------------------------------ */
.note { display: flex; align-items: baseline; gap: 10px; padding: 9px 18px; border-bottom: 1px solid var(--line-soft); font-size: 13.5px; }
.note:last-child { border-bottom: 0; }
.note .tag { flex: 0 0 auto; font-size: 10.5px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); width: 92px; }
.note b { color: #fff; }
.note b a { color: #fff; text-decoration: none; }
.note b a:hover { color: var(--accent-hi); }
.note .val { margin-left: auto; color: var(--accent-hi); font-weight: 600; white-space: nowrap; padding-left: 10px; }
.note .val.gold { color: var(--gold); }
.note .val.up { color: var(--up); }

.flagline { font-size: 13.5px; line-height: 1.65; color: var(--muted); margin: 0; }
.flagline .fp { color: var(--gold); font-weight: 600; }
.flagline b { color: #fff; }
.flagline b a { color: #fff; text-decoration: none; }
.flagline b a:hover { color: var(--accent-hi); }
.chartnote { padding: 0 18px 12px; margin: 4px 0 0; color: var(--faint); font-size: 11.5px; }
svg text { font-family: 'Segoe UI', Arial, sans-serif; }
.bar { fill: var(--accent); fill-opacity: 0.45; cursor: default; }
.bar.now { fill: var(--accent); fill-opacity: 1; }
.bar:hover { fill-opacity: 0.75; }
.bar.now:hover { fill-opacity: 1; }

.chartwrap { position: relative; }
.charttip {
  position: absolute;
  transform: translate(-50%, -100%) translateY(-8px);
  background: #0d1220;
  border: 1px solid rgba(140, 180, 255, 0.3);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 11px;
  color: #fff;
  white-space: pre-line;
  text-align: center;
  line-height: 1.4;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  z-index: 5;
}
.charttip.show { opacity: 1; visibility: visible; }

/* --- member page --------------------------------------------------------- */
.hero { margin-top: 22px; display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; }
.hero h1 {
  margin: 0; font-family: var(--head-font); font-weight: normal;
  font-size: clamp(28px, 4vw, 40px); line-height: 1; letter-spacing: 0.01em;
  color: var(--text); text-transform: uppercase;
}
.hero .sub { font-size: 14.5px; color: var(--muted); }
.hero .sub b { color: var(--text); font-weight: 600; }
/* the in-table badge (20px) reads as debris next to the hero's display-size
   h1 — scale it up to sit against that face instead of resizing globally */
.hero h1 .liberation-badge {
  width: 30px; height: 30px; margin-left: 12px; vertical-align: -7px;
}
.hero h1 .liberation-badge img { width: 26px; height: 26px; }
.statrow { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }

/* --- charts (uPlot) ------------------------------------------------------ */
.chartscroll { overflow-x: auto; padding: 10px 18px 4px; }
.chartbox { min-height: 200px; }
.chartctl { display: flex; gap: 8px; align-items: center; padding: 0 18px 12px; flex-wrap: wrap; }
.chartctl .winbtn {
  background: var(--panel-b); border: 1px solid var(--line); border-radius: 999px;
  color: var(--faint); font: 600 11px/1 'Segoe UI', Arial, sans-serif;
  letter-spacing: 0.1em; text-transform: uppercase; padding: 6px 13px; cursor: pointer;
}
.chartctl .winbtn:hover { color: var(--text); }
.chartctl .winbtn[aria-pressed="true"] { color: var(--accent-hi); border-color: var(--accent); }
.chartctl .hint { margin-left: auto; font-size: 11.5px; color: var(--dim); }
.uplot { font-family: 'Segoe UI', Arial, sans-serif; }
.u-legend { font-size: 11.5px; color: var(--faint); }
.u-legend .u-value { color: var(--accent-hi); font-variant-numeric: tabular-nums; }
.u-select { background: rgba(59,167,230,0.16); }

/* --- forms (officer period report — read-only GET range picker) --------- */
.rangeform { display: flex; align-items: end; gap: 14px; flex-wrap: wrap; }
.rangeform label { display: flex; flex-direction: column; gap: 5px; font-size: 10.5px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); }
.rangeform input[type="date"] {
  background: var(--panel-b); border: 1px solid var(--line); border-radius: 8px;
  color: var(--text); font: 14px 'Segoe UI', Arial, sans-serif; padding: 7px 10px;
  color-scheme: dark;
}
.rangeform input[type="date"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rangeform button {
  background: var(--accent); border: none; border-radius: 999px; cursor: pointer;
  color: #06121f; font: 600 13px 'Segoe UI', Arial, sans-serif; padding: 9px 18px;
}
.rangeform button:hover { background: var(--accent-hi); }
.rangeform .presets { display: flex; gap: 10px; align-items: center; font-size: 12.5px; padding-bottom: 9px; }

/* On narrow screens wide tables scroll inside their panel — the page body
   never scrolls sideways. */
@media (max-width: 700px) {
  .panel table {
    display: block; overflow-x: auto; white-space: nowrap;
    -webkit-overflow-scrolling: touch;
  }
}

/* --- misc ---------------------------------------------------------------- */
.prose { padding: 14px 18px; font-size: 14.5px; line-height: 1.5; color: var(--muted); }
.prose b { color: var(--text); }
.namecloud { padding: 4px 18px 14px; margin: 0; font-size: 13px; line-height: 1.9; color: var(--muted); }
.namecloud a { color: var(--text); text-decoration: none; font-weight: 600; }
.namecloud a:hover { color: var(--accent-hi); }
.eranote { margin: 14px 0 0; font-size: 12px; color: var(--dim); }
.searchbox {
  background: var(--panel-b); border: 1px solid var(--line); border-radius: 999px;
  color: var(--text); font: 14px 'Segoe UI', Arial, sans-serif; padding: 8px 16px; width: 240px; max-width: 100%;
}
.searchbox::placeholder { color: var(--dim); }
.searchbox:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.warn { color: var(--bronze); }
.ok { color: var(--up); }
.footer { margin-top: 40px; font-size: 12px; color: var(--dim); text-align: center; }
.footer a { color: var(--faint); }

/* tombstone */
.tomb { max-width: 560px; margin: 60px auto 0; text-align: center; }
.tomb .panel { padding: 36px 28px; }
.tomb h1 { margin: 0 0 6px; font-family: var(--head-font); font-weight: normal; font-size: 34px; color: var(--text); text-transform: uppercase; }
.tomb .rest { font-size: 13px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); margin: 0 0 18px; }
.tomb p { color: var(--muted); font-size: 14.5px; line-height: 1.6; margin: 10px 0 0; }
.tomb b { color: var(--text); }

/* stat card page */
.cardwrap { max-width: 680px; margin: 40px auto 0; }
.bignum { font-family: var(--head-font); font-size: clamp(26px, 4.5vw, 40px); line-height: 1; color: var(--accent-hi); }
.bignum.gold { color: var(--gold); }
.cardstats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; margin-top: 20px; }
@media (max-width: 640px) { .cardstats { grid-template-columns: 1fr; } }
.cardstat { text-align: center; padding: 22px 12px; }
.cardstat .lab { font-size: 10.5px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); margin-top: 10px; }
.cardstat .when { font-size: 12px; color: var(--dim); margin-top: 4px; }

/* PB ranking ladders (member page) */
.laddertable .rank { font-size: 15px; }
.merow td { background: rgba(59, 167, 230, 0.10); }
.merow .ign { color: var(--accent-hi); font-weight: 600; }
.merow .rank { color: var(--accent-hi); }

/* best guild week (guild page) */
.bigweek { text-align: center; padding-top: 26px; padding-bottom: 26px; }
.bigweek .bignum { font-size: clamp(34px, 5.5vw, 56px); }
.bigweek .flagline { margin-top: 12px; }
.panel.vcenter { display: flex; flex-direction: column; }
.panel.vcenter .bigweek { flex: 1; display: flex; flex-direction: column; justify-content: center; }

/* full-width stat card with share icon (member page) */
.sharecard { position: relative; }
.sharecard img { display: block; width: 100%; height: auto; border-radius: 14px; }
.shareicon {
  position: absolute; top: 14px; right: 14px; display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 50%; color: var(--accent-hi);
  background: rgba(13, 18, 32, 0.75); border: 1px solid var(--line);
}
.shareicon:hover { color: #fff; border-color: var(--accent); }
.shareicon:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }

/* character avatars (Nexon render via /avatar/, class thumbnail fallback) */
.avatar {
  width: 28px; height: 28px; border-radius: 50%; object-fit: cover; object-position: 50% 12%;
  vertical-align: middle; margin-right: 9px; background: #121b30; border: 1px solid var(--line);
}
.avatar-lg { width: 84px; height: 84px; margin-right: 0; align-self: center; border-color: var(--accent); }
.toast {
  position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); z-index: 40;
  background: var(--panel-b, #18243e); color: var(--text, #e8eefc);
  border: 1px solid var(--accent); border-radius: 999px; padding: 11px 22px;
  font-size: 13.5px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  opacity: 1; transition: opacity 0.45s ease;
}
.toast.gone { opacity: 0; }

/* --- the gathering (a whole page, not a panel) ---------------------------- */
/* The scene is the page: it runs edge to edge from the very top, the masthead
   rides on top of the artwork, and the bottom edge dissolves into the ground
   so there is no frame anywhere. Everything the visitor needs to read the
   picture is set on it or directly under it. */
body.stagepage { padding-bottom: 0; }
body.stagepage .wrap { max-width: none; padding: 0; position: relative; }
/* out of flow, so the stage starts at the top of the document with no offset */
body.stagepage header { position: absolute; top: 0; left: 0; right: 0; z-index: 6; }
body.stagepage .mast,
body.stagepage .footer,
.g-read-in { max-width: 1340px; margin: 0 auto; box-sizing: border-box; padding-left: clamp(20px, 3.4vw, 46px); padding-right: clamp(20px, 3.4vw, 46px); }
body.stagepage .mast { padding-top: 26px; }
/* chrome sitting on artwork: lift it off the picture without a bar */
body.stagepage .wordmark { display: none; }
body.stagepage .mast nav a { color: #c8dbf5; text-shadow: 0 1px 12px rgba(0, 0, 0, 0.85); }
body.stagepage .mast nav a:hover, body.stagepage .mast nav a.here { color: #fff; }
/* the page keeps one left edge all the way down, footer included */
body.stagepage .footer {
  margin-top: 58px; padding-top: 20px; padding-bottom: 58px; text-align: left;
  border-top: 1px solid var(--line-soft);
}

.gwrap { position: relative; }
.g-stage { position: relative; }
.gathering { position: relative; background: #05070c; overflow: hidden; margin: 0 auto; }
/* The crowd is now baked the same way the world underneath it is: painted
   only when hover, pin, search, sort, a scene change or an unsettled ease
   actually changes the picture, then carried through the ambient rock by a
   compositor transform same as the terrain layer. Oversized versus the stage
   (padding added in JS, mirroring PAD_X/PAD_Y below) for the same reason the
   background canvases are — a rocking transform must never uncover a bare
   edge. Left/top/width/height are set from JS once the pad is known; this
   rule only supplies the stacking and the cursor. */
.gathering canvas.g-cv { display: block; position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; cursor: crosshair; }
/* The still world — sky, parallax layers, terrain — baked once and only ever
   moved by a compositor transform. Oversized versus the stage (padding added
   in JS) so panning it never uncovers a bare edge; pointer events pass
   straight through to the picking canvas above it. */
.gathering canvas.g-bgcv { display: block; position: absolute; z-index: 1; pointer-events: none; }
/* The one thing that still can't be baked: ~60 motes drifting on their own
   clocks. Kept on its own canvas, unpadded and untransformed, so paying for
   it in full every frame never forces the (far more expensive) crowd above
   it to repaint too. Sits above the sprites and below the vignette purely by
   coming after canvas.g-cv in the document — same stacking context, so
   paint order alone settles it without another z-index to keep track of. */
.gathering canvas.g-motecv { display: block; position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; }

/* Scrims, not a frame. A soft wash off the top-left corner carries the title
   and the masthead; the last tenth of the picture melts into the page ground.
   The crowd stands low and wide, so nothing here reaches into it. */
.g-veil {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(4, 7, 13, 0.82) 0%, rgba(4, 7, 13, 0.34) 9%, transparent 20%),
    radial-gradient(112% 78% at -6% 4%, rgba(4, 7, 13, 0.9) 0%, rgba(4, 7, 13, 0.5) 40%, transparent 72%),
    linear-gradient(180deg, transparent 84%, rgba(9, 13, 23, 0.5) 94%, #0a0e18 100%),
    /* the vignette: a still scrim, so it is composited once here rather than
       filled across the whole canvas on every frame */
    radial-gradient(circle at 50% 52%, transparent 32%, rgba(0, 0, 0, 0.5) 100%);
}

/* the title lockup, set on the dark forest at the left of every scene */
.g-lock {
  position: absolute; z-index: 5; top: clamp(104px, 13vh, 158px);
  left: max(calc(50% - 670px + clamp(20px, 3.4vw, 46px)), clamp(20px, 3.4vw, 46px));
  width: min(46ch, 44vw);
}
.g-place { display: flex; align-items: baseline; gap: 9px; margin: 0 0 14px; }
.g-place b, .g-place span {
  font: 600 11px 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  letter-spacing: 0.2em; text-transform: uppercase;
}
.g-place b { color: var(--text); }
.g-place b::after { content: "·"; margin-left: 9px; color: var(--dim); letter-spacing: 0; }
.g-place span { color: var(--faint); }
.g-title {
  margin: 0; font-family: var(--head-font); font-weight: normal;
  font-size: clamp(42px, 5.5vw, 84px); line-height: 0.96; letter-spacing: 0.005em;
  text-transform: uppercase; color: #f2f7ff;
  text-shadow: 0 4px 34px rgba(0, 0, 0, 0.75), 0 1px 3px rgba(0, 0, 0, 0.6);
}
.g-ctl { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 26px; }
.g-seg { display: flex; gap: 6px; }
.on-coarse { display: none; }
@media (hover: none) { .on-fine { display: none; } .on-coarse { display: inline; } }

.g-btn {
  font: 600 11.5px 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
  /* No backdrop-filter here: these controls sit over #gathering's canvas,
     which repaints every frame of its animation, so a live blur behind
     them forced the compositor to re-run gaussian blur 60x/sec. A denser
     flat fill plus a hairline inset highlight reads as glass without it. */
  background: rgba(8, 12, 22, 0.84); border: 1px solid var(--line); border-radius: 999px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  padding: 7px 14px; cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.g-btn:hover { color: #fff; border-color: var(--accent); }
.g-btn[aria-pressed="true"] { color: #06121f; background: var(--accent); border-color: var(--accent); box-shadow: none; }
.g-field {
  font: 13px 'Segoe UI', 'Helvetica Neue', Arial, sans-serif; color: var(--text); width: 180px;
  background: rgba(8, 12, 22, 0.84); border: 1px solid var(--line); border-radius: 999px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  padding: 7px 14px;
}
.g-field::placeholder { color: var(--dim); }
.g-field:focus { outline: none; border-color: var(--accent); }
.g-ghost { background: transparent; }

/* On a phone the stage is too small to set a title over: the crowd is the
   small part of the picture. The lockup comes off the artwork and leads it. */
@media (max-width: 860px) {
  body.stagepage header { position: static; }
  body.stagepage .mast { padding-top: 22px; }
  body.stagepage .mast nav a { text-shadow: none; }
  .g-stage { display: flex; flex-direction: column; }
  .g-lock {
    position: static; order: -1; width: auto;
    padding: 26px clamp(20px, 3.4vw, 46px) 22px;
    max-width: 720px; margin: 0 auto; box-sizing: border-box;
  }
  /* off the artwork, the picture is a band: both of its edges dissolve */
  .g-veil {
    background:
      linear-gradient(180deg, #0a0e18 0%, rgba(10, 14, 24, 0) 9%,
                              transparent 86%, #0a0e18 100%),
      radial-gradient(circle at 50% 52%, transparent 32%, rgba(0, 0, 0, 0.5) 100%);
  }
  .g-title { text-shadow: none; }
  .g-field { flex: 1; min-width: 140px; }
}
@media (max-width: 700px) {
  .g-title { font-size: clamp(38px, 11vw, 56px); }
}

/* The one authored moment: when the map has finished loading, the lockup
   arrives on it. Nothing else on the page moves. */
@keyframes g-rise { from { opacity: 0; transform: translateY(18px); } }
.gathering:has(.g-load.gone) ~ .g-lock > * {
  animation: g-rise 0.85s cubic-bezier(0.16, 1, 0.3, 1) backwards;
}
.gathering:has(.g-load.gone) ~ .g-lock > :nth-child(2) { animation-delay: 0.07s; }
.gathering:has(.g-load.gone) ~ .g-lock > :nth-child(3) { animation-delay: 0.14s; }
.gathering:has(.g-load.gone) ~ .g-lock > :nth-child(4) { animation-delay: 0.21s; }
.gathering:has(.g-load.gone) ~ .g-lock > :nth-child(5) { animation-delay: 0.28s; }
@media (prefers-reduced-motion: reduce) {
  .gathering:has(.g-load.gone) ~ .g-lock > * { animation: none; }
  .g-out span { transition: none; }
}

.g-load {
  position: absolute; inset: 0; display: grid; place-items: center; z-index: 3;
  background: #05070c; transition: opacity 0.5s;
  font: 600 11.5px 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  letter-spacing: 0.24em; color: var(--faint);
}
.g-load.gone { opacity: 0; pointer-events: none; }
.g-tip {
  position: absolute; z-index: 8; pointer-events: none; opacity: 0;
  /* placed by transform, not left/top: moving it must not relayout the page */
  left: 0; top: 0; will-change: transform;
  transform: translate(-50%, -100%); transition: opacity 0.12s;
  min-width: 190px; padding: 10px 13px;
  background: rgba(10, 15, 28, 0.94); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 14px 38px rgba(0, 0, 0, 0.7);
}
.g-tip.on { opacity: 1; }
.g-tip.pinned { pointer-events: auto; border-color: var(--accent); }
.g-tip h4 { margin: 0 0 2px; font-size: 15px; font-weight: 600; color: #fff; }
.g-tip .sub { margin: 0 0 8px; font-size: 12px; color: var(--dim); }
.g-tip dl { display: grid; grid-template-columns: auto auto; gap: 2px 16px; margin: 0; font-size: 12.5px; }
.g-tip dt { color: var(--dim); }
.g-tip dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); }
.g-tip dd.hi { color: var(--accent-hi); font-weight: 600; }
.g-tip .g-hint { margin: 8px 0 0; font-size: 11px; color: var(--dim); }
.g-tip .g-more { display: inline-block; margin-top: 8px; font-size: 12.5px; text-decoration: none; }
.g-tip .g-more:hover { color: var(--accent-hi); }
.chartctl .searchbox { margin-left: auto; width: 210px; padding: 6px 14px; font-size: 13px; }
@media (max-width: 700px) {
  .chartctl .searchbox { margin-left: 0; width: 100%; }
}

/* --- officer sign-in ------------------------------------------------------ */
.loginwrap { display: grid; place-items: center; min-height: 46vh; margin-top: 28px; }
.loginbox { width: min(420px, 100%); }
.loginform { display: flex; flex-direction: column; gap: 12px; }
.loginform label { color: var(--muted); font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; }
.loginform input[type="password"] {
  background: rgba(10, 15, 28, 0.8); color: var(--text);
  border: 1px solid var(--line-mid); border-radius: 10px;
  padding: 12px 14px; font-size: 16px; letter-spacing: 0.12em;
  outline: none; transition: border-color 0.15s, box-shadow 0.15s;
}
.loginform input[type="password"]:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(59, 167, 230, 0.22);
}
.loginform button {
  background: linear-gradient(180deg, rgba(59,167,230,0.28), rgba(47,102,181,0.28));
  color: var(--accent-hi); border: 1px solid var(--accent);
  border-radius: 10px; padding: 12px 14px; font-size: 15px; font-weight: 600;
  letter-spacing: 0.03em; cursor: pointer; transition: filter 0.15s;
}
.loginform button:hover { filter: brightness(1.18); }
.loginerr { margin: 0; color: #ff9d9d; font-size: 14px; }
.loginnote { margin: 2px 0 0; color: var(--faint); font-size: 12.5px; }
.signout { color: var(--faint); font-size: 12.5px; margin-left: 10px; }
.signout:hover { color: var(--text); }
.lvup { color: var(--up); font-size: 12px; font-weight: 600; }

/* --- officer: load date repair -------------------------------------------
   The only write surface on the site, so it is styled to slow the reader
   down: suspect rows are marked but not alarming, voided rows recede, and
   the destructive button is the only red thing on the page. */

.flash { margin: 0 0 4px; padding: 11px 16px; border-radius: var(--radius); font-size: 14px; }
.flash-ok { border: 1px solid rgba(127,224,168,0.4); background: rgba(127,224,168,0.08); color: var(--up); }
.flash-err { border: 1px solid rgba(232,165,102,0.45); background: rgba(232,165,102,0.09); color: var(--bronze); }

.chip.chip-warn { border-color: rgba(232,165,102,0.5); }
.chip.chip-warn b { color: var(--bronze); }

#dates-table td { vertical-align: top; }
#dates-table td:first-child, #dates-table th { white-space: nowrap; }
#dates-table th, #dates-table td { padding-right: 18px; }
#dates-table tr.suspect-row { background: rgba(232,165,102,0.06); }
#dates-table tr.voided-row { opacity: 0.55; }
#dates-table tr.voided-row .n { text-decoration: line-through; }

.coverage { white-space: nowrap; }
.coverage .cov {
  display: inline-block; min-width: 30px; text-align: center; font-size: 11px;
  font-weight: 700; color: var(--accent-hi); cursor: help;
}
.coverage .cov-none { color: var(--dim); opacity: 0.45; }

.repair { min-width: 300px; }
.reasonline { margin: 0 0 7px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.repairform { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.repairform input[type="text"] {
  width: 100%; max-width: 340px; padding: 5px 9px; font-size: 12.5px;
  color: var(--text); background: var(--panel-b);
  border: 1px solid var(--line-mid); border-radius: 6px;
}
.foldopt { font-size: 12.5px; color: var(--muted); display: flex; gap: 6px; align-items: center; }
.foldopt input:disabled + * , .foldopt:has(input:disabled) { color: var(--dim); }

/* A date with no sign of trouble still gets a void control, but it stays out
   of the way until deliberately opened — the common case here is reading. */
.repairform.collapsed input[type="text"] { display: none; }
.repairform.collapsed:focus-within input[type="text"] { display: block; }

.btn-danger, .btn-ghost {
  font: inherit; font-size: 12.5px; font-weight: 700; padding: 5px 13px;
  border-radius: 6px; cursor: pointer;
}
.btn-danger { color: #ffdada; background: rgba(224,90,90,0.16); border: 1px solid rgba(224,90,90,0.55); }
.btn-danger:hover { background: rgba(224,90,90,0.28); }
.btn-ghost { color: var(--muted); background: transparent; border: 1px solid var(--line-mid); }
.btn-ghost:hover { color: var(--text); border-color: var(--line); }
