/* rainydays has two themes. Night (the default) is the RainyLofi night palette set for a dense work app: the
   ground carries the portfolio's cyan and blue haze and a faint still rain; the sidebar, toolbar and popovers
   are glass over it. Overcast (light) is the same app on a grey day: a pale slate sky with a bank of cloud along
   the top and slate rain, frosted white glass, and inks dark enough to read on white. js/theme.js sets
   html[data-theme] before anything paints. In both, tables stay solid so pinned columns can cover what scrolls
   under them, and label colours are soft tinted pills (each passes 6.5:1), never solid blocks, and never glow. */
/* Space Grotesk and JetBrains Mono, served from fonts/ (SIL Open Font License, see the OFL files there) so
   no page asks a third party for anything. Each family is one variable font per alphabet; a browser downloads only
   the alphabets a page uses. */
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/jetbrains-mono-cyrillic-ext.woff2") format("woff2"); unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/jetbrains-mono-cyrillic.woff2") format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/jetbrains-mono-greek.woff2") format("woff2"); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/jetbrains-mono-vietnamese.woff2") format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/jetbrains-mono-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/space-grotesk-vietnamese.woff2") format("woff2"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/space-grotesk-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("../fonts/space-grotesk-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

:root {
  --bg: #050b12;
  --sky:
    radial-gradient(1100px 700px at 88% -14%, rgba(8, 145, 178, 0.2), transparent 62%),
    radial-gradient(900px 640px at 12% 112%, rgba(37, 99, 235, 0.12), transparent 60%),
    radial-gradient(760px 560px at -6% 28%, rgba(56, 189, 248, 0.07), transparent 60%),
    #050b12;
  --raised: #0c1925;
  --raised-2: #112333;
  --deep: #0a1620;
  --sheet-top: #0e1d2b;
  --th: #0f1e2c;
  --sub: #0a1520;
  --sub-hover: #0f1f2e;
  --kcard: linear-gradient(180deg, #142739, #102131);
  --pop: rgba(13, 27, 40, 0.94);
  --panel: linear-gradient(180deg, rgba(17, 34, 49, 0.74), rgba(11, 23, 35, 0.66));
  --panel-ring: #0f1f2d;
  --pop-ring: #0d1b28;
  --side-ring: #08121b;
  --lane-ring: #132536;
  --glass-side: rgba(5, 12, 20, 0.58);
  --glass-bar: rgba(5, 11, 18, 0.62);
  --glass-top: rgba(5, 12, 20, 0.6);
  --side-solid: rgba(7, 15, 24, 0.94);
  --auth-panel: rgba(7, 16, 24, 0.86);
  --scrim: rgba(2, 6, 10, 0.6);
  --scrim-soft: rgba(2, 6, 10, 0.42);
  --well: rgba(10, 22, 32, 0.4);
  --well-2: rgba(10, 22, 32, 0.5);
  --row-hover: rgba(17, 35, 51, 0.7);
  --line: rgba(52, 224, 234, 0.16);
  --line-soft: rgba(52, 224, 234, 0.08);
  /* an input's resting edge: slate rather than cyan (the glow is for focus), and 3:1 or better on panels */
  --edge-input: rgba(127, 154, 166, 0.65);
  /* tints are written as rgba(var(--x-rgb), alpha) so one alpha works on either ground: --fg-rgb is the colour
     hover washes are made of (white at night, slate by day), --glow-rgb the accent tint, --sel-rgb selection */
  --fg-rgb: 255, 255, 255;
  --glow-rgb: 52, 224, 234;
  --sel-rgb: 8, 145, 178;
  --bad-rgb: 248, 113, 113;
  --dim-rgb: 127, 154, 166;
  --shade-rgb: 0, 0, 0;
  --shade-k: 1;
  --text: #e2eef3;
  --mist: #b3c7d0;
  --dim: #7f9aa6;
  --white: #ffffff;
  --on: #ffffff;
  --accent: #34e0ea;
  --accent-d: #0891b2;
  --btn: #0e7490;
  --blue: #60a5fa;
  --royal: #2563eb;
  --mint: #86efac;
  --bad: #fca5a5;
  --late: #f87171;
  --danger: #b91c1c;
  --danger-hover: #c62828;
  --danger-ink: #fecaca;
  --bad-wash: rgba(185, 28, 28, 0.14);
  --av-none: #334155;
  --mono: "JetBrains Mono", ui-monospace, Consolas, monospace;
  --sans: "Space Grotesk", system-ui, sans-serif;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  color-scheme: dark;
}

/* overcast: --white stays the name of the strongest text, which by day is near black; --on is text on a fill */
:root[data-theme="light"] {
  --bg: #e3e9ee;
  --sky:
    radial-gradient(1200px 520px at 50% -8%, rgba(255, 255, 255, 0.7), transparent 70%),
    radial-gradient(900px 640px at 100% 110%, rgba(8, 145, 178, 0.08), transparent 60%),
    linear-gradient(180deg, #cdd8e0 0%, #dfe6ec 38%, #e7ecf0 100%);
  --raised: #fbfcfd;
  --raised-2: #eef4f8;
  --deep: #f4f7f9;
  --sheet-top: #ffffff;
  --th: #f1f5f8;
  --sub: #f5f8fa;
  --sub-hover: #ebf1f5;
  --kcard: linear-gradient(180deg, #ffffff, #f6f9fb);
  --pop: rgba(250, 252, 253, 0.95);
  --panel: linear-gradient(180deg, rgba(255, 255, 255, 0.84), rgba(249, 251, 253, 0.74));
  --panel-ring: #fafcfd;
  --pop-ring: #fafcfd;
  --side-ring: #eef3f6;
  --lane-ring: #f6f9fb;
  --glass-side: rgba(244, 248, 251, 0.62);
  --glass-bar: rgba(238, 243, 247, 0.7);
  --glass-top: rgba(238, 243, 247, 0.72);
  --side-solid: rgba(244, 248, 251, 0.97);
  --auth-panel: rgba(250, 252, 253, 0.86);
  --scrim: rgba(24, 42, 56, 0.3);
  --scrim-soft: rgba(24, 42, 56, 0.2);
  --well: rgba(255, 255, 255, 0.5);
  --well-2: rgba(255, 255, 255, 0.6);
  --row-hover: rgba(14, 116, 144, 0.06);
  --line: rgba(30, 72, 96, 0.2);
  --line-soft: rgba(30, 72, 96, 0.11);
  --edge-input: rgba(30, 72, 96, 0.65);
  --fg-rgb: 22, 52, 70;
  --glow-rgb: 14, 116, 144;
  --sel-rgb: 8, 145, 178;
  --bad-rgb: 220, 38, 38;
  --dim-rgb: 84, 104, 115;
  --shade-rgb: 34, 62, 82;
  --shade-k: 0.32;
  --text: #16232b;
  --mist: #394c56;
  --dim: #4b5f69;
  --white: #081117;
  --accent: #0c6a84;
  --accent-d: #0891b2;
  --btn: #0e7490;
  --blue: #1d4ed8;
  --royal: #2563eb;
  --mint: #136c35;
  --bad: #b91c1c;
  --late: #c81e1e;
  --danger-hover: #991b1b;
  --danger-ink: #991b1b;
  --bad-wash: rgba(220, 38, 38, 0.08);
  --av-none: #64748b;
  color-scheme: light;
}

/* label and group colours: --fill is the hue (swatches, battery bars), --ink reads on the ground, and a
   label shows as a pill: --pill (the fill at 40% over the table surface, 50% on hover) under --pill-ink (the
   ink lifted 40% toward white). By day the pill is the fill at 14% (20% on hover) over white under the fill
   taken 38% toward black, and --ink is the fill 20% toward black (4.8:1 or better even on the sky's darkest top).
   Every pill pair is 6.5:1 or better in both themes, hover included. */
.c-cyan { --fill: #0e7490; --ink: #34e0ea; }
.c-blue { --fill: #1d4ed8; --ink: #60a5fa; }
.c-mint { --fill: #0f766e; --ink: #5eead4; }
.c-green { --fill: #15803d; --ink: #4ade80; }
.c-amber { --fill: #b45309; --ink: #fbbf24; }
.c-orange { --fill: #c2410c; --ink: #fb923c; }
.c-red { --fill: #b91c1c; --ink: #f87171; }
.c-pink { --fill: #be185d; --ink: #f472b6; }
.c-violet { --fill: #6d28d9; --ink: #a78bfa; }
.c-slate { --fill: #475569; --ink: #94a3b8; }
.c-cyan, .c-blue, .c-mint, .c-green, .c-amber, .c-orange, .c-red, .c-pink, .c-violet, .c-slate {
  --pill: color-mix(in srgb, var(--fill) 40%, #0c1925);
  --pill-hover: color-mix(in srgb, var(--fill) 50%, #0c1925);
  --pill-ink: color-mix(in srgb, var(--ink) 60%, #ffffff);
  --pill-edge: color-mix(in srgb, var(--ink) 22%, transparent);
}
[data-theme="light"] :is(.c-cyan, .c-blue, .c-mint, .c-green, .c-amber, .c-orange, .c-red, .c-pink, .c-violet, .c-slate) {
  --ink: color-mix(in srgb, var(--fill) 80%, #000000);
  --pill: color-mix(in srgb, var(--fill) 14%, #ffffff);
  --pill-hover: color-mix(in srgb, var(--fill) 20%, #ffffff);
  --pill-ink: color-mix(in srgb, var(--fill) 62%, #000000);
  --pill-edge: color-mix(in srgb, var(--fill) 30%, transparent);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--sky);
  color: var(--text); font-family: var(--sans); font-size: 14px; line-height: 1.5;
  -webkit-font-smoothing: antialiased; caret-color: var(--accent);
}
a { color: var(--blue); text-decoration: none; text-underline-offset: 3px; }
a:hover { color: var(--white); }
button { font: inherit; color: inherit; }
img { display: block; max-width: 100%; }
h1, h2, h3 { margin: 0; color: var(--white); line-height: 1.2; text-wrap: balance; }
p { margin: 0; }
[hidden] { display: none !important; }
::selection { background: var(--accent-d); color: var(--on); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
* { scrollbar-width: thin; scrollbar-color: rgba(var(--glow-rgb), 0.2) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: rgba(var(--glow-rgb), 0.18); border-radius: 10px; border: 3px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: rgba(var(--glow-rgb), 0.32); }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }

.dim { color: var(--dim); }
.mist { color: var(--mist); }
.small { font-size: 13px; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.ic { flex: none; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.stack { display: grid; gap: 16px; }
.row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.row-end { display: flex; justify-content: flex-end; align-items: center; gap: 10px; flex-wrap: wrap; }
.row-between { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 8px 14px; border-radius: 8px; border: 1px solid transparent;
  font-size: 14px; font-weight: 500; line-height: 1.3; cursor: pointer; white-space: nowrap;
  transition: transform 0.2s var(--ease), box-shadow 0.2s, border-color 0.2s, background 0.2s, color 0.2s;
}
.btn.primary { background: linear-gradient(135deg, var(--btn), var(--royal)); color: var(--on); }
.btn.primary:hover { transform: translateY(-1px); box-shadow: 0 10px 30px rgba(var(--sel-rgb), 0.4); color: var(--on); }
.btn.ghost { background: rgba(var(--fg-rgb), 0.03); border-color: var(--line); color: var(--text); }
.btn.ghost:hover { border-color: var(--blue); color: var(--white); }
/* an action done here, beside ghost links that leave for another site (a game's Refresh beside Roblox) */
.btn.tint { background: rgba(var(--sel-rgb), 0.14); border-color: rgba(var(--glow-rgb), 0.45); color: var(--white); }
.btn.tint:hover { background: rgba(var(--sel-rgb), 0.24); border-color: var(--accent); }
.btn.tint .ic { color: var(--accent); }
.btn.danger { background: var(--danger); color: var(--on); }
.btn.danger:hover { background: var(--danger-hover); }
.btn.danger-ghost { background: transparent; border-color: rgba(var(--bad-rgb), 0.35); color: var(--bad); }
.btn.danger-ghost:hover { border-color: var(--late); color: var(--danger-ink); }
.btn.small { padding: 5px 10px; font-size: 13px; border-radius: 7px; }
.btn.wide { width: 100%; }
.btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; box-shadow: none; }
.btn.busy { cursor: progress; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 30px; height: 30px; padding: 0; border: 0; border-radius: 7px; background: transparent;
  color: var(--mist); cursor: pointer; transition: background 0.15s, color 0.15s;
}
.icon-btn:hover { background: rgba(var(--fg-rgb), 0.07); color: var(--white); }
.small-link { background: none; border: 0; padding: 0; color: var(--blue); cursor: pointer; font-size: 13px; }
.small-link:hover { color: var(--white); text-decoration: underline; }
/* in a popover a small link stands alone, so it gets the full 24px target */
.pop .small-link { min-height: 24px; }

/* ---------- forms ---------- */
.field { display: grid; gap: 6px; position: relative; }
.label { font-size: 13px; font-weight: 500; color: var(--mist); }
.hint { font-size: 12px; color: var(--dim); }
.err { font-size: 12.5px; color: var(--bad); }
/* (an empty error stays in the page, out of sight, so the words put in it later are read out) */
.err:empty { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.input {
  width: 100%; padding: 9px 12px; border-radius: 8px; border: 1px solid var(--edge-input);
  background: rgba(var(--fg-rgb), 0.03); color: var(--text); font: inherit; font-size: 14px;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.input::placeholder { color: var(--dim); opacity: 1; }
.input:hover { border-color: rgba(var(--glow-rgb), 0.5); }
/* (the outline is clear, but forced colours, which drop the ring, paint it in) */
.input:focus { outline: 2px solid transparent; outline-offset: 0; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: rgba(var(--fg-rgb), 0.05); }
textarea.input { resize: vertical; min-height: 84px; line-height: 1.5; }
select.input { appearance: none; padding-right: 32px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--mist) 50%), linear-gradient(135deg, var(--mist) 50%, transparent 50%);
  background-position: calc(100% - 17px) 55%, calc(100% - 12px) 55%; background-size: 5px 5px; background-repeat: no-repeat; }
select.input option { background: var(--pop); color: var(--text); }
.field.bad .input { border-color: var(--late); }
.has-eye .input { padding-right: 40px; }
.input-eye { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 30px; height: 30px; border: 0; border-radius: 6px; background: none; color: var(--dim); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.input-eye:hover { color: var(--white); }
.form-err { padding: 10px 12px; border-radius: 8px; background: var(--bad-wash); border: 1px solid rgba(var(--bad-rgb), 0.3); color: var(--danger-ink); font-size: 13.5px; }
.check { display: inline-flex; align-items: center; gap: 8px; min-height: 24px; cursor: pointer; font-size: 14px; color: var(--mist); }
.check input { accent-color: var(--accent-d); width: 16px; height: 16px; }

/* ---------- avatars and status ---------- */
.av {
  --s: 28px; position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: var(--s); height: var(--s); border-radius: 50%; background: var(--fill, var(--av-none)); color: var(--on);
  font-size: calc(var(--s) * 0.38); font-weight: 600; letter-spacing: 0.01em; user-select: none;
}
.av img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.av-empty { background: transparent; color: var(--dim); border: 1px dashed rgba(var(--dim-rgb), 0.5); }
.av-cyan { --fill: #0e7490; } .av-blue { --fill: #1d4ed8; } .av-mint { --fill: #0f766e; } .av-green { --fill: #15803d; } .av-amber { --fill: #b45309; }
.av-orange { --fill: #c2410c; } .av-red { --fill: #b91c1c; } .av-pink { --fill: #be185d; } .av-violet { --fill: #6d28d9; } .av-slate { --fill: #475569; }
.av-dot {
  position: absolute; right: -1px; bottom: -1px; width: max(8px, calc(var(--s) * 0.3)); height: max(8px, calc(var(--s) * 0.3));
  border-radius: 50%; background: var(--ink); box-shadow: 0 0 0 2px var(--ring, var(--bg));
}
.avs { display: inline-flex; align-items: center; }
.avs .av { box-shadow: 0 0 0 2px var(--ring, var(--bg)); }
.avs .av + .av { margin-left: -7px; }
.avs-more { margin-left: 4px; font-family: var(--mono); font-size: 12px; color: var(--dim); }
/* online status: a mint ring when a tab of theirs is in use, a faint one while one is open in the background, none
   when they're offline (or don't show it); the gap ring stays, so it reads in a stack of avatars too */
.av.p-on { box-shadow: 0 0 0 2px var(--ring, var(--bg)), 0 0 0 4px var(--mint); }
.av.p-open { box-shadow: 0 0 0 2px var(--ring, var(--bg)), 0 0 0 3.5px color-mix(in srgb, var(--mint) 45%, transparent); }
.presence { font-family: var(--mono); font-size: 12px; }
.presence.active { color: var(--mint); }
.presence.open { color: var(--mist); }
.presence.off { color: var(--dim); }
.wchip { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; color: var(--ink); font-size: 13px; font-weight: 500; white-space: nowrap; }
.wchip.none { color: var(--dim); font-weight: 400; }
.wchip-note { color: var(--mist); font-weight: 400; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.wchip-note::before { content: "\00b7"; margin-right: 6px; color: var(--dim); }
.tdot { display: inline-block; flex: none; width: 9px; height: 9px; border-radius: 3px; background: var(--ink); }
/* a team's icon, or its dot centred in the same space (core.js teamMark) */
.tmark { display: inline-grid; place-items: center; flex: none; width: var(--s, 16px); height: var(--s, 16px); }
.tmark img { display: block; width: 100%; height: 100%; border-radius: calc(var(--s, 16px) * 0.28); object-fit: cover; }
.badge {
  display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 18px; padding: 0 6px;
  border-radius: 999px; background: var(--btn); color: var(--on); font-family: var(--mono); font-size: 11.5px; font-weight: 500;
}
.role { font-family: var(--mono); font-size: 12px; color: var(--mist); text-transform: lowercase; }
.role-owner { color: var(--accent); }
.role-creator { display: inline-flex; align-items: center; gap: 4px; color: var(--accent); }
.role-creator .ic { flex: none; }
.role-admin { color: var(--blue); }
.role-guest { color: var(--mint); }

/* ---------- popovers, menus, dialogs, toasts ---------- */
.pop {
  position: fixed; z-index: 1000; min-width: 200px; max-width: calc(100vw - 16px); max-height: min(70vh, 520px); overflow: auto;
  padding: 6px; border-radius: 12px; background: var(--pop); border: 1px solid var(--line); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 20px 50px rgba(var(--shade-rgb), calc(0.5 * var(--shade-k))); animation: pop-in 0.16s var(--ease); --ring: var(--pop-ring);
}
@keyframes pop-in { from { opacity: 0; transform: translateY(-4px) scale(0.98); } }
.menu-item {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 10px; border: 0; border-radius: 7px;
  background: none; color: var(--text); font-size: 14px; text-align: left; cursor: pointer;
}
.menu-item .ic { color: var(--mist); }
.menu-item:hover, .menu-item:focus-visible { background: rgba(var(--glow-rgb), 0.09); outline: none; color: var(--white); }
.menu-item:focus-visible { box-shadow: inset 0 0 0 2px var(--accent); }
.menu-item:disabled { opacity: 0.45; cursor: default; background: none; }
.menu-item.danger, .menu-item.danger .ic { color: var(--bad); }
.menu-ic { width: 15px; flex: none; }
.menu-hint { margin-left: auto; font-family: var(--mono); font-size: 12px; color: var(--dim); }
.menu-head { padding: 8px 10px 4px; font-family: var(--mono); font-size: 12px; color: var(--dim); }
.menu-sep { border: 0; border-top: 1px solid var(--line-soft); margin: 5px 4px; }

.dlg {
  width: min(480px, calc(100vw - 24px)); max-height: calc(100dvh - 40px); padding: 0; border-radius: 14px;
  border: 1px solid var(--line); background: linear-gradient(180deg, var(--sheet-top), var(--deep) 180px); color: var(--text);
  box-shadow: 0 30px 60px rgba(var(--shade-rgb), calc(0.55 * var(--shade-k)));
}
.dlg.wide { width: min(640px, calc(100vw - 24px)); }
.dlg::backdrop { background: rgba(2, 6, 10, 0.66); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.dlg[open] { animation: pop-in 0.2s var(--ease); }
.dlg-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 18px 0 22px; }
.dlg-head h2 { font-size: 18px; }
.dlg-body { padding: 16px 22px 22px; }
.dlg-text { color: var(--mist); }

.toasts { position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%); z-index: 2000; display: grid; gap: 8px; justify-items: center; pointer-events: none; }
.toast {
  display: flex; align-items: center; gap: 9px; padding: 10px 14px; border-radius: 10px; max-width: min(520px, calc(100vw - 32px));
  background: var(--pop); border: 1px solid var(--line); box-shadow: 0 14px 40px rgba(var(--shade-rgb), calc(0.5 * var(--shade-k))); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  font-size: 14px; animation: toast-in 0.3s var(--ease); transition: opacity 0.3s, transform 0.3s;
}
.toast .ic { color: var(--mint); }
.toast.error { border-color: rgba(var(--bad-rgb), 0.4); }
.toast.error .ic { color: var(--late); }
.toast.out { opacity: 0; transform: translateY(6px); }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px); } }

/* ---------- brand ---------- */
.brand { display: inline-flex; align-items: center; gap: 8px; font-family: var(--mono); font-weight: 700; font-size: 16px; color: var(--white); letter-spacing: -0.01em; }
.brand:hover { color: var(--white); }

/* ---------- app shell ---------- */
/* a still tile of faint rain (drawn once by rain.js) over the haze, behind everything */
body.in-app::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image: var(--rain, none); background-size: 320px 320px;
}
/* by day the still rain falls from a bank of cloud along the top (both drawn once by rain.js) */
[data-theme="light"] body.in-app::before {
  background-image: var(--rain-light, none), var(--clouds, none);
  background-size: 320px 320px, 1600px 420px; background-repeat: repeat, repeat-x; background-position: 0 0, 50% 0;
}
[data-theme="light"] .dlg::backdrop { background: rgba(24, 42, 56, 0.32); }
.app { display: grid; grid-template-columns: 264px minmax(0, 1fr); height: 100dvh; }
.side {
  display: flex; flex-direction: column; gap: 6px; min-height: 0; padding: 14px 10px 10px;
  background: var(--glass-side); -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); border-right: 1px solid var(--line-soft); --ring: var(--side-ring);
}
.side-brand { padding: 4px 10px 12px; }
.side-nav { display: grid; gap: 2px; }
.side-link {
  position: relative; isolation: isolate; display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 8px;
  color: var(--mist); font-size: 14px; font-weight: 500; transition: background 0.15s, color 0.15s;
}
.side-link .ic { color: var(--dim); transition: color 0.15s; }
.side-link .badge { margin-left: auto; }
.side-link:hover { background: rgba(var(--fg-rgb), 0.04); color: var(--white); }
.side-link[aria-current="page"] { color: var(--white); }
.side-link[aria-current="page"] .ic { color: var(--accent); }
.side-scroll { flex: 1; min-height: 0; overflow-y: auto; margin: 8px -4px 0; padding: 0 4px 12px; border-top: 1px solid var(--line-soft); }
.side-label { display: flex; align-items: center; justify-content: space-between; padding: 16px 4px 2px 10px; font-family: var(--mono); font-size: 12px; color: var(--dim); }
.side-sec { margin-top: 8px; }
.side-head { display: flex; align-items: center; gap: 2px; padding-right: 2px; }
.side-toggle { width: 24px; height: 26px; border: 0; background: none; color: var(--dim); cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: 5px; flex: none; }
.side-toggle:hover { color: var(--white); }
.side-toggle .ic { transition: transform 0.2s var(--ease); }
.side-toggle.shut .ic { transform: rotate(-90deg); }
.side-title { position: relative; isolation: isolate; flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 4px 6px; border-radius: 6px; color: var(--text); font-size: 13.5px; font-weight: 600; }
/* (the name: the span that isn't the highlight, the team's mark or a guest's tag) */
.side-title > span:not(.side-ink):not(.tmark):not(.side-tag) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
a.side-title:hover { background: rgba(var(--fg-rgb), 0.04); color: var(--white); }
a.side-title[aria-current="page"] { color: var(--white); }
/* a team someone is only a guest of: a quiet tag after its name (which still takes the room first) */
.side-title span.side-tag { flex: none; margin-left: auto; font-family: var(--mono); font-size: 11px; font-weight: 500; color: var(--mint); text-transform: lowercase; }
.side-title span.side-tag.soon { color: var(--warn); }
.side-add { width: 26px; height: 26px; opacity: 0.7; }
.side-head:hover .side-add, .side-label:hover .side-add, .side-add:focus-visible { opacity: 1; }
.side-list { display: grid; gap: 1px; padding: 2px 0 2px 14px; }
.side-board {
  position: relative; isolation: isolate; display: flex; align-items: center; gap: 9px; padding: 6px 10px; border-radius: 7px; color: var(--mist); font-size: 13.5px;
  transition: background 0.15s, color 0.15s;
}
.side-board span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-board .ic { color: var(--dim); }
.side-board:hover { background: rgba(var(--fg-rgb), 0.04); color: var(--white); }
.side-board[aria-current="page"] { color: var(--white); }
/* the current page's highlight, a layer of its own under the link, so it can glide to the next one (js/core.js) */
.side-ink { position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: rgba(var(--sel-rgb), 0.16); pointer-events: none; view-transition-name: side-ink; }
.side-board[aria-current="page"] .ic { color: var(--accent); }
.side-empty { padding: 4px 10px 6px; font-size: 13px; color: var(--dim); }
.side-group { display: grid; gap: 1px; }
.side-group + .side-group { margin-top: 6px; }
.side-sub-row { display: flex; align-items: center; justify-content: space-between; min-height: 24px; padding-right: 2px; }
.side-sub { padding: 4px 10px 2px; font-family: var(--mono); font-size: 11px; color: var(--dim); }
/* a team's Games and Boards headings each have a small + (for a role that can add one): shown while the pointer's
   over the team, or on a touch screen always. (The team's name has no + of its own: these are what it would add.) */
.side-sub-add { width: 22px; height: 22px; border-radius: 6px; color: var(--dim); opacity: 0; transition: opacity 0.15s, background 0.15s, color 0.15s; }
.side-sec:hover .side-sub-add, .side-sub-add:focus-visible { opacity: 1; }
@media (hover: none) { .side-sub-add { opacity: 0.75; } }
/* a board or game being dragged to its place in your own order: lifted off the list, the rest making way */
.side-items { display: grid; gap: 1px; }
.side-items > a { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.side-items > a.dragging {
  z-index: 2; background: var(--panel-hi, rgba(var(--fg-rgb), 0.09)); color: var(--white); cursor: grabbing;
  box-shadow: 0 0 0 1px var(--line), 0 8px 22px rgba(var(--shade-rgb), calc(0.45 * var(--shade-k)));
}
body.side-dragging, body.side-dragging * { cursor: grabbing !important; }
.side-cta { display: flex; align-items: center; gap: 9px; width: 100%; margin-top: 6px; padding: 9px 10px; border-radius: 8px; border: 1px dashed var(--line); background: none; color: var(--mist); cursor: pointer; font-size: 13.5px; }
.side-cta:hover { border-color: var(--accent); color: var(--white); }
.side-privacy { align-self: flex-start; margin: 2px 0 0 10px; padding: 3px 0; font-size: 12px; color: var(--dim); }
.side-privacy:hover { color: var(--white); text-decoration: underline; }
/* the skip link sits above the page until a keyboard reaches it */
.skip-link {
  position: fixed; left: 12px; top: -60px; z-index: 3000; padding: 9px 14px; border-radius: 8px;
  background: var(--btn); color: var(--on); font-weight: 600; box-shadow: 0 10px 30px rgba(var(--shade-rgb), calc(0.5 * var(--shade-k)));
  transition: top 0.15s var(--ease);
}
.skip-link:focus { top: 12px; color: var(--on); }
.side-me {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px 8px 8px; border-radius: 10px; text-align: left;
  border: 1px solid var(--line-soft); background: rgba(var(--fg-rgb), 0.03); cursor: pointer; transition: border-color 0.15s, background 0.15s;
}
.side-me:hover { border-color: var(--line); background: rgba(var(--fg-rgb), 0.04); }
.side-me > .ic { color: var(--dim); margin-left: auto; }
.side-me-text { display: grid; min-width: 0; }
.side-me-name { color: var(--white); font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-me-status { color: var(--ink, var(--dim)); font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.main-wrap { position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* Back to top: a round glass button over the page's bottom right corner (clear of its scrollbar), there once the
   page is more than a screen down; hidden, it's out of reach of the keyboard and screen readers too */
.to-top {
  position: absolute; right: 26px; bottom: max(22px, env(safe-area-inset-bottom)); z-index: 60;
  display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line); background: var(--glass-bar); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  color: var(--text); cursor: pointer; box-shadow: 0 10px 28px rgba(var(--shade-rgb), calc(0.4 * var(--shade-k)));
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity 0.2s, transform 0.2s var(--ease), visibility 0s 0.2s, border-color 0.15s, color 0.15s;
}
.to-top.shown { opacity: 1; visibility: visible; transform: none; transition: opacity 0.2s, transform 0.2s var(--ease), visibility 0s, border-color 0.15s, color 0.15s; }
.to-top:hover { border-color: var(--accent); color: var(--white); }
@media (prefers-reduced-motion: reduce) { .to-top, .to-top.shown { transform: none; transition: none; } }
@media (max-width: 900px) { .to-top { right: 16px; } }
/* the scrollbar's room is kept whether a page scrolls or not, so moving between a long page and a short one doesn't shift it */
.main { flex: 1; min-height: 0; overflow: auto; outline: none; scrollbar-gutter: stable; }
.mtop { display: none; }
.scrim { display: none; }
/* while a tab views a team as a lower role (core.js viewAs): an amber bar across the top, over the sidebar and page */
.app.viewing { grid-template-rows: auto minmax(0, 1fr); }
.viewas-bar {
  grid-column: 1 / -1; display: flex; align-items: center; gap: 12px; padding: 8px clamp(14px, 2vw, 22px); z-index: 2;
  background: color-mix(in srgb, var(--warn) 14%, var(--glass-top)); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  border-bottom: 1px solid color-mix(in srgb, var(--warn) 45%, transparent); color: var(--text); font-size: 13.5px;
}
.viewas-bar[hidden] { display: none; }
.viewas-bar > .ic { flex: none; color: var(--warn); }
.viewas-text { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; row-gap: 1px; min-width: 0; margin: 0; }
.viewas-text a { color: var(--white); font-weight: 600; }
.viewas-text a:hover { text-decoration: underline; }
.viewas-note { color: var(--dim); font-size: 12.5px; }
.viewas-stop { flex: none; margin-left: auto; }
.viewas-narrow { display: none; }
/* a phone: one line, the team's name shortened if it must be, and the note left to the wider screens */
@media (max-width: 640px) {
  .viewas-bar { gap: 10px; padding-block: 7px; }
  .viewas-text { flex-wrap: nowrap; }
  .viewas-text > span:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .viewas-text a { display: inline-block; max-width: 34vw; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
  .viewas-note, .viewas-wide { display: none; }
  .viewas-narrow { display: inline; }
}

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .side {
    position: fixed; z-index: 500; inset: 0 auto 0 0; width: min(290px, 86vw); transform: translateX(-102%);
    transition: transform 0.28s var(--ease); box-shadow: 20px 0 50px rgba(var(--shade-rgb), calc(0.5 * var(--shade-k))); background: var(--side-solid);
  }
  .side.open { transform: none; }
  .side.open + .scrim { display: block; position: fixed; inset: 0; z-index: 400; background: var(--scrim); }
  .mtop {
    display: flex; align-items: center; gap: 10px; padding: 8px 12px; height: 54px; flex: none;
    background: var(--glass-top); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); border-bottom: 1px solid var(--line-soft); --ring: var(--side-ring);
  }
  .mtop .brand { font-size: 15px; padding: 2px 0; }
  .mtop-inbox { margin-left: auto; position: relative; width: 38px; height: 38px; }
  .mtop-inbox .badge { position: absolute; top: 1px; right: -2px; height: 16px; min-width: 16px; font-size: 10.5px; padding: 0 4px; }
}

/* ---------- pages ---------- */
.page { padding: 26px clamp(16px, 3vw, 40px) 64px; }
.page.narrow { max-width: 1200px; margin-inline: auto; }
/* a game's pages: wider, for their charts and lists (games.css sets panels side by side as the room allows) */
.page.wide { max-width: 1680px; margin-inline: auto; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 20px; }
.page-head h1 { font-size: 26px; letter-spacing: -0.015em; }
.page-sub { color: var(--dim); margin-top: 6px; max-width: 70ch; }
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line-soft); margin-bottom: 22px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.tab {
  position: relative; display: inline-flex; align-items: center; gap: 8px; padding: 9px 12px; margin-bottom: -1px; border: 0; border-bottom: 2px solid transparent;
  background: none; color: var(--mist); font-size: 14px; font-weight: 500; cursor: pointer; white-space: nowrap; transition: color 0.15s, border-color 0.15s;
}
.tab:hover { color: var(--white); }
.tab[aria-selected="true"] { color: var(--white); border-bottom-color: var(--accent); }
.tab[aria-current="page"] { color: var(--white); }
/* a page's tabs (settings, a team) draw their underline as its own element, so moving between tabs slides it across */
.tab-ink { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; border-radius: 2px; background: var(--accent); pointer-events: none; view-transition-name: tab-ink; }
.tab .ic { color: var(--dim); }
.tab[aria-selected="true"] .ic, .tab[aria-current="page"] .ic { color: var(--accent); }
.panel {
  background: var(--panel); border: 1px solid var(--line-soft); border-radius: 14px; padding: 20px 22px; --ring: var(--panel-ring);
  box-shadow: inset 0 1px 0 rgba(var(--fg-rgb), 0.03), 0 24px 48px -32px rgba(var(--shade-rgb), calc(0.8 * var(--shade-k)));
}
.panel + .panel { margin-top: 16px; }
.panel h2 { font-size: 16px; margin-bottom: 4px; }
.panel-sub { color: var(--dim); font-size: 13.5px; margin-bottom: 16px; max-width: 70ch; }
.section-title { font-size: 15px; font-weight: 600; color: var(--white); margin: 0 0 12px; display: flex; align-items: center; gap: 8px; }
.section-title .count { font-family: var(--mono); font-size: 12px; color: var(--dim); font-weight: 400; }
.empty-page { max-width: 460px; margin: 12vh auto 0; padding: 0 20px; display: grid; gap: 12px; justify-items: start; }
.empty-page h1 { font-size: 24px; }
.empty { padding: 28px 20px; text-align: center; color: var(--dim); border: 1px dashed var(--line); border-radius: 12px; background: var(--well); }
.empty strong { display: block; color: var(--text); font-size: 15px; margin-bottom: 4px; }
.boot {
  display: grid; place-content: center; justify-items: center; gap: 22px; height: 100dvh;
  color: var(--dim); font-family: var(--mono); font-size: 12.5px; letter-spacing: 0.06em;
  background: radial-gradient(320px 320px at 50% 46%, rgba(var(--sel-rgb), 0.16), transparent 70%);
  animation: boot-in 0.15s ease-out both;
}
/* the resting state is a full mark, which is what reduced motion leaves on screen. The boot screen is often up for
   under half a second, so the fill starts with water already in it and a drop already falling. */
.boot-mark { width: 112px; height: auto; overflow: visible; }
.boot-glass { fill: rgba(var(--glow-rgb), 0.07); stroke: rgba(var(--glow-rgb), 0.35); stroke-width: 5; }
[data-theme="light"] #boot-drop stop { stop-color: #0e7490; }
.boot-water { animation: boot-drain 2.8s linear -0.7s infinite; }
.boot-wave { transform: translate(-480px, 64px); animation: boot-rise 2.8s -0.7s infinite; }
.boot-drop { stroke-width: 9; stroke-linecap: round; opacity: 0; animation: boot-fall 0.95s cubic-bezier(0.5, 0, 1, 1) -0.6s infinite; }
.boot-drop:nth-of-type(2) { animation-delay: -0.28s; }
.boot-drop:nth-of-type(3) { animation-delay: 0.03s; }
/* the level climbs from below the mark to above it, the wave drifting sideways as it goes */
@keyframes boot-rise {
  0% { transform: translate(0, 436px); animation-timing-function: cubic-bezier(0.35, 0, 0.5, 1); }
  72% { transform: translate(-360px, 64px); animation-timing-function: linear; }
  100% { transform: translate(-480px, 64px); }
}
/* once full it lets go, so the next fill starts from an empty glass */
@keyframes boot-drain { 0%, 80% { opacity: 1; } 100% { opacity: 0; } }
@keyframes boot-fall {
  0% { transform: translate(26px, -106px); opacity: 0; }
  30% { opacity: 1; }
  100% { transform: translate(0, 0); opacity: 0.9; }
}
@keyframes boot-in { from { opacity: 0; } }
.boot-err { display: grid; gap: 14px; justify-items: center; place-content: center; height: 100dvh; padding: 20px; text-align: center; }
.spin { width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(var(--glow-rgb), 0.25); border-top-color: var(--accent); animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
/* a quick load never shows its spinner: it fades in only once the wait passes 300ms */
.loading { display: flex; align-items: center; gap: 10px; padding: 40px 0; color: var(--dim); font-family: var(--mono); font-size: 13px; animation: loading-in 0.2s ease-out 0.3s both; }
@keyframes loading-in { from { opacity: 0; } }

/* ---------- moving between pages (viewTransition() in js/core.js sets html[data-vt]) ---------- */
/* Only what changed moves. In the app the sidebar holds still while the page under it fades out fast and clears in
   from a light blur, like a rained-on window clearing; a tab change also holds the page's title and tabs. The
   current-page markers glide on their own. The first appearance of the app, or of a sign-in screen, is a plain
   crossfade of everything. */
:root[data-vt="page"] .main, :root[data-vt="tab"] .main, :root[data-vt="view"] .main { view-transition-name: page; }
:root[data-vt="tab"] .page-head { view-transition-name: page-head; }
:root[data-vt="tab"] .page-head + .tabs { view-transition-name: page-tabs; }
:root[data-vt="auth"] .auth-hero { view-transition-name: auth-hero; }
:root[data-vt="auth"] .auth-panel { view-transition-name: auth-panel; }
:root[data-vt]:not([data-vt="swap"])::view-transition-old(root),
:root[data-vt]:not([data-vt="swap"])::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
:root[data-vt="swap"]::view-transition-old(root) { animation-duration: 0.16s; }
:root[data-vt="swap"]::view-transition-new(root) { animation-duration: 0.3s; animation-timing-function: var(--ease); }
::view-transition-old(page), ::view-transition-old(auth-panel) { animation: vt-out 0.12s ease-in both; }
::view-transition-new(page), ::view-transition-new(auth-panel) { animation: vt-clear 0.32s var(--ease) 0.04s both; }
/* switching a board between table and kanban is a plain crossfade: the header and toolbar are the same either side */
:root[data-vt="view"]::view-transition-old(page) { animation: vt-fade-out 0.12s ease-in both; }
:root[data-vt="view"]::view-transition-new(page) { animation: vt-fade-in 0.22s var(--ease) both; }
/* what a tab change holds still is drawn at its own size, never stretched to fit */
::view-transition-old(page-head), ::view-transition-new(page-head), ::view-transition-old(page-tabs), ::view-transition-new(page-tabs) {
  width: auto; height: auto; object-fit: none; object-position: left top;
}
::view-transition-group(side-ink), ::view-transition-group(tab-ink), ::view-transition-group(seg-ink) {
  animation-duration: 0.34s; animation-timing-function: var(--ease);
}
@keyframes vt-out { to { opacity: 0; filter: blur(3px); } }
@keyframes vt-clear { from { opacity: 0; filter: blur(5px); transform: translateY(6px); } }
@keyframes vt-fade-out { to { opacity: 0; } }
@keyframes vt-fade-in { from { opacity: 0; } }

/* ---------- plain pages: the privacy policy and the server's error pages (privacy.html, 404.html, 50x.html) ---------- */
.doc { max-width: 720px; margin: 0 auto; padding: 40px clamp(18px, 4vw, 32px) 72px; }
.doc-brand { margin-bottom: 36px; font-size: 18px; }
.doc h1 { font-size: clamp(28px, 4vw, 36px); letter-spacing: -0.015em; margin-bottom: 8px; }
.doc h2 { font-size: 19px; margin: 36px 0 10px; }
.doc p, .doc li { color: var(--mist); font-size: 15.5px; line-height: 1.65; max-width: 68ch; }
.doc p + p { margin-top: 12px; }
.doc ul { margin: 10px 0 0; padding-left: 20px; display: grid; gap: 8px; }
.doc strong { color: var(--text); font-weight: 600; }
.doc code { font-family: var(--mono); font-size: 0.9em; color: var(--text); }
.doc a:not(.brand) { text-decoration: underline; }
.doc-date { font-family: var(--mono); font-size: 13px; color: var(--dim) !important; }
.doc-lede { font-size: 17px !important; color: var(--text) !important; margin-top: 18px; }
.errpage { min-height: 100dvh; display: grid; place-content: center; justify-items: start; gap: 14px; padding: 32px clamp(18px, 6vw, 64px); max-width: 640px; margin-inline: auto; }
.errpage .brand-mark { margin-bottom: 8px; }
.errpage h1 { font-size: clamp(28px, 5vw, 40px); letter-spacing: -0.015em; }
.errpage p { color: var(--mist); font-size: 16px; max-width: 52ch; }
.errpage p a:not(.btn) { text-decoration: underline; text-underline-offset: 3px; }
.errpage .code { font-family: var(--mono); font-size: 13px; color: var(--dim); margin-top: 6px; }

/* ---------- signed-out screens ---------- */
/* The rain fills the window; the pitch and the panel share a frame of at most 1360px in the middle of it, both
   starting from one top line (the brand level with the panel's heading), so moving between the screens changes
   only what's under the heading. The top line drops lower on taller windows and rises on short ones, so Create
   account's button stays in view on a laptop. */
.auth {
  --auth-top: clamp(28px, calc(50vh - 340px), 200px); --auth-pad: clamp(28px, 3vw, 40px);
  position: relative; min-height: 100dvh; display: grid; grid-template-columns: minmax(0, 1fr) minmax(380px, 460px);
  align-items: start; column-gap: clamp(32px, 5vw, 96px); overflow: hidden;
  padding: var(--auth-top) max(clamp(24px, 5vw, 72px), calc((100% - 1360px) / 2)) 48px;
}
[data-theme="light"] .auth { background: var(--clouds, none) 50% 0 / 1600px 420px repeat-x; }
.auth-rain { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.6; }
.auth-hero { position: relative; display: flex; flex-direction: column; gap: 18px; padding-top: var(--auth-pad); container-type: inline-size; }
.auth-brand { font-size: 22px; margin-bottom: 18px; }
/* (sized by its column: about 72px beside the panel on a big screen, never under 34px; a phone's is 32px, below) */
.auth-pitch { font-size: clamp(34px, 9cqi, 88px); font-weight: 700; line-height: 1.04; letter-spacing: -0.02em; color: var(--white); max-width: 14ch; }
.auth-sub { font-size: 17px; color: var(--mist); max-width: 40ch; }
/* a still glimpse of a board under the pitch, on a wide screen only (auth.js miniBoard): a group's title over its 4px
   accent edge, 40px rows of a name, a face, a label pill and a mono date, as the board draws them */
.auth-mini { display: none; margin-top: 18px; max-width: 600px; border-radius: 14px; border: 1px solid var(--line-soft); background: var(--panel);
  box-shadow: inset 0 1px 0 rgba(var(--fg-rgb), 0.03), 0 24px 48px -32px rgba(var(--shade-rgb), calc(0.8 * var(--shade-k))); overflow: hidden; }
@media (min-width: 1280px) and (min-height: 700px) { .auth-mini { display: block; } }
.auth-mini-head { display: flex; align-items: baseline; gap: 10px; padding: 12px 16px 10px; }
.auth-mini-title { font-weight: 600; font-size: 15px; color: var(--accent); }
.auth-mini-n { font-family: var(--mono); font-size: 12px; color: var(--dim); }
.auth-mini-rows { margin: 0 0 14px 14px; border-left: 4px solid var(--accent); border-radius: 4px 0 0 4px; }
.auth-mini-row { display: grid; grid-template-columns: minmax(0, 1fr) 44px 128px 76px; align-items: center; height: 40px; padding-left: 14px;
  border-top: 1px solid var(--line-soft); font-size: 14px; color: var(--text); }
.auth-mini-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.auth-mini-row .av { justify-self: center; }
.auth-mini-pill { margin: 0 8px; height: 28px; border-radius: 6px; display: grid; place-items: center; font-size: 13px; font-weight: 600;
  background: var(--pill); color: var(--pill-ink); box-shadow: inset 0 0 0 1px var(--pill-edge); }
.auth-mini-pill.none { background: none; box-shadow: none; }
.auth-mini-date { font-family: var(--mono); font-size: 12.5px; color: var(--mist); }
.auth-mini-date.late { color: var(--late); }
.auth-mini-date.today { color: var(--accent); }
.auth-mini-date.late::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-right: 6px; border-radius: 50%; background: var(--late); vertical-align: 1px; }
.auth-panel {
  position: relative; display: flex; flex-direction: column; gap: 18px; padding: var(--auth-pad);
  background: var(--auth-panel); border: 1px solid var(--line); border-radius: 14px; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  box-shadow: inset 0 1px 0 rgba(var(--fg-rgb), 0.03), 0 24px 48px -32px rgba(var(--shade-rgb), calc(0.8 * var(--shade-k)));
}
.auth-panel h1 { font-size: 24px; }
/* (headings and a form's result take focus when a screen changes, to be read out; they aren't controls) */
.auth-panel h1:focus, .auth-done:focus { outline: none; }
.auth-lede { color: var(--mist); }
.auth-panel .small-link { display: inline-block; padding: 3px 0; min-height: 24px; }
/* links inside a sentence are underlined, not only coloured */
.auth-foot a, .auth-foot .small-link { text-decoration: underline; text-underline-offset: 3px; }
.auth-closed:empty { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.input-wrap { position: relative; display: block; }
.auth-lede .ic { vertical-align: -3px; color: var(--accent); }
.auth-lede strong { color: var(--white); font-weight: 600; word-break: break-all; }
.auth-foot { color: var(--dim); font-size: 14px; }
.auth-note { color: var(--mint); font-size: 13.5px; }
.auth-note.bad { color: var(--bad); }
/* (an empty live region stays in the page, out of sight, so what's put in it later is read out) */
.auth-note:empty { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.auth-fix { padding-top: 6px; border-top: 1px solid var(--line-soft); }
.auth-legal { margin-top: 6px; font-size: 12.5px; }
.auth-legal a { color: var(--dim); text-decoration: underline; display: inline-block; padding: 3px 0; }
.auth-legal a:hover { color: var(--white); }
@media (max-width: 860px) {
  .auth { grid-template-columns: 1fr; align-content: start; padding: 0; }
  .auth-hero { padding: 32px 22px 8px; gap: 10px; }
  .auth-brand { margin-bottom: 8px; }
  .auth-pitch { font-size: 32px; }
  .auth-sub { font-size: 15px; }
  .auth-panel { margin: 18px 12px 24px; padding: 26px 20px; }
  /* (past Sign in and Create account, people already have an account: the brand line, then the task) */
  .auth.task .auth-pitch, .auth.task .auth-sub { display: none; }
  .auth.task .auth-hero { padding-bottom: 0; }
  .auth.task .auth-brand { margin-bottom: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
  /* pages still change with a short fade, but nothing glides, rises or blurs */
  ::view-transition-group(*) { animation: none !important; }
  ::view-transition-old(page), ::view-transition-old(auth-panel), ::view-transition-old(side-ink), ::view-transition-old(tab-ink), ::view-transition-old(seg-ink) { animation: vt-fade-out 0.1s ease-in both !important; }
  ::view-transition-new(page), ::view-transition-new(auth-panel), ::view-transition-new(side-ink), ::view-transition-new(tab-ink), ::view-transition-new(seg-ink) { animation: vt-fade-in 0.14s ease-out both !important; }
}
