/* viha: one monotone look everywhere. Grey Windows 95 chrome around black keygen panels, one monospace pixel font. */

/* Kaamos, the plain look; .theme-kaamos too, so its card in the dashboard keeps it whatever the dashboard wears */
:root, .theme-kaamos {
  --page: #000;
  /* Text straight on the page's ground: what a page shows before it opens (click to enter) */
  --page-ink: #ffffff;
  --face: #c0c0c0;
  --hi: #ffffff;
  --mid: #dfdfdf;
  --shade: #808080;
  --lo: #0a0a0a;
  --ink: #000;
  --dim: #3a3a3a;
  --well: #ffffff;
  --title-a: #0a0a0a;
  --title-b: #7b7b7b;
  --title-ink: #fff;
  --sel: #000;
  --sel-ink: #fff;
  /* Read by fx.js for the canvas effects */
  --logo: #ffffff;
  --dither: #000000 #555555 #aaaaaa #ffffff;
  --star: #ffffff;
  /* The black keygen panels (banners, cards, the name over the banner) and the shadow under a window */
  --panel: #000;
  --panel-ink: #e4e4e4;
  --panel-hi: #ffffff;
  --panel-mid: #c4c4c4;
  --panel-soft: #c0c0c0;
  --panel-dim: #9a9a9a;
  --panel-edge: #3a3a3a;
  --drop: rgba(0, 0, 0, .8);
  /* The thin frame around a window and the default button, and the hard shadow a page may cast instead of the soft
     one (its owner's choice) */
  --ring: #000;
  --cast: #4a4a4a;
  /* A pattern over the page's ground, one image in 14 px tiles: Punastus's dots, Meripihka's scanlines, Sinikopio's
     grid; none for the others */
  --page-art: none;
  /* What is unsaved: the status text on its panel, and the star on a group's name */
  --alert: #ff4d4d;
  --mark: #9a0000;

  --mono: "VT323", ui-monospace, Consolas, monospace;
  color-scheme: light;
}

/* A page's theme (lib/themes.js): the same windows in other shades, three more greys and then the ones with a hue, each
   of which sets every shade (else it would fall back to Kaamos's greys). Set on the page's <html>, so the page behind
   the window and the starfield take it too; the dashboard draws each in a little window of its own. Kaamos is :root
   above. Every pair of text and its ground keeps at least 4.5:1 (test/themes.test.js). */
.theme-hiili {
  --page: #000;
  --face: #262626;
  --hi: #4d4d4d;
  --mid: #363636;
  --shade: #111111;
  --lo: #000;
  --ink: #dcdcdc;
  --dim: #a0a0a0;
  --well: #121212;
  --title-a: #000;
  --title-b: #404040;
  --title-ink: #e4e4e4;
  --sel: #dcdcdc;
  --sel-ink: #000;
  --panel: #3a3a3a;
  --panel-ink: #e4e4e4;
  --panel-hi: #ffffff;
  --panel-mid: #cfcfcf;
  --panel-soft: #cfcfcf;
  --panel-dim: #aaaaaa;
  --panel-edge: #5a5a5a;
  --alert: #ff8080;
  --mark: #ff6b6b;
  color-scheme: dark;
}
.theme-lumi {
  --page: #f2f2f2;
  --page-ink: #000;
  --face: #e6e6e6;
  --hi: #ffffff;
  --mid: #f3f3f3;
  --shade: #a0a0a0;
  --lo: #505050;
  --ink: #000;
  --dim: #474747;
  --well: #ffffff;
  --title-a: #ffffff;
  --title-b: #a8a8a8;
  --title-ink: #000;
  --sel: #000;
  --sel-ink: #fff;
  --logo: #000000;
  --star: #9a9a9a;
  --panel: #ffffff;
  --panel-ink: #1a1a1a;
  --panel-hi: #000;
  --panel-mid: #333333;
  --panel-soft: #333333;
  --panel-dim: #5a5a5a;
  --panel-edge: #c8c8c8;
  --drop: rgba(0, 0, 0, .25);
  --cast: #b4b4b4;
  --alert: #b00000;
  --mark: #9a0000;
}
.theme-tuhka {
  --page: #1a1a1a;
  --page-ink: #c8c8c8;
  --face: #8e8e8e;
  --hi: #b4b4b4;
  --mid: #a2a2a2;
  --shade: #646464;
  --lo: #262626;
  --ink: #141414;
  --dim: #262626;
  --well: #b8b8b8;
  --title-a: #262626;
  --title-b: #5a5a5a;
  --title-ink: #d2d2d2;
  --sel: #262626;
  --sel-ink: #d2d2d2;
  --logo: #c8c8c8;
  --star: #8c8c8c;
  --dither: #1e1e1e #4a4a4a #8a8a8a #c8c8c8;
  --panel: #222222;
  --panel-ink: #b8b8b8;
  --panel-hi: #d6d6d6;
  --panel-mid: #a6a6a6;
  --panel-soft: #a6a6a6;
  --panel-dim: #8a8a8a;
  --panel-edge: #444444;
  --alert: #ff6b6b;
  --mark: #4a0000;
  color-scheme: dark;
}
/* Punastus, the blush of an ecchi anime: sakura pink windows on a halftone page, deep plum where the others have black
   panels, a hot pink blush after the name and hearts before the links (below, "A bio page"). */
.theme-punastus {
  --page: #ffd6e7;
  --page-ink: #3b0d2c;
  --face: #f7b8d0;
  --hi: #ffffff;
  --mid: #fbd3e2;
  --shade: #c76b95;
  --lo: #4a0f33;
  --ink: #3b0d2c;
  --dim: #7a2f5c;
  --well: #fff4f8;
  --title-a: #b0125f;
  --title-b: #ff8fbf;
  --title-ink: #ffffff;
  --sel: #b0125f;
  --sel-ink: #ffffff;
  --logo: #ffffff;
  --dither: #2a0a20 #8c1f5e #ff5fa2 #ffe3ef;
  --star: #ff5fa2;
  --panel: #2a0a20;
  --panel-ink: #ffe3ef;
  --panel-hi: #ffffff;
  --panel-mid: #ffc2da;
  --panel-soft: #ffc2da;
  --panel-dim: #e58fb6;
  --panel-edge: #6b1f4c;
  --drop: rgba(74, 15, 51, .3);
  --ring: #4a0f33;
  --cast: rgba(74, 15, 51, .35);
  --page-art: radial-gradient(#ffbcd6 1.6px, transparent 1.8px);
  --blush: #ff5fa2;
  --alert: #ff6f9c;
  --mark: #8a0f4a;
}
/* Paperi, paper printed in two inks: black type and a red stamp on warm newsprint, the banners printed in both */
.theme-paperi {
  --page: #e9e4d8;
  --page-ink: #1a1814;
  --face: #f4f0e6;
  --hi: #ffffff;
  --mid: #faf7f0;
  --shade: #b3ab98;
  --lo: #2b2824;
  --ink: #1a1814;
  --dim: #4a453c;
  --well: #fffdf8;
  --title-a: #1a1814;
  --title-b: #c8102e;
  --title-ink: #ffffff;
  --sel: #c8102e;
  --sel-ink: #ffffff;
  --logo: #f4f0e6;
  --dither: #1a1814 #6a0f1e #d8283f #f4f0e6;
  --star: #8a8270;
  --panel: #1a1814;
  --panel-ink: #f4f0e6;
  --panel-hi: #ffffff;
  --panel-mid: #d9d3c4;
  --panel-soft: #d9d3c4;
  --panel-dim: #a8a090;
  --panel-edge: #4a453c;
  --drop: rgba(43, 40, 36, .25);
  --ring: #1a1814;
  --cast: #1a1814;
  --alert: #ff6b6b;
  --mark: #c8102e;
}
/* Hurme, shed blood: oxblood windows on black, a red glow in the panels, embers for stars */
.theme-hurme {
  --page: #070000;
  --page-ink: #ffd6d0;
  --face: #2a0b0b;
  --hi: #5a1a1a;
  --mid: #3a1010;
  --shade: #120303;
  --lo: #000;
  --ink: #f2d6d0;
  --dim: #c48f86;
  --well: #160404;
  --title-a: #3d0000;
  --title-b: #a3141a;
  --title-ink: #ffe9e6;
  --sel: #b3121b;
  --sel-ink: #ffffff;
  --logo: #ffd6d0;
  --dither: #000000 #4a0508 #b3121b #ffcfc7;
  --star: #ff6a5c;
  --panel: #000;
  --panel-ink: #f2d6d0;
  --panel-hi: #ffffff;
  --panel-mid: #e0aaa2;
  --panel-soft: #e0aaa2;
  --panel-dim: #b07a72;
  --panel-edge: #4a1212;
  --drop: rgba(0, 0, 0, .85);
  --ring: #000;
  --cast: #6b0a10;
  --alert: #ff6b6b;
  --mark: #ff8a80;
  color-scheme: dark;
}
/* Ruska, the autumn's turning leaves: tan windows on dark loam, a rust title bar, amber stars */
.theme-ruska {
  --page: #1f0c04;
  --page-ink: #ffe2bf;
  --face: #d9b48c;
  --hi: #fff3e3;
  --mid: #ead0b2;
  --shade: #9a6a3e;
  --lo: #2a1206;
  --ink: #1f0c04;
  --dim: #5a2e12;
  --well: #fff8ee;
  --title-a: #6e1f05;
  --title-b: #b04a14;
  --title-ink: #ffffff;
  --sel: #8a2a08;
  --sel-ink: #ffffff;
  --logo: #ffe2bf;
  --dither: #160803 #7a2a0a #e07a2a #ffe4c2;
  --star: #ffb066;
  --panel: #160803;
  --panel-ink: #f5dcc2;
  --panel-hi: #ffffff;
  --panel-mid: #e8c49e;
  --panel-soft: #e8c49e;
  --panel-dim: #c08d63;
  --panel-edge: #4a2410;
  --drop: rgba(20, 8, 2, .8);
  --ring: #1f0c04;
  --cast: #7a3a14;
  --alert: #ff8a5c;
  --mark: #8a1500;
}
/* Meripihka, amber: an amber monitor, every line in its one colour, picked lines in reverse, scanlines over the page */
.theme-meripihka {
  --page: #0a0500;
  --page-ink: #ffb000;
  --face: #1a0f00;
  --hi: #5c3a00;
  --mid: #2e1c00;
  --shade: #0d0700;
  --lo: #000;
  --ink: #ffb000;
  --dim: #c98a1a;
  --well: #0f0800;
  --title-a: #3d2600;
  --title-b: #7a4f00;
  --title-ink: #ffd27a;
  --sel: #ffb000;
  --sel-ink: #1a0f00;
  --logo: #ffc040;
  --dither: #000000 #4a2e00 #b37400 #ffc040;
  --star: #ffb000;
  --panel: #000;
  --panel-ink: #ffb000;
  --panel-hi: #ffd27a;
  --panel-mid: #e09a10;
  --panel-soft: #e09a10;
  --panel-dim: #b37a10;
  --panel-edge: #3d2600;
  --drop: rgba(0, 0, 0, .8);
  --ring: #000;
  --cast: #5c3a00;
  --page-art: repeating-linear-gradient(rgba(255, 176, 0, .12) 0 1px, transparent 1px 2px);
  --alert: #ff5a3c;
  --mark: #ff7a50;
  color-scheme: dark;
}
/* Kulta, gold leaf on black lacquer: gilded edges round every window and button, ivory type */
.theme-kulta {
  --page: #050403;
  --page-ink: #e6c35c;
  --face: #14110a;
  --hi: #b8913a;
  --mid: #4a3c1a;
  --shade: #2a2210;
  --lo: #000;
  --ink: #f3e6c4;
  --dim: #c9ad6e;
  --well: #0b0905;
  --title-a: #3a2a08;
  --title-b: #86651a;
  --title-ink: #fff6dc;
  --sel: #d4af37;
  --sel-ink: #14110a;
  --logo: #e6c35c;
  --dither: #000000 #4a3610 #b8913a #ffe9a8;
  --star: #e6c35c;
  --panel: #000;
  --panel-ink: #f3e6c4;
  --panel-hi: #ffe9a8;
  --panel-mid: #d9bf7a;
  --panel-soft: #d9bf7a;
  --panel-dim: #a88a4a;
  --panel-edge: #4a3c1a;
  --drop: rgba(0, 0, 0, .85);
  --ring: #000;
  --cast: #6b5418;
  --alert: #ff6b5c;
  --mark: #ff8f80;
  color-scheme: dark;
}
/* Rikki, sulphur (and broken): the one yellow, sulphur windows under black title bars, a black shadow when cast */
.theme-rikki {
  --page: #0c0c00;
  --page-ink: #fff35c;
  --face: #e8d200;
  --hi: #fff7a8;
  --mid: #f3e45c;
  --shade: #8f8000;
  --lo: #1a1800;
  --ink: #0c0c00;
  --dim: #3d3800;
  --well: #fffbd6;
  --title-a: #0c0c00;
  --title-b: #4a4400;
  --title-ink: #fff35c;
  --sel: #0c0c00;
  --sel-ink: #fff35c;
  --logo: #fff35c;
  --dither: #0c0c00 #4a4400 #c2b000 #fff35c;
  --star: #e8d200;
  --panel: #0c0c00;
  --panel-ink: #f5ec9a;
  --panel-hi: #fff35c;
  --panel-mid: #e0d470;
  --panel-soft: #e0d470;
  --panel-dim: #b0a640;
  --panel-edge: #3d3800;
  --drop: rgba(0, 0, 0, .8);
  --ring: #0c0c00;
  --cast: #0c0c00;
  --alert: #ff5c3c;
  --mark: #a00000;
}
/* Sammal, moss: sage windows on the forest floor, an olive title bar */
.theme-sammal {
  --page: #0f1a0d;
  --page-ink: #e6f2d0;
  --face: #aab59a;
  --hi: #eef3e4;
  --mid: #c4ccb6;
  --shade: #6b7a58;
  --lo: #142010;
  --ink: #0d160a;
  --dim: #2f3d24;
  --well: #f4f7ec;
  --title-a: #1e3312;
  --title-b: #5a7336;
  --title-ink: #ffffff;
  --sel: #2f4a1c;
  --sel-ink: #f4f7ec;
  --logo: #e6f2d0;
  --dither: #0b1408 #2f4a1c #8aa35a #e9f2d6;
  --star: #c8dca0;
  --panel: #0b1408;
  --panel-ink: #dfe8cf;
  --panel-hi: #ffffff;
  --panel-mid: #c2cfaa;
  --panel-soft: #c2cfaa;
  --panel-dim: #93a37a;
  --panel-edge: #2f3d24;
  --drop: rgba(5, 10, 3, .8);
  --ring: #0b1408;
  --cast: #3a4a2a;
  --alert: #ff7a5c;
  --mark: #741400;
}
/* Revontuli, the northern lights: night-blue windows, a green glow in the panels, a mint highlight */
.theme-revontuli {
  --page: #02070d;
  --page-ink: #b9ffe0;
  --face: #14222e;
  --hi: #2f4a5e;
  --mid: #1c2f3d;
  --shade: #08111a;
  --lo: #000;
  --ink: #d7f5e9;
  --dim: #8fb8aa;
  --well: #0a141c;
  --title-a: #062a22;
  --title-b: #1d7f5f;
  --title-ink: #e8fff6;
  --sel: #5ff2b4;
  --sel-ink: #02130d;
  --logo: #b9ffe0;
  --dither: #030a12 #0d3b4a #2fbf8a #c8ffe6;
  --star: #9dffd2;
  --panel: #030a12;
  --panel-ink: #d7f5e9;
  --panel-hi: #ffffff;
  --panel-mid: #b5e3d2;
  --panel-soft: #b5e3d2;
  --panel-dim: #7fb3a3;
  --panel-edge: #1d3a48;
  --drop: rgba(0, 0, 0, .8);
  --ring: #000;
  --cast: #0f5c47;
  --alert: #ff7a8a;
  --mark: #ff8f9c;
  color-scheme: dark;
}
/* Jää, ice: pale blue windows on a frozen page, deep glacier panels, snow for stars */
.theme-jaa {
  --page: #e4f3f8;
  --page-ink: #06202b;
  --face: #cde4ec;
  --hi: #ffffff;
  --mid: #e3f1f6;
  --shade: #7fa6b5;
  --lo: #1d3f4d;
  --ink: #06202b;
  --dim: #2c4f5e;
  --well: #ffffff;
  --title-a: #0b4a66;
  --title-b: #24769a;
  --title-ink: #ffffff;
  --sel: #0b4a66;
  --sel-ink: #ffffff;
  --logo: #e6f8ff;
  --dither: #072230 #1f5f7a #7fc8e0 #f0fbff;
  --star: #5f93a8;
  --panel: #072230;
  --panel-ink: #d6f1fa;
  --panel-hi: #ffffff;
  --panel-mid: #b2dcea;
  --panel-soft: #b2dcea;
  --panel-dim: #7fb1c4;
  --panel-edge: #2c5566;
  --drop: rgba(6, 32, 43, .25);
  --ring: #1d3f4d;
  --cast: #9cc3d1;
  --alert: #ff7a7a;
  --mark: #9a0000;
}
/* Sinikopio, a blueprint: white lines on Prussian blue, a drafting grid over the page */
.theme-sinikopio {
  --page: #0b2a55;
  --page-ink: #ffffff;
  --face: #123d73;
  --hi: #4f7fb8;
  --mid: #1f5190;
  --shade: #0a2449;
  --lo: #04142b;
  --ink: #f2f7ff;
  --dim: #b5cdeb;
  --well: #0d3263;
  --title-a: #04142b;
  --title-b: #2a64a8;
  --title-ink: #ffffff;
  --sel: #f2f7ff;
  --sel-ink: #0b2a55;
  --logo: #ffffff;
  --dither: #071c3a #1f5190 #6f9fd8 #f2f7ff;
  --star: #cfe0ff;
  --panel: #071c3a;
  --panel-ink: #e3eeff;
  --panel-hi: #ffffff;
  --panel-mid: #bcd3f0;
  --panel-soft: #bcd3f0;
  --panel-dim: #8fb0dc;
  --panel-edge: #2a4f80;
  --drop: rgba(4, 20, 43, .8);
  --ring: #04142b;
  --cast: #04142b;
  /* (a line along the top and the left of each tile) */
  --page-art: conic-gradient(from 90deg at 1px 1px, transparent 90deg, rgba(255, 255, 255, .14) 0);
  --alert: #ffb36b;
  --mark: #ffc58a;
  color-scheme: dark;
}
/* Hämärä, dusk: lavender windows on a violet night */
.theme-hamara {
  --page: #120a24;
  --page-ink: #f0e6ff;
  --face: #bdb3d4;
  --hi: #f3efff;
  --mid: #d6cfe8;
  --shade: #7d6f9e;
  --lo: #1a0f33;
  --ink: #120a24;
  --dim: #3d2f61;
  --well: #f7f4ff;
  --title-a: #2a1260;
  --title-b: #7a4fb8;
  --title-ink: #ffffff;
  --sel: #3a1a7a;
  --sel-ink: #ffffff;
  --logo: #f0e6ff;
  --dither: #0e0720 #3d2370 #a07ad9 #f3e8ff;
  --star: #d9c2ff;
  --panel: #0e0720;
  --panel-ink: #e8defc;
  --panel-hi: #ffffff;
  --panel-mid: #cbbbe8;
  --panel-soft: #cbbbe8;
  --panel-dim: #9d8cc4;
  --panel-edge: #3a2a5c;
  --drop: rgba(10, 4, 24, .8);
  --ring: #120a24;
  --cast: #4a2f80;
  --alert: #ff7a9c;
  --mark: #8a0f3a;
}
/* Sähkö, electricity: neon on dark indigo, magenta edges and cyan picks, the one theme in two hues; yellow for what is
   unsaved, as neither of them */
.theme-sahko {
  --page: #0a0414;
  --page-ink: #7af3ff;
  --face: #1c0b33;
  --hi: #ff3ec8;
  --mid: #3a1a66;
  --shade: #0d0418;
  --lo: #000;
  --ink: #e9f9ff;
  --dim: #c9a8f0;
  --well: #120624;
  --title-a: #c4148f;
  --title-b: #087a96;
  --title-ink: #ffffff;
  --sel: #00e5ff;
  --sel-ink: #0a0414;
  --logo: #ff7ae0;
  --dither: #07020f #5a0f7a #ff3ec8 #7af3ff;
  --star: #7af3ff;
  --panel: #07020f;
  --panel-ink: #e9f9ff;
  --panel-hi: #ffffff;
  --panel-mid: #ffb3ea;
  --panel-soft: #9fe8ff;
  --panel-dim: #c38be0;
  --panel-edge: #3a1a66;
  --drop: rgba(0, 0, 0, .8);
  --ring: #000;
  --cast: #ff3ec8;
  --alert: #ffde59;
  --mark: #ffde59;
  color-scheme: dark;
}

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

/* (the page's pattern, if its theme has one, in 14 px dots) */
html { background: var(--page) var(--page-art) 0 0 / 14px 14px; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  background: var(--page) var(--page-art) 0 0 / 14px 14px;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 1.25rem;
  line-height: 1.2;
  overflow-x: hidden;
}

input, textarea, button { font: inherit; color: inherit; }
p { text-wrap: pretty; }
::selection { background: var(--sel); color: var(--sel-ink); }
a { color: inherit; text-underline-offset: .15em; }
:focus-visible { outline: 1px dotted var(--ink); outline-offset: 2px; }
[hidden] { display: none !important; }

.sr {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

canvas.stars {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.screen {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);   /* never wider than the screen, whatever a window holds on one line */
  place-items: center;
  padding: 2rem 1rem;
}

/* Bevels: raised for windows and buttons, sunken for fields and black panels */
.kg, .kbtn, .links a, .socials a, .case-opt {
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid);
}
.well, .kg-banner, .pic .avatar, .pic .pic-fx, .check span::before, .nfo, .social-icon, .case-eg {
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
  box-shadow: inset 1px 1px 0 var(--lo);
  border-radius: 0;
}

/* The window */

.kg {
  width: min(100%, 31rem);
  background: var(--face);
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid), 0 0 0 1px var(--ring), 0 1.5rem 4rem var(--drop);
}
/* A page whose owner picked the hard shadow: a solid block down and to the right instead of the soft glow (as wide as
   a phone's margin, so it never runs off the screen) */
.kg.cast { box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid), 0 0 0 1px var(--ring), .5rem .5rem 0 var(--cast); }
.kg.desk-win { width: min(100%, 78rem); }
.kg.dialog { width: min(100%, 27rem); }

.kg-title {
  display: flex;
  align-items: center;
  gap: 1ch;
  margin: 3px;
  padding: 2px 8px;
  background: linear-gradient(90deg, var(--title-a), var(--title-b));
  color: var(--title-ink);
  font-size: 1.125rem;
  letter-spacing: .04em;
}
.kg-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.kg-banner {
  position: relative;
  height: 9rem;
  margin: 0 6px;
  overflow: hidden;
  background: var(--panel);
}
.banner-fx { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* The logo banner is as tall as the art: the text without JavaScript, fx.js sets it otherwise */
.logo-banner { height: auto; }
.js .logo-banner { height: 18rem; }

/* Without JavaScript the block logo shows as text */
.nfo-logo {
  position: relative;
  width: fit-content;
  margin: 0 auto;
  padding: .75rem 0;
  max-width: 100%;
  overflow: hidden;
  font-family: Consolas, "DejaVu Sans Mono", monospace;
  font-size: 6px;   /* the art is 98 columns: this fits a phone */
  line-height: 1;
  color: #fff;
}
.js .nfo-logo { display: none; }

.kg-body { padding: .9rem 1rem 1rem; }

.kg-status {
  display: flex;
  gap: 3px;
  padding: 0 4px 4px;
  font-size: 1.0625rem;
  color: var(--dim);
}
.kg-status > span {
  flex: 1 0 auto;
  min-width: 0;
  padding: 1px 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: 1px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
}
/* The last cell is the one that gives way: a long one (the editor's list of addresses) ends in an ellipsis. The
   language switch after it never does, and keeps to the right end, where Windows shows the keyboard's language. */
.kg-status > span:last-child, .kg-status > span:has(+ .lang) { flex: 0 1 auto; }
.kg-status > span.lang { flex: none; margin-left: auto; }
.lang a { color: var(--dim); text-decoration: none; }
.lang a:hover { color: var(--ink); }
.lang a[aria-current] { color: var(--ink); text-decoration: underline; }

/* Fields */

.pitch { margin: 0 0 .9rem; color: var(--dim); }

.field {
  display: grid;
  grid-template-columns: 10ch minmax(0, 1fr);
  align-items: center;
  gap: 0 1ch;
  margin-bottom: .5rem;
}
.field > label, .field > .label { color: var(--dim); }

.well {
  width: 100%;
  margin: 0;
  padding: 2px 6px;
  background: var(--well);
  color: var(--ink);
  font-size: 1.375rem;
  outline: none;
}
.well:focus, .name-well:focus-within { box-shadow: inset 1px 1px 0 var(--lo), 0 0 0 1px var(--ink); }
.name-well { display: flex; align-items: baseline; }
.name-well .prefix { flex: none; color: var(--dim); }
.name-well input { flex: 1; min-width: 0; padding: 0; border: 0; background: transparent; outline: none; }

/* Status lines are little black keygen displays */
.lcd {
  min-height: 1.75em;
  background: var(--panel);
  color: var(--panel-ink);
  font-size: 1.25rem;
  overflow-wrap: anywhere;
}

.note { margin: .5rem 0 0; color: var(--dim); font-size: 1.125rem; }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

/* Buttons */

.kbtn {
  display: inline-block;
  padding: 3px 12px;
  background: var(--face);
  color: var(--ink);
  border-radius: 0;
  font-size: 1.375rem;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: .04em;
  cursor: pointer;
  white-space: nowrap;
}
/* With a letter case picked (a page's window, or the dashboard wearing it), what is drawn in capitals wears that one
   instead (lib/case.js) */
.cased .kbtn, .cased .group legend { text-transform: none; }
.cased .tag, .cased .swap-kind { text-transform: none; }
.kbtn:active {
  border-color: var(--lo) var(--hi) var(--hi) var(--lo);
  box-shadow: inset 1px 1px 0 var(--shade);
  padding: 4px 11px 2px 13px;
}
.kbtn:focus-visible { outline: 1px dotted var(--ink); outline-offset: -6px; }
/* The default button carries the extra black frame, as in Windows 95 */
.kbtn.primary { box-shadow: 0 0 0 1px var(--ring), inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid); }
.kbtn:disabled { color: var(--shade); text-shadow: 1px 1px 0 var(--hi); cursor: progress; }
.kbtn.small { padding: 1px 8px; font-size: 1.125rem; }
.kbtn.small:active { padding: 2px 7px 0 9px; }

.buttons { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-top: .9rem; }
.buttons.two { grid-template-columns: repeat(2, 1fr); }
.buttons.one { grid-template-columns: 1fr; }

.nfo {
  margin: .8rem 0 0;
  padding: 6px 8px;
  background: var(--well);
  color: var(--dim);
  white-space: pre-line;
}
.nfo p { margin: 0; }

/* A bio page */

.bio-banner { height: auto; min-height: 9rem; display: flex; align-items: center; }
/* (the badges take a row of their own under the picture and the name: .badges) */
.bio-head { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1rem; width: 100%; padding: 1rem; }
.bio-id { flex: 1 1 0; min-width: 0; }
.who {
  margin: 0;
  font-weight: 400;
  font-size: clamp(2.25rem, 9vw, 3rem);
  line-height: .95;
  overflow-wrap: anywhere;
  color: var(--panel-hi);
  text-shadow: 2px 2px 0 var(--panel);
}
.who-row { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: .6rem; }
.uid { color: var(--panel-soft); text-shadow: 1px 1px 0 var(--panel); white-space: nowrap; }
/* The page's other names, which all lead here */
.aka { margin: .45rem 0 0; color: var(--panel-dim); text-shadow: 1px 1px 0 var(--panel); overflow-wrap: anywhere; }
.aka-names { color: var(--panel-ink); }
.pic { flex: none; margin: 0; line-height: 0; }
.pic .avatar, .pic .pic-fx { width: 96px; height: 96px; background: var(--panel); object-fit: cover; }
.pic-fx { display: none; image-rendering: pixelated; }
.js .dithered .avatar { display: none; }
.js .dithered .pic-fx { display: block; }

.bio-text { font-size: 1.25rem; color: var(--ink); }

.links { display: grid; grid-template-columns: minmax(0, 1fr); gap: 5px; margin: .9rem 0 0; padding: 0; list-style: none; }
.links li { min-width: 0; }
.links a {
  display: flex;
  align-items: baseline;
  padding: 3px 10px;
  background: var(--face);
  text-decoration: none;
  font-size: 1.375rem;
}
/* Label and site both give way on narrow screens, ending in an ellipsis instead of running out of the button */
.l-label { flex: 0 1 auto; min-width: 0; max-width: 70%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lead { flex: 1 1 0; min-width: 2ch; margin: 0 1ch; overflow: hidden; white-space: nowrap; color: var(--shade); }
.lead::before { content: "................................................................................"; }
.l-site { flex: 0 1 auto; min-width: 0; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dim); font-size: 1.125rem; }
.links a:hover, .links a:focus-visible { background: var(--sel); color: var(--sel-ink); outline: none; }
.links a:hover .lead, .links a:hover .l-site, .links a:focus-visible .lead, .links a:focus-visible .l-site { color: inherit; }
.links a:active { border-color: var(--lo) var(--hi) var(--hi) var(--lo); }

/* Punastus's own marks, in its --blush: the name's shadow, three blush strokes after it, and a heart before each link
   (drawn, so screen readers read nothing more) */
.theme-punastus .who { text-shadow: 3px 3px 0 var(--blush); }
.theme-punastus .who::after, .theme-punastus .links a::before {
  content: "";
  display: inline-block;
  background: var(--blush);
  -webkit-mask: var(--mark-art) center / contain no-repeat;
  mask: var(--mark-art) center / contain no-repeat;
}
.theme-punastus .who::after {
  --mark-art: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 16'%3E%3Cpath d='M5 14 9 3M13 14 17 3M21 14 25 3' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E");
  width: .66em;
  height: .36em;
  margin-left: .2em;
  vertical-align: .14em;
}
.theme-punastus .links a::before {
  --mark-art: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 21s-7-4.4-9.5-8.6C.6 9.2 2.4 5 6.3 5c2.2 0 3.7 1.3 4.7 2.8C12 6.3 13.5 5 15.7 5c3.9 0 5.7 4.2 3.8 7.4C19 16.6 12 21 12 21z'/%3E%3C/svg%3E");
  flex: none;
  align-self: center;
  width: .72em;
  height: .72em;
  margin-right: .45em;
}

/* Pixel icons: 16×16 bitmaps at 2×, the same pixel size as the text and pictures */
.px { display: block; width: 32px; height: 32px; fill: currentColor; shape-rendering: crispEdges; }

.socials { display: flex; flex-wrap: wrap; gap: 5px; margin: .9rem 0 0; padding: 0; list-style: none; }
.socials a {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  background: var(--face);
  color: var(--ink);
}
.socials a:hover, .socials a:focus-visible { background: var(--sel); color: var(--sel-ink); outline: none; }
.socials a:active { border-color: var(--lo) var(--hi) var(--hi) var(--lo); box-shadow: inset 1px 1px 0 var(--shade); }

/* Embeds: live cards in black keygen panels, pictures dithered at 2× */
.embeds { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; margin: .9rem 0 0; padding: 0; list-style: none; }
.embed {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 6px 8px 6px 6px;
  background: var(--panel);
  color: var(--panel-ink);
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
}
.embed-pic { width: 64px; height: 64px; margin: 0; }
.embed .pic .avatar, .embed .pic .pic-fx { width: 64px; height: 64px; border: 0; box-shadow: none; }
.embed-noimg { display: grid; place-items: center; color: var(--panel-hi); border: 1px solid var(--panel-edge); }
.embed-text { min-width: 0; }
.embed-text p { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.embed-kind { font-size: 1rem; color: var(--panel-dim); }
.embed-title { font-size: 1.375rem; color: var(--panel-hi); }
.embed-sub { color: var(--panel-mid); }
.embed-go { align-self: center; }
/* (lit up when pointed at, like the links and socials) */
.embed-go:hover, .embed-go:focus-visible { background: var(--sel); color: var(--sel-ink); outline: none; }

/* Sliders as in Windows 95: a sunken groove, filled as far as it is set (--at, which the scripts keep), and a raised
   block to drag. On a black panel the groove is the panel's. */
.slider {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 22px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  --fill: var(--ink);
  --groove: var(--well);
  --rim-a: var(--shade);
  --rim-b: var(--hi);
}
.slider::-webkit-slider-runnable-track {
  box-sizing: content-box;
  height: 4px;
  border: 2px solid;
  border-color: var(--rim-a) var(--rim-b) var(--rim-b) var(--rim-a);
  background: linear-gradient(90deg, var(--fill) var(--at, 0%), var(--groove) 0);
}
.slider::-moz-range-track {
  box-sizing: content-box;
  height: 4px;
  border: 2px solid;
  border-color: var(--rim-a) var(--rim-b) var(--rim-b) var(--rim-a);
  background: linear-gradient(90deg, var(--fill) var(--at, 0%), var(--groove) 0);
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  box-sizing: border-box;
  width: 11px;
  height: 20px;
  margin-top: -8px;
  background: var(--face);
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  border-radius: 0;
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid);
}
.slider::-moz-range-thumb {
  box-sizing: border-box;
  width: 11px;
  height: 20px;
  background: var(--face);
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  border-radius: 0;
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid);
}
.slider:disabled { cursor: default; }
.slider:disabled::-webkit-slider-thumb { visibility: hidden; }
.slider:disabled::-moz-range-thumb { visibility: hidden; }
.slider:focus-visible { outline: 1px dotted var(--ink); outline-offset: 2px; }

/* A page's music: a black panel like the cards, play at one end and mute and volume at the other, between them the
   track's name (and little bars that dance while it plays) over how far it has played. Without JavaScript, the
   browser's own player in its place. */
.player {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "play bar sound";
  align-items: center;
  gap: 2px 10px;
  padding: 6px 8px 6px 6px;
  background: var(--panel);
  color: var(--panel-ink);
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
}
.player.titled { grid-template-areas: "play name sound" "play bar sound"; }
html:not(.js) .player > :not(audio) { display: none; }
.player > audio { display: block; width: 100%; grid-column: 1 / -1; }
.js .player > audio { display: none; }
.player .kbtn { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; }
.player .kbtn:active { padding: 1px 0 0 1px; }
/* (lit up when pointed at, like the links, socials and the embeds' buttons) */
.player .kbtn:hover, .player .kbtn:focus-visible { background: var(--sel); color: var(--sel-ink); outline: none; }
.player-play { grid-area: play; }
.player-sound { grid-area: sound; display: flex; align-items: center; gap: 8px; }
.player-play .i-pause, .player.playing .player-play .i-play, .player-mute .i-muted, .player-mute[aria-pressed="true"] .i-sound { display: none; }
.player.playing .player-play .i-pause, .player-mute[aria-pressed="true"] .i-muted { display: block; }
.player-title { grid-area: name; display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0; color: var(--panel-hi); font-size: 1.375rem; }
.player-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.player-bar { grid-area: bar; display: flex; align-items: center; gap: 8px; min-width: 0; }
.player-time { flex: none; color: var(--panel-dim); font-size: 1.0625rem; }
.player .slider { --fill: var(--panel-hi); --groove: var(--panel); --rim-a: var(--panel-edge); --rim-b: var(--panel-dim); }
.player .slider:focus-visible { outline-color: var(--panel-hi); }
.player-vol { width: 4.5rem; }
.player.fixed-volume .player-vol { display: none; }
/* Four pixel bars of an equaliser, which dance while it plays */
.player-eq { display: flex; flex: none; align-items: flex-end; gap: 2px; height: 14px; }
.player-eq span { width: 3px; height: 6px; background: var(--panel-hi); }
.player-eq span:nth-child(2) { height: 12px; }
.player-eq span:nth-child(3) { height: 4px; }
.player-eq span:nth-child(4) { height: 9px; }
.player.playing .player-eq span { animation: eq .8s steps(4) infinite alternate; }
.player.playing .player-eq span:nth-child(2) { animation-duration: .6s; animation-delay: -.2s; }
.player.playing .player-eq span:nth-child(3) { animation-duration: .9s; animation-delay: -.5s; }
.player.playing .player-eq span:nth-child(4) { animation-duration: .7s; animation-delay: -.1s; }
@keyframes eq { from { height: 2px; } to { height: 14px; } }
@media (prefers-reduced-motion: reduce) { .player.playing .player-eq span { animation: none; } }
/* (with music fx on, player.js sets the bars from what is heard) */
.player.live .player-eq span { animation: none; }

/* Music fx (player.js): a light behind the page shines with the music, a haze in the page's own backdrop ink,
   brightest round the window and fading out to the edges, under the background's animation and the window, as bright
   as the music is loud (player.js sets its opacity). In the dashboard's preview, it fills the preview behind the
   page's window. */
.music-haze {
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse 75% 70% at 50% 45%, color-mix(in srgb, var(--star) 45%, transparent), transparent);
}
.pv-page > .music-haze { position: absolute; z-index: -1; }

/* And the whole page glows with the music, as After Effects's Deep Glow does it. Whatever is bright on the page, the
   background's stars and everything in the window, its text, icons, picture and edges, gives off light, near and far,
   as bright as the music is loud. player.js has the filters, one for the background and one for the window, and puts
   .glowing on the page while the music is heard, and .glow-back too when its owner wants the background alone to glow.
   In the dashboard, only the preview's window glows: the filter on the dashboard's background, or on the preview that
   scrolls, has a browser drawing it without a graphics card stop to a frame or two a second. */
.bloom { position: absolute; width: 0; height: 0; }
.glowing > body.bio > canvas.stars { filter: url(#bloom-page); }
.glowing:not(.glow-back) > body.bio > .screen, .glowing:not(.glow-back) #pv-page > .kg { filter: url(#bloom-window); }

/* A page that keeps its player off: a speaker at the end of the status bar, as in Windows's tray, crossed out until the
   music plays. Nothing without JavaScript, which is what plays it. */
.player.mini { display: flex; padding: 0; background: none; border: 0; }
.player.mini > audio, html:not(.js) .player.mini { display: none; }
.kg-status > span:has(> .player.mini) { flex: none; padding: 0; }
.kg-status > span:has(+ span > .player.mini) { flex: 0 1 auto; }
.player.mini .player-play {
  display: grid;
  place-items: center;
  width: 30px;
  height: 100%;
  min-height: 20px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--dim);
  cursor: pointer;
}
.player.mini .player-play:hover, .player.mini.playing .player-play { color: var(--ink); }
.player.mini .player-play:focus-visible { outline: 1px dotted var(--ink); outline-offset: -3px; }
.player.mini .px { width: 16px; height: 16px; }
.player.mini .i-sound, .player.mini.playing .i-muted { display: none; }
.player.mini.playing .i-sound { display: block; }
@media (pointer: coarse) { .player.mini .player-play { width: 44px; } }

/* What a page shows first when its owner wants the music from the first moment: the page emptied, its background
   moving on, and "click to enter" in the middle, the page hidden until it is pressed. Only with JavaScript (player.js
   takes it away), and should that never run, the page shows after a few seconds all the same. */
.enter { display: none; }
.js .gate .enter {
  position: fixed;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  padding: 1rem;
  cursor: pointer;
  animation: unseen 0s 6s forwards;
}
.js .gate > .screen { visibility: hidden; animation: seen 0s 6s forwards; }
.js .gate.gated .enter, .js .gate.gated > .screen { animation: none; }
.enter:focus { outline: none; }
@keyframes seen { to { visibility: visible; } }
@keyframes unseen { to { visibility: hidden; } }
.enter-go {
  padding: .75rem 1.25rem;
  background: none;
  border: 0;
  color: var(--page-ink);
  font-size: clamp(1.75rem, 7vw, 2.25rem);
  letter-spacing: .08em;
  cursor: pointer;
}
.enter-go:focus-visible { outline: 1px dotted var(--page-ink); outline-offset: 2px; }

/* And pressed, the window comes in as its owner picked (lib/music.js): player.js puts .enter-<id> on it until it is
   in, and the dashboard's cards on their little windows (.enter-eg-win) while pointed at. Faded in; grown from where
   it was pressed (--from), as Windows opens one; dropped in from above the screen with a bounce (--fall, --bounce: a
   little window falls as far as its panel); drawn from the top down a band at a time, as a slow line draws a picture;
   switched on like an old picture tube, a white line (--line of its height; a little window's is thicker) that opens
   out and fades to the picture; or flickering in in pieces, each band of it off to one side. (Its shadow is let
   through what is cut away, -5rem round it.) Nothing for visitors who ask for less motion. */
@media (prefers-reduced-motion: no-preference) {
  .enter-fade { animation: enter-fade .6s ease-out both; }
  .enter-zoom { transform-origin: var(--from, 50% 50%); animation: enter-zoom .35s cubic-bezier(.2, .7, .3, 1) both; }
  .enter-drop { animation: enter-drop .75s both; }
  .enter-wipe { animation: enter-wipe .9s steps(12, end) both; }
  .enter-crt { position: relative; animation: enter-crt .65s cubic-bezier(.2, .8, .3, 1) both; }
  .enter-crt::after { content: ""; position: absolute; inset: -2px; background: #fff; pointer-events: none; animation: enter-crt-line .65s linear both; }
  .enter-glitch { animation: enter-glitch .6s steps(1, end) both; }
}
@keyframes enter-fade { from { opacity: 0; } }
@keyframes enter-zoom { from { opacity: 0; transform: scale(.05); } 30% { opacity: 1; } }
@keyframes enter-drop {
  from { transform: translateY(var(--fall, calc(-100vh - 100%))); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  60% { transform: none; animation-timing-function: cubic-bezier(0, .55, .45, 1); }
  80% { transform: translateY(var(--bounce, -1.5rem)); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  to { transform: none; }
}
@keyframes enter-wipe { from { clip-path: inset(-5rem -5rem 100% -5rem); } to { clip-path: inset(-5rem); } }
@keyframes enter-crt {
  from { transform: scale(0, var(--line, .006)); }
  30% { transform: scale(1, var(--line, .006)); }
  60%, to { transform: none; }
}
@keyframes enter-crt-line { 35% { opacity: 1; } 80%, to { opacity: 0; } }
@keyframes enter-glitch {
  from { opacity: 0; }
  8% { opacity: 1; clip-path: inset(12% -5rem 58% -5rem); transform: translateX(-4%); }
  16% { clip-path: inset(52% -5rem 18% -5rem); transform: translateX(3%); }
  24% { opacity: 0; }
  34% { opacity: 1; clip-path: inset(-5rem -5rem 72% -5rem); transform: translateX(2%); filter: invert(1); }
  44% { clip-path: inset(68% -5rem -5rem -5rem); transform: translateX(-2.5%); filter: none; }
  54% { clip-path: inset(24% -5rem 30% -5rem); transform: translateX(1.2%); }
  64% { clip-path: inset(-5rem); transform: translateX(-1%) skewX(-3deg); }
  76% { clip-path: inset(40% -5rem 44% -5rem); transform: translateX(3.5%); }
  86% { clip-path: inset(-5rem); transform: translateX(.3%); }
  to { opacity: 1; clip-path: inset(-5rem); transform: none; filter: none; }
}

/* Discord status as a little square: full, half, crossed, empty */
.dot { display: inline-block; width: 10px; height: 10px; margin-right: 6px; border: 2px solid var(--panel-hi); vertical-align: 0; }
.dot.online { background: var(--panel-hi); }
.dot.idle { background: linear-gradient(135deg, var(--panel-hi) 50%, transparent 50%); }
.dot.dnd { background: linear-gradient(var(--panel-hi), var(--panel-hi)) center / 100% 2px no-repeat; }

/* Dashboard: a toolbar that stays at the top (save and its status, the page, log out) over tabs, one part of the
   dashboard open at a time; on a phone the save bar runs along the bottom of the screen */

.ed-bar {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: -.9rem -1rem .9rem;
  padding: 6px 1rem;
  background: var(--face);
  border-bottom: 1px solid var(--shade);
  box-shadow: 0 1px 0 var(--hi);
}
.ed-save { display: flex; gap: 6px; flex: 1 1 30rem; min-width: 0; margin: 0; }
.ed-save .lcd { flex: 1 1 auto; min-width: 0; min-height: 0; margin: 0; display: flex; align-items: center; }
.ed-nav { display: flex; gap: 6px; }

/* Unsaved: the status turns red and says what, and each group with changes is starred */
.lcd.alert { color: var(--alert); }
.lcd.alert::before { content: "■"; margin-right: 1ch; }
.group.changed > legend::after { content: "*"; margin-left: .6ch; color: var(--mark); }

/* Tabs, as on a Windows 95 property sheet: the open one stands taller and runs into the sheet under it. One with
   unsaved edits is starred, as its group is. */
.ed-tabs { display: flex; flex-wrap: wrap; align-items: flex-end; padding-left: 2px; }
.ed-tab {
  position: relative;
  margin: 0 -2px 0 0;
  padding: 2px 12px 3px;
  background: var(--face);
  color: var(--ink);
  border: 2px solid;
  border-bottom: 0;
  border-color: var(--hi) var(--lo) transparent var(--hi);
  box-shadow: inset -1px 0 0 var(--shade), inset 1px 1px 0 var(--mid);
  font: inherit;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
}
.ed-tab[aria-selected="true"] { z-index: 1; margin-bottom: -2px; padding: 4px 14px 5px; }
.ed-tab.changed::after { content: "*"; margin-left: .4ch; color: var(--mark); }
.ed-tab:focus-visible { outline: 1px dotted var(--ink); outline-offset: -5px; }
.ed-sheet {
  padding: .9rem .8rem .8rem;
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid);
}
.ed-panel { display: flex; flex-direction: column; gap: .9rem; min-width: 0; }
.ed-sheet .group { margin: 0; }

/* Sivu: the person on the left, what the page lists on the right, in the page's own order. The other tabs set their
   groups side by side where they fit. Both follow the dashboard window's own width, which the preview beside it
   takes from on a wide screen. */
.ed-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: .9rem; align-items: start; }
.ed-col { display: flex; flex-direction: column; gap: .9rem; min-width: 0; }
.ed-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); gap: .9rem; align-items: start; }
#panel-mail > .ed-pair { max-width: 46rem; }
.desk-win { container: desk / inline-size; }
@container desk (min-width: 45rem) {
  .ed-cols { grid-template-columns: minmax(15rem, 22rem) minmax(0, 1fr); }
}
@media (max-width: 47.99rem) {
  .desk .screen { padding-bottom: 6rem; }
  .ed-bar { position: static; }
  .ed-nav { flex: 1 1 100%; }
  .ed-nav .kbtn { flex: 1 1 0; }
  .ed-save {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;
    flex-direction: row-reverse;
    padding: 8px;
    background: var(--face);
    border-top: 2px solid var(--hi);
    box-shadow: 0 -1px 0 var(--shade), 0 -8px 24px rgba(0, 0, 0, .6);
  }
  /* Fingers, not a mouse */
  .desk .kbtn { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; }
  .desk .well { min-height: 44px; }
  .desk .kbtn.icon { width: 44px; }
  .desk .check { min-height: 44px; }
  .desk .ed-tab { min-height: 44px; }
  .desk .ed-tab[aria-selected="true"] { min-height: 48px; }
}

/* On a wide screen the page shows beside the dashboard in a window of its own, as what is picked and typed so far
   would make it (app.js keeps it current). The toolbar's Esikatselu puts it away and brings it back. */
.preview-win, .desk .ed-nav .pv-toggle { display: none; }
@media (min-width: 70rem) {
  .desk .ed-nav .pv-toggle { display: inline-block; }
  .desk-screen.with-preview {
    grid-template-columns: minmax(0, 78rem) minmax(22rem, 31rem);
    justify-content: center;
    place-items: start stretch;
    gap: 1.25rem;
  }
  .desk-screen.with-preview .desk-win { width: 100%; }
  .desk-screen.with-preview .preview-win { display: block; position: sticky; top: 1rem; width: 100%; }
}
.pv-toggle[aria-pressed="true"] {
  border-color: var(--lo) var(--hi) var(--hi) var(--lo);
  box-shadow: inset 1px 1px 0 var(--shade);
  background: repeating-conic-gradient(var(--hi) 0 25%, var(--face) 0 50%) 0 0 / 2px 2px;
}
/* Just the page's window, on the dashboard's background (the page's own); scrolls by itself when taller than the screen */
/* (its own layer, so the music's glow goes under the window) */
.pv-page { position: relative; z-index: 0; max-height: calc(100vh - 2rem); overflow-y: auto; }
.pv-page > .kg { margin: 0 auto; }
/* (room for a hard shadow, which the scrolling box would cut off) */
.pv-page:has(> .kg.cast) { padding: 0 .5rem .5rem 0; }

/* Etched group boxes */
.group {
  margin: 0 0 .9rem;
  padding: .6rem .8rem .8rem;
  border: 1px solid var(--shade);
  box-shadow: 1px 1px 0 var(--hi), inset 1px 1px 0 var(--hi);
}
.group legend { padding: 0 .4rem; color: var(--ink); text-transform: uppercase; letter-spacing: .04em; }
.group > label { display: block; margin: .6rem 0 .2rem; color: var(--dim); }
.group > label:first-of-type { margin-top: 0; }
.group > label.check { margin: 0; color: var(--ink); }
.group textarea { resize: vertical; line-height: 1.15; }
.group .lcd { margin-top: .6rem; }
.group .note { margin: 0 0 .4rem; }

.avatar-row { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.avatar-tools { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.avatar-tools:has(input[type=file]:focus-visible) label.kbtn { outline: 1px dotted var(--ink); outline-offset: -6px; }

/* The tab icon on a tab, raised as the dashboard's own are and standing on the edge of its sheet, at the size a
   browser's tab shows it */
.tab-eg {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  max-width: min(100%, 16rem);
  padding: 4px 14px 5px 10px;
  background: var(--face);
  color: var(--ink);
  border: 2px solid;
  border-bottom: 0;
  border-color: var(--hi) var(--lo) transparent var(--hi);
  box-shadow: inset -1px 0 0 var(--shade), inset 1px 1px 0 var(--mid), 0 2px 0 var(--hi);
  line-height: 1.2;
}
.tab-eg img { flex: none; width: 16px; height: 16px; object-fit: cover; }
.tab-eg-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group > .avatar-row + label.check, .group > .well + label.check, .group > .kbtn + label.check, .group > .case-opts + label.check { margin-top: .5rem; }

/* Music: its player while there is a track (with no volume of its own: the starting volume below sets it), the buttons
   to put one in or take it out, and how it plays */
.group > .player { margin: 0 0 .5rem; }
.group > .player .player-vol { display: none; }
.music-tools { display: flex; flex-wrap: wrap; gap: 6px; }
.music-set > label:not(.check), .music-pick { display: block; margin: .6rem 0 .2rem; color: var(--dim); }
.music-set > label.check { margin-top: .5rem; }
.music-set output { color: var(--ink); }
.music-fx { display: grid; }
/* Each music fx's strength, under its box and in line with its words (dimmed, and its slider without a block, while
   it is off) */
.fx-power { display: grid; grid-template-columns: auto minmax(0, 14rem); gap: .8rem; align-items: center; margin: 0 0 .35rem 30px; color: var(--dim); }
.fx-power:has(.slider:disabled) output { color: var(--dim); }
.music-fx .fx-only { margin: 0 0 .35rem 30px; }
.music-fx .fx-only:has(input:disabled) { color: var(--dim); cursor: default; }
.play-opts { grid-template-columns: minmax(0, 1fr); }
.play-note { color: var(--dim); font-size: 1.0625rem; }
.play-opt:has(input:checked) .play-note { color: var(--ink); }
/* A way it can't start (on play, with no player on the page): greyed out and embossed, as Windows 95 shows what can't
   be picked */
.play-opt:has(input:disabled) { cursor: default; }
.play-opt:has(input:disabled) .case-name, .play-opt:has(input:disabled) .play-note { color: var(--shade); text-shadow: 1px 1px 0 var(--hi); }

.links-edit { margin: 0 0 .5rem; padding: 0; list-style: none; }
.link-row { display: grid; grid-template-columns: 1fr 1.6fr auto; gap: 5px; margin-bottom: 5px; }
.row-tools { display: flex; gap: 3px; }
.kbtn.icon { width: 2.2rem; padding: 2px 0; text-transform: none; }
/* A row's buttons lie flat until pointed at or used, so a long list reads as its fields */
.row-tools .kbtn.icon { border-color: transparent; box-shadow: none; background: transparent; color: var(--dim); }
li:hover > .row-tools .kbtn.icon, li:focus-within > .row-tools .kbtn.icon { color: var(--ink); }
.row-tools .kbtn.icon:hover, .row-tools .kbtn.icon:focus-visible {
  background: var(--face);
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid);
}
.row-tools .kbtn.icon:active { border-color: var(--lo) var(--hi) var(--hi) var(--lo); box-shadow: inset 1px 1px 0 var(--shade); }

/* The sites socials know: folded into the note, opened on a click */
.known { display: inline; }
.known summary { display: inline; cursor: pointer; text-decoration: underline dotted; text-underline-offset: .15em; }
.known summary:focus-visible { outline: 1px dotted var(--ink); outline-offset: 2px; }
.known-list { display: block; margin-top: .2rem; }

.social-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 5px; align-items: stretch; margin-bottom: 5px; }
.social-icon { display: grid; place-items: center; width: 40px; background: var(--panel); color: var(--panel-hi); }

/* Where a Discord profile card comes from: the server's icon, what to do there, and the way in */
.discord-hint { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 6px 10px; align-items: start; margin: .2rem 0 .7rem; }
.discord-hint .social-icon { height: 40px; }
.discord-hint .kbtn { grid-column: 2; justify-self: start; }
.group .discord-hint .note { margin: 0; }

.mail-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; margin-top: .3rem; }
.mail-addresses { margin: .5rem 0 0; }
/* Short choices side by side, as many to a row as fit: domains, and the names picked for mail */
.chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 9rem), 1fr)); column-gap: 10px; }
.chips .check { min-width: 0; }
.chips .check.locked { grid-column: 1 / -1; }
.chips .check span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group .mail-pick { margin: .6rem 0 .1rem; color: var(--dim); }
.mail-pick + .mail-addresses { margin-top: 0; }
.group .mail-spam { margin: .4rem 0 0; }
.mail-tools { display: flex; gap: 6px; margin-top: .6rem; }

/* Checkboxes, skinned */
.check { position: relative; display: flex; align-items: center; padding: 2px 0; cursor: pointer; }
.check input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.check span::before {
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 10px;
  vertical-align: -2px;
  background: var(--well);
}
.check input:checked + span::before { box-shadow: inset 1px 1px 0 var(--lo), inset 0 0 0 3px var(--well), inset 0 0 0 8px var(--ink); }
.check small { color: var(--dim); font-size: 1.0625rem; }
.check:has(input:focus-visible) span { outline: 1px dotted var(--ink); outline-offset: 2px; }
.check.locked { cursor: default; color: var(--dim); }

/* Letter case: a card per choice, raised until picked and pressed in once it is (checkered, like a Windows 95 toggle
   that is on). Its name is written in its own case, over the owner's name as the page will show it. */
.case-opts { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr)); gap: 6px; }
.case-opt { position: relative; display: grid; gap: 4px; min-width: 0; padding: 4px 6px 6px; background: var(--face); cursor: pointer; }
.case-opt input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.case-name { display: flex; align-items: center; color: var(--dim); font-size: 1.125rem; }
.case-name::before {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  margin-right: 8px;
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
  border-radius: 50%;
  background: var(--well);
  box-shadow: inset 1px 1px 0 var(--lo);
}
.case-eg {
  display: block;
  padding: 1px 8px 2px;
  background: var(--panel);
  color: var(--panel-dim);
  font-size: 1.625rem;
  line-height: 1.1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.case-opt:hover .case-eg { color: var(--panel-mid); }
.case-opt:has(input:checked) {
  padding: 5px 5px 5px 7px;
  background: repeating-conic-gradient(var(--hi) 0 25%, var(--face) 0 50%) 0 0 / 2px 2px;
  border-color: var(--lo) var(--hi) var(--hi) var(--lo);
  box-shadow: inset 1px 1px 0 var(--shade);
}
.case-opt:has(input:checked) .case-name { color: var(--ink); }
.case-opt:has(input:checked) .case-name::before { box-shadow: inset 1px 1px 0 var(--lo), inset 0 0 0 3px var(--well), inset 0 0 0 6px var(--ink); }
.case-opt:has(input:checked) .case-eg { color: var(--panel-hi); }
.case-opt:has(input:focus-visible) .case-name { outline: 1px dotted var(--ink); outline-offset: 1px; }

/* Theme: the same cards, each with a little window in its theme's shades (its class sets them for that window):
   the page around it, the title bar, the banner with the name, a link */
.theme-eg {
  display: grid;
  gap: 4px;
  margin: 5px;
  padding: 4px;
  background: var(--face);
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  box-shadow: 0 0 0 5px var(--page);
}
.theme-eg-bar { height: 8px; background: linear-gradient(90deg, var(--title-a), var(--title-b)); }
.theme-eg-banner {
  padding: 2px 6px;
  background: var(--panel);
  color: var(--panel-hi);
  font-size: 1.375rem;
  line-height: 1.1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.theme-eg-link {
  height: 14px;
  background: var(--face);
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid);
}

/* Background: the same cards, smaller, each running its animation as a preview on a black panel */
.fx-opts { grid-template-columns: repeat(auto-fill, minmax(min(100%, 8.5rem), 1fr)); }
.fx-eg { display: block; width: 100%; height: 44px; background: var(--panel); }

/* How the page comes in behind "click to enter": the same small cards, each a little window on a black panel, which
   comes in that way while the card is pointed at or reached from the keyboard (the page's own animations, above) */
.enter-opts { grid-template-columns: repeat(auto-fill, minmax(min(100%, 8.5rem), 1fr)); }
.enter-eg { display: grid; place-items: center; height: 52px; overflow: hidden; background: var(--panel); }
.enter-eg-win {
  --fall: -56px;
  --bounce: -4px;
  --line: .08;
  display: grid;
  align-content: start;
  width: 58%;
  height: 32px;
  padding: 2px;
  background: var(--face);
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
}
.enter-opt:not(:hover):not(:has(input:focus-visible)) .enter-eg-win { animation: none; }
.enter-opt:not(:hover):not(:has(input:focus-visible)) .enter-eg-win::after { content: none; }

/* Emoticons: a black panel of them under the bio, shut until opened */
.emo { margin-top: 6px; }
.emo-panel {
  margin-top: 6px;
  max-height: 16rem;
  overflow-y: auto;
  padding: 4px 8px 8px;
  background: var(--panel);
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
}
.emo-group { margin: 6px 0 4px; color: var(--panel-dim); font-size: 1rem; }
.emo-list { display: flex; flex-wrap: wrap; gap: 4px; }
.emo-pick {
  min-width: 2.4rem;
  padding: 2px 8px;
  background: transparent;
  color: var(--panel-ink);
  border: 1px solid var(--panel-edge);
  font: inherit;
  font-size: 1.25rem;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
}
.emo-pick:hover, .emo-pick:focus-visible { background: var(--panel-ink); color: var(--panel); outline: none; }
@media (max-width: 47.99rem) { .emo-pick { min-height: 44px; } }

/* Names: the main one tagged, each other one with its buttons and whatever is under way with it, whether the page shows
   them, offers to answer on a black panel, and room for more */
.names-list { margin: 0 0 .5rem; padding: 0; list-style: none; }
.group > .names-list + label.check { margin-bottom: .5rem; }
.name-row { padding: 6px 0; border-bottom: 1px solid var(--shade); box-shadow: 0 1px 0 var(--hi); }
.name-addr { font-size: 1.375rem; overflow-wrap: anywhere; }
.tag { display: inline-block; margin-left: .6ch; padding: 0 6px; background: var(--panel); color: var(--panel-hi); font-size: 1rem; letter-spacing: .06em; text-transform: uppercase; vertical-align: .15em; }
.name-tools { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.name-note { margin: 5px 0 0; color: var(--dim); font-size: 1.0625rem; }
.name-note .kbtn { margin-left: .4ch; }
.offer-in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px 10px;
  align-items: center;
  margin: 0 0 .5rem;
  padding: 6px 8px;
  background: var(--panel);
  color: var(--panel-ink);
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
}
.offer-in p { margin: 0; overflow-wrap: anywhere; }
.offer-in p::before { content: "■"; margin-right: 1ch; color: var(--alert); }
.names-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.names-tools .kbtn:disabled { cursor: default; }
.names-count { margin-left: auto; color: var(--dim); }
.group .names-tools + .note { margin: .4rem 0 0; }
#names-status:empty { display: none; }

/* The names' dialogs: windows over the dashboard, which dims behind them */
.kg.dlg { width: min(calc(100% - 1rem), 30rem); max-height: calc(100vh - 1rem); padding: 0; overflow: auto; color: var(--ink); }
.dlg::backdrop { background: rgba(0, 0, 0, .55); }
.dlg h2 { margin: 0 0 .3rem; font-weight: 400; font-size: 1.5rem; }
.dlg .note { margin: .3rem 0 .6rem; }
.dlg form > label, .give-ask > label, .give-code > .label { display: block; margin: .6rem 0 .2rem; color: var(--dim); }
.dlg .lcd { margin: .6rem 0 0; }
.dlg .field .lcd { margin: 0; }
.dlg [data-status]:empty { display: none; }
.dlg-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; }
.dlg-row .lcd { margin: 0; }
.dlg-foot { padding-top: .5rem; border-top: 1px solid var(--shade); box-shadow: inset 0 1px 0 var(--hi); }
.code { letter-spacing: .12em; }
output.code { display: flex; align-items: center; justify-content: center; margin: 0; font-size: 1.75rem; color: var(--panel-hi); }
input.code { font-size: 1.625rem; text-align: center; text-transform: uppercase; }
.swap-give { margin: 0; font-size: 1.375rem; overflow-wrap: anywhere; }
.swap-cards { display: grid; gap: 6px; margin: .6rem 0 0; }
.swap-card {
  display: grid;
  grid-template-columns: 6ch minmax(0, 1fr);
  column-gap: 10px;
  align-items: baseline;
  padding: 6px 10px;
  background: var(--panel);
  color: var(--panel-ink);
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
}
.swap-card p { margin: 0; }
.swap-kind { grid-row: span 2; color: var(--panel-dim); font-size: 1rem; letter-spacing: .06em; text-transform: uppercase; }
.swap-name { color: var(--panel-hi); font-size: 1.5rem; overflow-wrap: anywhere; }
.swap-sub { color: var(--panel-mid); font-size: 1.0625rem; }

.ed-account form { margin: 0; }
.ed-account .kbtn { margin-top: .6rem; }
.ed-account .status { min-height: 1.2em; margin: .4rem 0 0; }

/* Dialogs: errors and confirmations */

.err-row { display: flex; gap: 1rem; align-items: flex-start; }
.err-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #000;
  color: #fff;
  border: 2px solid var(--shade);
  font-size: 2rem;
  line-height: 1;
}
.err-icon.ok { border-radius: 0; font-size: 1.75rem; }
.err-row h1 { margin: 0; font-weight: 400; font-size: 1.75rem; }
.err-row h2 { margin: 0; }
.err-row p { margin: .4rem 0 0; overflow-wrap: anywhere; }

@media (max-width: 34rem) {
  .screen { padding: 1rem .5rem; place-items: start center; }
  .kg-body { padding: .8rem .7rem .9rem; }
  .field { grid-template-columns: minmax(0, 1fr); }
  .field > label, .field > .label { margin-bottom: 2px; }
  .buttons { grid-template-columns: 1fr 1fr; }
  .buttons .kbtn:last-child:nth-child(3) { grid-column: 1 / -1; }
  .link-row { grid-template-columns: 1fr auto; }
  .link-row [name=url] { grid-column: 1 / -1; grid-row: 2; }
  .link-row .row-tools { grid-column: 2; grid-row: 1; }
  .embed { grid-template-columns: 64px minmax(0, 1fr); }
  .embed-go { grid-column: 2; justify-self: start; }
  /* (a phone has buttons for the volume, and the bar needs the room) */
  .player-vol { display: none; }
  .social-row { grid-template-columns: auto 1fr; }
  .social-row .row-tools { grid-column: 2; justify-self: end; }
  .mail-row { grid-template-columns: 1fr; }
  .offer-in { grid-template-columns: 1fr; }
  .offer-in .kbtn { justify-self: start; }
  .ed-bar { margin: -.8rem -.7rem .9rem; padding: 6px .7rem; }
  /* Every tab on one row, even in Finnish */
  .ed-tab { padding: 2px 6px 3px; }
  .ed-tab[aria-selected="true"] { padding: 4px 8px 5px; }
  .ed-sheet { padding: .7rem .5rem .6rem; }
  .bio-head { gap: .75rem; padding: .75rem; }
}

/* Badges: nameplates across the foot of a page's banner (views.js plate), a 16×16 picture and the badge's name, or its
   few letters. A badge's tile picks the frame: black a double rule, grey dotted, white the plate in reverse. Every shade
   is one of the theme's panel shades, each pair one test/themes.test.js keeps at 4.5:1, so every theme's plates read;
   the faces are solid, so the banner's animation never runs under the letters. The corners are cut a pixel wide, and
   the letters are capitals unless the page has a case of its own (.cased), as buttons are. */
.badges { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.plate { flex: none; display: inline-flex; max-width: 100%; margin: 0; font-size: 1.25rem; line-height: 1; letter-spacing: .08em; text-transform: uppercase; }
.plate-face {
  display: flex;
  align-items: stretch;
  min-width: 0;
  height: 28px;
  background: var(--panel);
  color: var(--panel-ink);
  border: 3px double var(--panel-dim);
  clip-path: polygon(2px 0, calc(100% - 2px) 0, 100% 2px, 100% calc(100% - 2px), calc(100% - 2px) 100%, 2px 100%, 0 calc(100% - 2px), 0 2px);
}
.plate-icon { flex: none; display: grid; place-items: center; width: 24px; background: var(--panel-edge); color: var(--panel-hi); }
.plate-icon .px { width: 16px; height: 16px; }
/* A name longer than a plate ends in an ellipsis (a block of its own, as text-overflow needs) */
.plate-name { display: block; align-self: center; min-width: 0; max-width: 10.5rem; padding: 0 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plate-grey .plate-face { border: 2px dotted var(--panel-dim); }
.plate-grey .plate-icon { background: var(--panel); color: var(--panel-ink); }
.plate-white .plate-face { background: var(--panel-hi); color: var(--panel); border: 2px solid var(--panel-hi); }
.plate-white .plate-icon { background: var(--panel); color: var(--panel-hi); }
.plate-text { letter-spacing: .14em; }
.plate-text .plate-icon { display: none; }
.plate-text .plate-name { padding: 0 10px; }
.cased .plate { text-transform: none; }
/* Punastus's blush, which its name casts too, behind the plate in reverse (on the plate's outside: the cut corners
   would clip it away) */
.theme-punastus .plate-white { filter: drop-shadow(2px 2px 0 var(--blush)); }
/* The plate that opens the rest of a page's badges, and the rest, in place: they flow on after it as more plates */
.badges .more { flex: 0 1 auto; max-width: 100%; min-width: 0; }
.badges .more details[open] { display: flex; flex-wrap: wrap; gap: 6px; }
.plate-more { list-style: none; cursor: pointer; }
.plate-more::-webkit-details-marker { display: none; }
.plate-more .plate-face { border: 2px solid var(--panel-dim); }
.plate-more:focus-visible { outline: 1px dotted var(--panel-hi); outline-offset: 2px; }
details[open] > .plate-more .more-n, details:not([open]) > .plate-more .more-less { display: none; }
.badges-rest { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; margin: 0; padding: 0; list-style: none; }
/* In lists: the picture or the letters alone, smaller; a plate in reverse keeps a dark edge where lists are light */
.plate.mini { font-size: 1.0625rem; letter-spacing: .04em; vertical-align: middle; }
.plate.mini .plate-face { height: 24px; }
.plate.mini .plate-icon { width: 20px; }
.plate.mini .plate-name { padding: 0 5px; }
.plate.mini:not(.plate-text) .plate-name { display: none; }
.plate.mini.plate-white .plate-face { border-color: var(--panel); }
.tiles { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 3px; vertical-align: middle; }
.tiles-more { font-size: 1.0625rem; color: var(--dim); padding: 0 2px; }

/* The verified seal after a page's name (views.js seal), in the panel's brightest shade; small after a name in a list */
.verified { flex: none; align-self: center; line-height: 0; color: var(--panel-hi); }
.verified.mini { display: inline-block; margin-left: 5px; vertical-align: -2px; color: var(--ink); }
.verified.mini .px { width: 16px; height: 16px; }

/* admin.<home>: the dashboard's window, wider, with Windows 95 tabs over a panel. Pages and names are tables that
   scroll sideways when narrow, with the one picked beside them. */
.kg.adm-win { width: min(100%, 90rem); }
.adm-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 6px; }
.adm-nav { display: flex; gap: 6px; padding-bottom: 6px; }
.tabs { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 2px; padding: 0 3px; }
.tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 2rem;
  padding: 2px 14px;
  background: var(--face);
  color: var(--ink);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: .04em;
  border: 2px solid;
  border-bottom: 0;
  border-color: var(--hi) var(--lo) transparent var(--hi);
  box-shadow: inset -1px 0 0 var(--shade), inset 1px 1px 0 var(--mid);
}
/* The open tab stands taller and runs into its panel */
.tab[aria-current="page"] { min-height: 2.4rem; margin: 0 -2px -3px; padding-bottom: 5px; z-index: 2; }
.tab:focus-visible { outline: 1px dotted var(--ink); outline-offset: -5px; }
.tab-panel {
  position: relative;
  z-index: 1;
  padding: .8rem;
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  box-shadow: inset -1px -1px 0 var(--shade), inset 1px 1px 0 var(--mid);
}

.adm-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 6px; }
.adm-search { display: flex; flex-wrap: wrap; gap: 6px; flex: 1 1 22rem; min-width: 0; margin: 0; }
.adm-search > .well, .adm-search > .name-well { flex: 1 1 14rem; width: auto; min-width: 0; }
.adm-search > select.well { flex: 0 1 auto; }
.adm-filters { display: flex; flex-wrap: wrap; gap: 4px; }
/* A filter that is on is pressed in, checkered, like a Windows 95 toggle */
.kbtn[aria-current] {
  border-color: var(--lo) var(--hi) var(--hi) var(--lo);
  box-shadow: inset 1px 1px 0 var(--shade);
  background: repeating-conic-gradient(var(--hi) 0 25%, var(--face) 0 50%) 0 0 / 2px 2px;
}
.cnt { color: var(--dim); }
.tab-panel > .lcd { margin: 0 0 .8rem; }
.adm-bar .ed-save .lcd { margin: 0; }

.adm-cols { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .9rem; }
.adm-main { flex: 999 1 34rem; min-width: 0; }
.adm-side, .adm-three > .adm-col { flex: 1 1 20rem; min-width: 0; display: flex; flex-direction: column; gap: .9rem; }
.adm-three > .adm-col { flex-basis: 17rem; }
.adm-three > .adm-wide { flex: 999 1 30rem; }
.adm-side > .group, .adm-col > .group, .adm-main > .group { margin: 0; }
.adm-main > .group { margin-top: .9rem; }
.group label small, .adm-two label small { color: var(--dim); font-size: 1.0625rem; }

.adm-table-box {
  overflow-x: auto;
  background: var(--well);
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
  box-shadow: inset 1px 1px 0 var(--lo);
}
.adm-table { width: 100%; min-width: 46rem; border-collapse: collapse; }
.adm-log { min-width: 58rem; }
.adm-table th {
  padding: 1px 8px;
  background: var(--face);
  font-weight: 400;
  text-align: left;
  white-space: nowrap;
  border: 2px solid;
  border-color: var(--hi) var(--lo) var(--lo) var(--hi);
  box-shadow: inset -1px -1px 0 var(--shade);
}
.adm-table td { padding: 4px 8px; border-bottom: 1px solid var(--mid); vertical-align: middle; }
.adm-table td small { display: block; color: var(--dim); font-size: 1.0625rem; }
.adm-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.adm-table .act { width: 1%; text-align: right; white-space: nowrap; }
.adm-table .dim, .adm-table .sub { color: var(--dim); }
.adm-name { white-space: nowrap; }
/* A whole row is the link to its page */
.adm-table tbody tr { position: relative; }
.adm-row { text-decoration: none; font-size: 1.375rem; }
.adm-row::after { content: ""; position: absolute; inset: 0; }
.adm-row:focus-visible { outline: none; }
.adm-table tr:has(.adm-row:focus-visible) { outline: 1px dotted var(--ink); outline-offset: -3px; }
.adm-table tbody tr:has(.adm-row):hover { background: var(--mid); }
.adm-table tr.sel, .adm-table tr.sel:hover { background: var(--sel); color: var(--sel-ink); }
.adm-table tr.sel .dim, .adm-table tr.sel .sub { color: var(--panel-mid); }
.adm-table tr.sel .tag { background: var(--sel-ink); color: var(--sel); }
.adm-table tr.off .adm-row { text-decoration: line-through; }
.adm-empty { margin: 0; padding: 1rem 8px; color: var(--dim); }
.adm-pager { display: flex; gap: 6px; margin-top: 6px; }
.adm-foot { margin: .6rem 0 0; }

/* The page picked: its top as its visitors see it (.adm-pv-page), its address, then what it has and what may be done
   to it */
.adm-addr { margin: -.4rem 0 0; }
.facts { display: grid; grid-template-columns: 9ch minmax(0, 1fr); gap: 4px 1ch; margin: 0; }
.facts dt { color: var(--dim); }
.facts dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.adm-mail .kbtn { margin-left: .5ch; }
.held, .holders, .hist { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 5px; }
.held li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: center; }
.holders li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.holders li .kbtn { margin-left: auto; }
.hist time { display: block; color: var(--dim); font-size: 1.0625rem; }
.adm-sub { margin: .7rem 0 .3rem; color: var(--dim); }
.grant { display: flex; flex-wrap: wrap; gap: 5px; }
.kbtn.grant-btn { gap: 6px; padding-left: 3px; text-transform: none; letter-spacing: 0; }
.adm-acts { display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); gap: 6px; margin-top: .6rem; }
.adm-more { margin: .5rem 0 0; }
.adm-confirm { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; }

/* Badges in their order, the picked one pressed in black */
.rank { margin: .3rem 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; }
.rank-row { display: flex; align-items: center; gap: 6px; padding: 3px 4px; }
.rank-row.sel { background: var(--sel); color: var(--sel-ink); }
.rank-pick { flex: 1 1 auto; display: flex; align-items: center; gap: 8px; min-width: 0; color: inherit; text-decoration: none; }
.rank-pick:focus-visible { outline: 1px dotted currentColor; outline-offset: 2px; }
.rank-n { flex: none; width: 2ch; text-align: right; color: var(--dim); }
.rank-text { display: flex; flex-direction: column; min-width: 0; font-size: 1.375rem; line-height: 1.05; }
.rank-text small { font-size: 1.0625rem; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rank-row.sel .rank-n, .rank-row.sel small, .rank-row.sel .lock { color: var(--panel-mid); }
.lock { flex: none; font-size: 1.0625rem; color: var(--dim); padding-right: 4px; }
.adm-two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); gap: 10px; }
.adm-two label { display: block; margin: 0 0 .2rem; color: var(--dim); }

/* The picture, cell by cell: a click turns one on or off, a drag paints */
.pix-wrap { display: flex; flex-wrap: wrap; gap: 1rem; margin: .8rem 0 .5rem; }
.pix {
  display: grid;
  grid-template-columns: repeat(16, minmax(0, 1fr));
  width: min(100%, 20rem);
  aspect-ratio: 1;
  touch-action: none;
  background: var(--well);
  border: 2px solid;
  border-color: var(--shade) var(--hi) var(--hi) var(--shade);
  box-shadow: inset 1px 1px 0 var(--lo);
}
.cell { display: block; min-width: 0; padding: 0; border: 0; background: var(--well); box-shadow: inset -1px -1px 0 var(--mid); cursor: crosshair; }
.cell[aria-pressed="true"] { background: var(--ink); box-shadow: inset -1px -1px 0 var(--dim); }
.cell:disabled { cursor: default; }
.cell:focus-visible { outline: 2px solid var(--shade); outline-offset: -2px; }
.pix-side { flex: 1 1 13rem; display: flex; flex-direction: column; gap: .8rem; min-width: 0; }
.pix-side .adm-sub, .pix-side .note { margin: 0; }
.prev { display: flex; align-items: flex-end; gap: 1rem; }
.prev figure { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.prev figcaption { font-size: 1.0625rem; color: var(--dim); }
.tools { display: flex; flex-wrap: wrap; gap: 6px; }
.adm-tiles, .adm-until { margin: 0; padding: 0; border: 0; min-width: 0; }
.group .adm-tiles legend, .group .adm-until legend { padding: 0; margin-bottom: .2rem; color: var(--dim); text-transform: none; letter-spacing: 0; }
.check.radio span::before { border-radius: 50%; }
.check.radio input:checked + span::before { box-shadow: inset 1px 1px 0 var(--lo), inset 0 0 0 4px var(--well), inset 0 0 0 8px var(--ink); }

/* The badge as a page shows it: the page's own window down to its banner, in the page's theme, the same width as on
   the page; under it, what the pointer over the badge would say */
.adm-pv-page { padding: .3rem 0 .2rem; }
.adm-pv-page > .kg { margin: 0 auto; }
.adm-pv-page .kg-body { display: none; }
.tip { display: inline-block; max-width: 100%; margin: .9rem 0 0; padding: 2px 8px; background: var(--well); color: var(--ink); border: 1px solid var(--ink); box-shadow: 2px 2px 0 var(--shade); }
.tip-name { text-transform: uppercase; letter-spacing: .04em; }
.adm-unshown { margin: .9rem 0 0; color: var(--dim); }
.perk { display: grid; grid-template-columns: 10ch 7ch minmax(0, 1fr); gap: 8px; align-items: center; margin-top: .4rem; }
.perk .well { text-align: right; }
.perk small { color: var(--dim); font-size: 1.0625rem; }
.group .adm-after { margin: .5rem 0 0; }
.give { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; margin-top: .6rem; }
.adm-danger { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.adm-danger .note { margin: 0; }

/* Names held, and the form to hold one */
.adm-system { margin: 0; font-size: 1.0625rem; white-space: normal; overflow-wrap: anywhere; }
#hold-form > label { display: block; margin: .6rem 0 .2rem; color: var(--dim); }
#hold-form > label:first-child { margin-top: 0; }
#hold-form .lcd { margin: .4rem 0 0; }
.adm-until { margin-top: .6rem; }
.date-row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; align-items: center; }

.actor { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.adm-log td:first-child { white-space: nowrap; }

@media (max-width: 47.99rem) {
  .adm-head { flex-direction: column-reverse; align-items: stretch; }
  .adm-nav { justify-content: flex-end; }
  .tab { padding: 2px 9px; }
  .tab-panel { padding: .6rem; }
  .adm-two, .give, .adm-confirm, .date-row { grid-template-columns: minmax(0, 1fr); }
  .perk { grid-template-columns: 10ch 7ch; }
  .perk small { grid-column: 1 / -1; }
}

/* Fieldsets are as wide as their widest line unless told otherwise: in a column they give way like anything else */
.adm-cols fieldset { min-width: 0; }
.adm-search select { font: inherit; font-size: 1.375rem; }
.kbtn .cnt { margin-left: .6ch; }
.adm-three > .adm-col:first-child { flex-basis: 21rem; }
.rank-text { overflow: hidden; }
.rank-text > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The editor: the ready-made pictures, the grid and its tools for a picture, the field for letters */
.pix-wrap[data-face="text"] .presets, .pix-wrap[data-face="text"] .pix, .pix-wrap[data-face="text"] .tools, .pix-wrap[data-face="text"] .pix-note, .pix-wrap[data-face="icon"] .adm-label { display: none; }
.presets { flex: 1 1 100%; min-width: 0; }
.presets .adm-sub { margin: 0 0 .4rem; }
.preset-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); gap: 4px; }
.kbtn.preset { display: grid; place-items: center; min-width: 0; height: 44px; padding: 0; }
/* Whether the page picked on the Pages tab is verified, and the switch */
.adm-verified { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 0 0 .6rem; }
.adm-verified .verified.mini { margin-left: 0; }
.adm-verified .kbtn { margin-left: auto; }
.adm-face { display: flex; flex-wrap: wrap; gap: 0 1rem; margin: 0; padding: 0; border: 0; min-width: 0; }
.group .adm-face legend { padding: 0; margin-bottom: .2rem; color: var(--dim); text-transform: none; letter-spacing: 0; }
.adm-label label { display: block; margin: 0 0 .2rem; color: var(--dim); }
.adm-label .well { width: 9ch; }

/* A new password, under the button that made it, with a way to copy it */
.adm-pw { margin-top: .8rem; }
.adm-pw .label { display: block; margin: 0 0 .2rem; color: var(--dim); }
.adm-pw .code { user-select: all; overflow-wrap: anywhere; }
.group .adm-pw .note { margin: .4rem 0 0; }
#adm-pw-said:empty { display: none; }
