/* ============================================================================
   Weien Wong design system
   ----------------------------------------------------------------------------
   One stylesheet shared by every service on the domain. Each service sets a
   single --accent-h hue and inherits everything else, so the thirteen sites
   read as one product family instead of thirteen unrelated projects.

   Grounded in how the tools this fleet resembles are actually built — Linear,
   Vercel, Supabase, Stripe:

   * Dark is the primary theme, built from tokens. Light is a real second
     palette, not an inversion — inverted dark themes are the single most
     obvious tell of an unconsidered UI.
   * Depth comes from a surface ladder plus 1px hairlines, not drop shadows.
     Shadows on dark backgrounds read as smudges.
   * Exactly one chromatic accent per service, and it is rationed: focus rings,
     the primary button, the active nav item. Never decoration.
   * Monospace carries data — ids, ports, counts, timestamps. These are
     developer tools and the type should say so.
   * Buttons are 8px radius, not pills. Pill-shaped CTAs read as consumer.
   ========================================================================== */

:root {
  /* -- accent -------------------------------------------------------------
     The only value a service overrides. Everything chromatic is derived from
     this hue, so a new service picks one number and stays consistent. */
  --accent-h: 244;
  --accent-s: 57%;

  --accent: hsl(var(--accent-h) var(--accent-s) 60%);
  --accent-hover: hsl(var(--accent-h) var(--accent-s) 70%);
  --accent-quiet: hsl(var(--accent-h) 30% 22%);
  --accent-ink: hsl(var(--accent-h) 60% 88%);
  --accent-ring: hsl(var(--accent-h) var(--accent-s) 60% / 0.55);

  /* -- surface ladder (dark, the primary theme) ---------------------------
     Four steps, each a hair lighter. Elevation is position on this ladder. */
  --canvas: #08090a;
  --surface-1: #0f1011;
  --surface-2: #141516;
  --surface-3: #191a1c;
  --surface-4: #1f2123;

  --hairline: #23252a;
  --hairline-strong: #33353b;

  --ink: #f7f8f8;
  --ink-muted: #c9cdd4;
  --ink-subtle: #8a8f98;
  --ink-faint: #62666d;

  /* Semantic colours are independent of the accent, so a green service does
     not make "success" invisible. */
  --ok: #3fb950;
  --ok-quiet: #0d2b14;
  --warn: #d29922;
  --warn-quiet: #2b2008;
  --danger: #f0616d;
  --danger-quiet: #2d1114;
  --info: #58a6ff;
  --info-quiet: #0d2237;

  /* -- type ---------------------------------------------------------------
     Negative tracking on display sizes is most of what separates a considered
     page from a default one. No webfont: a silent fallback is worse than an
     honest system stack. */
  --font: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
          "Liberation Mono", monospace;

  --text-display: 2.5rem;
  --text-h1: 1.75rem;
  --text-h2: 1.25rem;
  --text-h3: 1rem;
  --text-body: 0.9375rem;
  --text-sm: 0.875rem;
  --text-xs: 0.8125rem;
  --text-micro: 0.75rem;

  /* -- space (4px base) --------------------------------------------------- */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;
  --s8: 4rem;

  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 12px;
  --r-xl: 16px;
  --r-pill: 999px;

  --page: 1200px;
  --nav-h: 56px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Light theme — authored, not inverted. Surfaces get *lighter* going up the
   ladder in dark and *whiter* in light, but the borders and text are chosen
   separately so contrast holds in both. */
:root[data-theme="day"] {
  --canvas: #fbfbfc;
  --surface-1: #ffffff;
  --surface-2: #f7f8f9;
  --surface-3: #f1f2f4;
  --surface-4: #e9ebee;

  --hairline: #e3e5e9;
  --hairline-strong: #cfd3da;

  --ink: #16181d;
  --ink-muted: #40454e;
  --ink-subtle: #666c77;
  --ink-faint: #878d98;

  --accent: hsl(var(--accent-h) 48% 42%);
  --accent-hover: hsl(var(--accent-h) 48% 34%);
  --accent-quiet: hsl(var(--accent-h) 60% 95%);
  --accent-ink: hsl(var(--accent-h) 50% 32%);

  --ok: #1a7f37;
  --ok-quiet: #dafbe1;
  --warn: #8a6100;
  --warn-quiet: #fff8c5;
  --danger: #b3261e;
  --danger-quiet: #ffebe9;
  --info: #0969da;
  --info-quiet: #ddf4ff;
}

/* ------------------------------------------------------------------- reset */

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

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

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--text-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
}

img, svg, video { max-width: 100%; height: auto; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; text-wrap: balance; }
h1 { font-size: var(--text-h1); line-height: 1.15; letter-spacing: -0.021em; }
h2 { font-size: var(--text-h2); line-height: 1.25; letter-spacing: -0.014em; }
h3 { font-size: var(--text-h3); line-height: 1.35; letter-spacing: -0.008em; }
p  { margin: 0; }

a { color: var(--accent-ink); text-decoration-color: color-mix(in srgb, currentColor 35%, transparent); text-underline-offset: 2px; }
a:hover { text-decoration-color: currentColor; }

:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 2px; border-radius: var(--r-xs); }

code, kbd, samp, .mono { font-family: var(--mono); font-size: 0.9em; font-variant-numeric: tabular-nums; }

.display { font-size: var(--text-display); line-height: 1.05; letter-spacing: -0.032em; font-weight: 600; }
.lede { color: var(--ink-muted); font-size: 1.0625rem; line-height: 1.6; max-width: 62ch; }
.muted { color: var(--ink-subtle); font-size: var(--text-sm); }
.faint { color: var(--ink-faint); font-size: var(--text-xs); }

.eyebrow {
  font-family: var(--mono);
  font-size: var(--text-micro);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-subtle);
}

/* ------------------------------------------------------------------ layout */

.page { width: 100%; max-width: var(--page); margin-inline: auto; padding-inline: var(--s5); }
.stack { display: flex; flex-direction: column; gap: var(--s4); }
.stack-lg { display: flex; flex-direction: column; gap: var(--s6); }
.row { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.row-tight { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.spacer { margin-left: auto; }

main { flex: 1 0 auto; padding-block: var(--s6) var(--s8); }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  background: var(--accent); color: #fff; padding: var(--s2) var(--s4);
  border-radius: 0 0 var(--r-md) 0;
}
.skip-link:focus { left: 0; }

/* ---------------------------------------------------------------- topbar */

.topbar {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in srgb, var(--canvas) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--hairline);
}

.topbar-inner { min-height: var(--nav-h); display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }

.brand {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-weight: 600; font-size: var(--text-sm); color: var(--ink);
  text-decoration: none; white-space: nowrap; letter-spacing: -0.011em;
}
.brand img, .brand svg { border-radius: var(--r-sm); flex: none; }

.navlink {
  color: var(--ink-subtle); text-decoration: none;
  font-size: var(--text-sm); padding: var(--s2) var(--s3);
  border-radius: var(--r-md); transition: color .12s var(--ease), background .12s var(--ease);
}
.navlink:hover { color: var(--ink); background: var(--surface-2); }
.navlink[aria-current="page"] { color: var(--ink); background: var(--surface-3); }

/* --------------------------------------------------------------- controls */

.btn {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  --btn-bd: var(--hairline-strong);
  font: inherit; font-size: var(--text-sm); font-weight: 500;
  line-height: 1.2;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 36px; padding: var(--s2) var(--s4);
  border: 1px solid var(--btn-bd); border-radius: var(--r-md);
  background: var(--btn-bg); color: var(--btn-fg);
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background .12s var(--ease), border-color .12s var(--ease), opacity .12s var(--ease);
}
.btn:hover:not(:disabled) { --btn-bg: var(--surface-3); }
.btn:disabled { opacity: .45; cursor: default; }

.btn-primary { --btn-bg: var(--accent); --btn-bd: var(--accent); --btn-fg: #fff; font-weight: 600; }
.btn-primary:hover:not(:disabled) { --btn-bg: var(--accent-hover); --btn-bd: var(--accent-hover); }

.btn-danger { --btn-fg: var(--danger); --btn-bd: color-mix(in srgb, var(--danger) 45%, transparent); }
.btn-sm { min-height: 30px; padding: var(--s1) var(--s3); font-size: var(--text-xs); }
.btn-lg { min-height: 44px; padding: var(--s3) var(--s5); font-size: var(--text-body); }

.field {
  font: inherit; font-size: var(--text-body);
  width: 100%; min-height: 40px; padding: var(--s2) var(--s3);
  color: var(--ink); background: var(--surface-1);
  border: 1px solid var(--hairline-strong); border-radius: var(--r-md);
  transition: border-color .12s var(--ease);
}
.field::placeholder { color: var(--ink-faint); }
.field:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--accent-ring); }

label { font-size: var(--text-sm); color: var(--ink-muted); }

/* ----------------------------------------------------------------- panels */

.card {
  background: var(--surface-1);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: var(--s5);
}
.card-tight { padding: var(--s4); }
.card-hover { transition: background .12s var(--ease), border-color .12s var(--ease); }
.card-hover:hover { background: var(--surface-2); border-color: var(--hairline-strong); }

.section-head {
  display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap;
  padding-bottom: var(--s3); border-bottom: 1px solid var(--hairline);
}
.section-head .muted { margin-left: auto; }

/* Stat tiles: the number is the point, so it gets the mono face and tabular
   figures; the label is deliberately quiet. */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s3); }

.stat {
  background: var(--surface-1); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: var(--s4);
  display: flex; flex-direction: column; gap: var(--s1);
}
.stat .n {
  font-family: var(--mono); font-size: 1.5rem; font-weight: 600;
  line-height: 1.1; font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.stat .k { font-size: var(--text-micro); letter-spacing: .09em; text-transform: uppercase; color: var(--ink-subtle); }

/* ------------------------------------------------------------------ chips */

.chip {
  display: inline-flex; align-items: center; gap: var(--s1);
  font-family: var(--mono); font-size: var(--text-micro);
  padding: 2px var(--s2); border-radius: var(--r-pill);
  border: 1px solid var(--hairline-strong); color: var(--ink-subtle);
  background: transparent; white-space: nowrap;
}
.chip-accent { background: var(--accent-quiet); border-color: color-mix(in srgb, var(--accent) 55%, transparent); color: var(--accent-ink); }
.chip-ok      { background: var(--ok-quiet);     border-color: color-mix(in srgb, var(--ok) 45%, transparent);     color: var(--ok); }
.chip-warn    { background: var(--warn-quiet);   border-color: color-mix(in srgb, var(--warn) 45%, transparent);   color: var(--warn); }
.chip-danger  { background: var(--danger-quiet); border-color: color-mix(in srgb, var(--danger) 45%, transparent); color: var(--danger); }
.chip-info    { background: var(--info-quiet);   border-color: color-mix(in srgb, var(--info) 45%, transparent);   color: var(--info); }

button.chip { cursor: pointer; min-height: 28px; padding-inline: var(--s3); font-family: var(--font); font-size: var(--text-xs); }
button.chip:hover { background: var(--surface-3); color: var(--ink); }
button.chip[aria-pressed="true"] { background: var(--accent-quiet); border-color: var(--accent); color: var(--accent-ink); }

/* ----------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; border: 1px solid var(--hairline); border-radius: var(--r-lg); background: var(--surface-1); }

table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }

th {
  text-align: left; padding: var(--s3) var(--s4);
  font-size: var(--text-micro); font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-subtle);
  background: var(--surface-2); border-bottom: 1px solid var(--hairline);
  white-space: nowrap; position: sticky; top: 0; z-index: 1;
}

td { padding: var(--s3) var(--s4); border-bottom: 1px solid var(--hairline); vertical-align: top; color: var(--ink-muted); }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: var(--surface-2); color: var(--ink); }

/* Digits in a column must line up, or the table reads as sloppy however good
   the rest of the page is. */
td.num, th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- notices */

.notice {
  border: 1px solid var(--hairline-strong);
  border-left: 3px solid var(--accent);
  background: var(--surface-1);
  border-radius: var(--r-md);
  padding: var(--s4) var(--s5);
  color: var(--ink-muted);
}
.notice-danger { border-left-color: var(--danger); }
.notice-warn { border-left-color: var(--warn); }
.notice-ok { border-left-color: var(--ok); }

.empty { text-align: center; padding: var(--s7) var(--s4); color: var(--ink-subtle); }

/* ------------------------------------------------------------------ pager */

.pager { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; padding-top: var(--s3); }
.pager[hidden] { display: none; }
.pager-info { font-family: var(--mono); font-size: var(--text-xs); color: var(--ink-subtle); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pager-num {
  font: inherit; font-size: var(--text-xs); font-variant-numeric: tabular-nums;
  min-width: 32px; min-height: 32px; padding: var(--s1) var(--s2);
  border: 1px solid var(--hairline-strong); border-radius: var(--r-sm);
  background: transparent; color: var(--ink-subtle); cursor: pointer;
}
.pager-num:hover:not(:disabled) { background: var(--surface-3); color: var(--ink); }
.pager-num[aria-current="page"] { background: var(--accent-quiet); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.pager-num:disabled { opacity: .4; cursor: default; }

/* ----------------------------------------------------------------- footer */

.site-footer {
  flex: none; margin-top: var(--s7);
  border-top: 1px solid var(--hairline);
  padding-block: var(--s5) var(--s6);
  color: var(--ink-subtle); font-size: var(--text-sm);
}

/* ------------------------------------------------------------- scrollbars */

:root { --sb-thumb: color-mix(in srgb, var(--ink-faint) 55%, transparent); --sb-thumb-hover: var(--ink-faint); }

* { scrollbar-width: thin; scrollbar-color: var(--sb-thumb) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--sb-thumb); border-radius: var(--r-pill); border: 2px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--sb-thumb-hover); background-clip: padding-box; }
*::-webkit-scrollbar-corner { background: transparent; }

.table-wrap, .scroll-x, pre, textarea { overscroll-behavior: contain; }

/* ------------------------------------------------------------ breakpoints */

@media (max-width: 900px) {
  :root { --text-display: 2rem; --text-h1: 1.5rem; }
  .page { padding-inline: var(--s4); }
}

@media (max-width: 620px) {
  :root { --nav-h: 52px; }
  main { padding-block: var(--s5) var(--s7); }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .section-head .muted { margin-left: 0; flex-basis: 100%; }
  th, td { padding: var(--s2) var(--s3); }
  .btn { min-height: 40px; }
}

@media (max-width: 380px) {
  .stats { grid-template-columns: 1fr; }
}

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

/* ============================================================== auth dialog
   Native <dialog>: the platform gives focus trapping, Escape, and inertness
   of the page behind for free. Hand-rolled modals get those wrong. */

.ww-dialog {
  width: min(420px, calc(100vw - 2rem));
  padding: 0;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--r-xl);
  background: var(--surface-1);
  color: var(--ink);
}
.ww-dialog::backdrop { background: rgb(0 0 0 / .6); backdrop-filter: blur(2px); }

.ww-dialog-close-form { position: absolute; top: var(--s2); right: var(--s2); margin: 0; }
.ww-dialog-x {
  font: inherit; font-size: 1.25rem; line-height: 1;
  width: 32px; height: 32px; border: 0; border-radius: var(--r-md);
  background: transparent; color: var(--ink-subtle); cursor: pointer;
}
.ww-dialog-x:hover { background: var(--surface-3); color: var(--ink); }

.ww-dialog-body { padding: var(--s6) var(--s5) var(--s5); display: flex; flex-direction: column; gap: var(--s4); }
.ww-dialog-lede { margin: 0; }
.ww-dialog-foot { margin: 0; }

.ww-tabs { display: flex; gap: var(--s1); background: var(--surface-3); padding: 3px; border-radius: var(--r-md); }
.ww-tab {
  flex: 1; font: inherit; font-size: var(--text-sm); font-weight: 500;
  padding: var(--s2); border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--ink-subtle); cursor: pointer;
}
.ww-tab[aria-selected="true"] { background: var(--surface-1); color: var(--ink); }

.ww-auth-error { padding: var(--s2) var(--s3); font-size: var(--text-sm); color: var(--danger); }

/* ================================================================= landing
   Every sub-app shows the same shape before sign-in: what it is, what it can
   do, how to start. A bare login form tells a first-time visitor nothing. */

.hero { display: flex; flex-direction: column; gap: var(--s4); padding-block: var(--s6) var(--s5); }
.hero-actions { display: flex; gap: var(--s3); flex-wrap: wrap; }

.shot {
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--surface-2); overflow: hidden;
}
.shot img { display: block; width: 100%; }
.shot-caption { padding: var(--s2) var(--s4); font-size: var(--text-xs); color: var(--ink-subtle); border-top: 1px solid var(--hairline); }

/* Placeholder used when a service has no screenshot yet — an honest empty
   frame rather than a stock photo pretending to be the product. */
.shot-empty {
  aspect-ratio: 16 / 9; display: grid; place-items: center;
  color: var(--ink-faint); font-family: var(--mono); font-size: var(--text-xs);
  background:
    repeating-linear-gradient(45deg, transparent 0 10px, color-mix(in srgb, var(--hairline) 60%, transparent) 10px 11px);
}

.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--s3); }

.steps { display: flex; flex-direction: column; gap: var(--s3); counter-reset: step; margin: 0; padding: 0; list-style: none; }
.steps li {
  counter-increment: step;
  display: grid; grid-template-columns: 28px 1fr; gap: var(--s3);
  align-items: start; color: var(--ink-muted); font-size: var(--text-sm);
}
.steps li::before {
  content: counter(step);
  font-family: var(--mono); font-size: var(--text-xs); font-weight: 600;
  width: 26px; height: 26px; display: grid; place-items: center;
  border-radius: var(--r-pill);
  background: var(--accent-quiet); color: var(--accent-ink);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
}
.steps li strong { color: var(--ink); font-weight: 600; }
