/* Schedule. One design for every profile: the same band for everyone (light gray in the light theme, black in the
   dark one; people's colors are on their avatars), grays for chrome, and each course in its own color (purple, cyan,
   orange, pink, green, lime; ink for work and other non-class time). */
:root {
  --title-top: calc(28px + env(safe-area-inset-top, 0px));   /* a page's title: the page's top padding (20 px on phones); Everyone's too */
  --band: #e3e3e6; --band-ink: #111111;
  --strong: #111111; --strong-ink: #ffffff;   /* the black of buttons and switches, the same in both themes */
  --band-muted: color-mix(in srgb, var(--band-ink) 80%, var(--band));
  --band-line: color-mix(in srgb, var(--band-ink) 38%, var(--band));
  --bg: #f4f4f4;
  --surface: #ffffff;
  --ink: #111111;
  --muted: #666666;
  --line: #dadada;
  --line-soft: #ebebeb;
  --live: #d92d20;
  --star: #f2a900;
  --wheel-edge: #d4d4d4; --wheel-mid: #ffffff;
  /* the wheel's panel and its Now button over the map: white at 65% with a faint shadow in the light (26 Oct ~14:40,
     user; ~15:25 "quite a bit weaker" than the chips' it had at first; black at 29% from the Figma before that, white
     at 55% until 26 Oct), black at 20% in the dark */
  --glass: rgba(255, 255, 255, 0.65); --glass-shadow: 0 1px 6px rgba(0, 0, 0, .06);
  --frost: transparent;   /* a tint for the frosted band behind the pulled-up list's wheel (see .sheet-dock::before): none, so where nothing passes under it it looks like the blurred map round it (28 Oct, user: with 40% of the page's color it showed as a darker band, with a step at the list header's corners on Android) */
  --tab-ic: #000000; --tab-ic-rest: .31;   /* resting tab icons: black at 31% in the light (26 Oct, user), the ink at 78% in the dark */
  --float: #ffffff;   /* the "In class" chips over the map (black in the dark, as in the Figma) */
  /* the Friends tab (3 Nov 2026, Timur's Figma, dark as drawn; "In light mode the page background should be white"):
     its page, a request's card, the search field, the faint third line (mutual friends), Decline's gray, the blue */
  --fr-page: #ffffff; --fr-card: #f4f4f5; --fr-field: #eeeeef; --fr-dim: #a3a3a3; --fr-out: #8c8c8c; --fr-blue: #127dff;
  --tabbar: 47px;   /* the tab bar at the bottom: 6 px above the icons, 25 px icons (Apple's 25 pt; Timur's Figma, 3 Nov 2026: 30 px until then), 4 px, the labels */
  --tab-pad: max(env(safe-area-inset-bottom, 0px), var(--native-inset-bottom, 0px), 20px);   /* (--native-inset-bottom: the Android app's gesture bar, the iPhone app's own tab bar; app.js setupNative) */   /* below it: the phone's own inset, at least 20 px (the Figma's 21) */
  /* below a page's end: the tab bar, and above its icons (6 px under the bar's top) as much room as under its labels,
     so scrolled to the end the space over the tabs and under them is the same (27 Oct, user; was the bar + 48 px, 54 px
     over the icons) */
  --page-end: calc(var(--tabbar) + 2 * var(--tab-pad) - 6px);
  --dock-h: 116px;  /* the wheel's dock on Friends: the moment's 43 px row, 7 px, the wheel's 66 px panel */
  --top-fade: calc(env(safe-area-inset-top, 0px) * 1.6);   /* how far the status bar's fade (.topfade) reaches; 32 px at least in an installed app */
  --dock-top: max(var(--top-fade), 8px);   /* where the wheel sticks with the list pulled up: just under that fade */
  --when-h: 50px;   /* the moment's line over the wheel (43 px and 7 px): it slides away when the list is pulled up */
  --win-h: 100dvh;   /* the window's height: app.js sets it from innerHeight (an installed Android app gave 100dvh 56 px over the window, 28 Oct) */

  /* Course colors: bar, tinted fill, readable text */
  --p-purple: #6209f1; --p-purple-fill: #efe5fd; --p-purple-text: #5a08dc;
  --p-cyan:   #00a6e0; --p-cyan-fill:   #e5f6fd; --p-cyan-text:   #0a6f9a;
  --p-orange: #ff7f0a; --p-orange-fill: #fff3e7; --p-orange-text: #a8500a;
  --p-pink:   #e50276; --p-pink-fill:   #fce4f1; --p-pink-text:   #b8025c;
  --p-green:  #109e6e; --p-green-fill:  #e3f5ee; --p-green-text:  #0b6b4b;
  --p-lime:   #b1ca4a; --p-lime-fill:   #f7f9ec; --p-lime-text:   #5c6b12;
  --p-ink:    #15152d; --p-ink-fill:    #e7e7e9; --p-ink-text:    #15152d;

  /* Hanken Grotesk for the titles and the text (4 Nov 2026, Timur; Bricolage Grotesque and Figtree before) */
  --font-display: "Hanken Grotesk", system-ui, sans-serif;
  --font-body: "Hanken Grotesk", "Heebo", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-he: "Heebo", "Hanken Grotesk", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --hour: 88px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --band: #111111; --band-ink: #ffffff;
    --bg: #111111; --surface: #1a1a1a; --ink: #f0f0f0; --muted: #a0a0a0; --line: #333333; --line-soft: #242424;
    --live: #ff6b5e; --star: #ffc53d;
    --wheel-edge: #0a0a0a; --wheel-mid: #2e2e2e; --glass: rgba(0, 0, 0, 0.2); --glass-shadow: none; --float: #000000; --tab-ic: var(--ink); --tab-ic-rest: .78;
    --fr-page: #111111; --fr-card: #1a1a1a; --fr-field: #000000; --fr-dim: #5a5a5a; --fr-out: #949494;
    --p-purple: #8b4dff; --p-purple-fill: #231742; --p-purple-text: #c9adff;
    --p-cyan:   #1cb6ec; --p-cyan-fill:   #0f2b37; --p-cyan-text:   #86d8f6;
    --p-orange: #ff8f2a; --p-orange-fill: #36230f; --p-orange-text: #ffbb7c;
    --p-pink:   #f0388f; --p-pink-fill:   #3b1428; --p-pink-text:   #ffa3cd;
    --p-green:  #2cc58d; --p-green-fill:  #0f2a21; --p-green-text:  #8fe3c3;
    --p-lime:   #bcd65a; --p-lime-fill:   #252b10; --p-lime-text:   #d6ea8c;
    --p-ink:    #d8d8e8; --p-ink-fill:    #26262e; --p-ink-text:    #e2e2ee;
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --band: #111111; --band-ink: #ffffff;
  --bg: #111111; --surface: #1a1a1a; --ink: #f0f0f0; --muted: #a0a0a0; --line: #333333; --line-soft: #242424;
  --live: #ff6b5e; --star: #ffc53d;
  --wheel-edge: #0a0a0a; --wheel-mid: #2e2e2e; --glass: rgba(0, 0, 0, 0.2); --glass-shadow: none; --float: #000000; --tab-ic: var(--ink); --tab-ic-rest: .78;
  --fr-page: #111111; --fr-card: #1a1a1a; --fr-field: #000000; --fr-dim: #5a5a5a; --fr-out: #949494;
  --p-purple: #8b4dff; --p-purple-fill: #231742; --p-purple-text: #c9adff;
  --p-cyan:   #1cb6ec; --p-cyan-fill:   #0f2b37; --p-cyan-text:   #86d8f6;
  --p-orange: #ff8f2a; --p-orange-fill: #36230f; --p-orange-text: #ffbb7c;
  --p-pink:   #f0388f; --p-pink-fill:   #3b1428; --p-pink-text:   #ffa3cd;
  --p-green:  #2cc58d; --p-green-fill:  #0f2a21; --p-green-text:  #8fe3c3;
  --p-lime:   #bcd65a; --p-lime-fill:   #252b10; --p-lime-text:   #d6ea8c;
  --p-ink:    #d8d8e8; --p-ink-fill:    #26262e; --p-ink-text:    #e2e2ee;
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
/* No zooming the page, like an app (27 Oct 2026, user): scrolling only, so no pinch and no double-tap zoom. The map
   pinches on its own (.m3d .stage, touch-action: none); the viewport tag and app.js (gesturestart) do the rest. */
html { touch-action: pan-x pan-y; }
/* The iPhone app (iOS 26; viewport-fit=cover with the see-through status bar): a page shorter than the screen is laid
   out in a viewport short by the status bar's height, so the tab bar and everything else fixed to the bottom sit that
   much too high (28 Oct, a friend's video: on a class's page in the editor, about 55 px; WebKit bug 301108). A page at
   least as tall as the screen gets the whole screen, so the page is made that tall: 100% (the short viewport) plus the
   status bar, but no taller than the screen (100lvh), so once the whole screen is given it doesn't scroll. Where the
   top inset is 0, or the page is taller anyway, this changes nothing. */
@media (display-mode: standalone) { html { min-height: min(100lvh, calc(100% + env(safe-area-inset-top, 0px))); } }
[hidden] { display: none !important; }
body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--font-body); font-size: 15px; line-height: 1.5; -webkit-font-smoothing: antialiased; }
.page {
  max-width: 1060px; margin: 0 auto;
  padding-block: var(--title-top) var(--page-end);
  padding-left: max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
  display: flex; flex-direction: column; gap: 36px;
}
[lang="he"] { font-family: var(--font-he); }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
h2 { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 22px; letter-spacing: -0.01em; text-wrap: balance; }
.section { display: flex; flex-direction: column; gap: 14px; }
.shead { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; }
.shead p { margin: 0; color: var(--muted); font-size: 13px; }
.view { display: flex; flex-direction: column; gap: 36px; }
.live-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--live); }

/* ---------- Top of the screen ---------- */
/* A progressive blur instead of a hard edge (no band at the top since 25 Oct: the tab bar is at the bottom). The blur
   is strongest at the top edge and fades out lower down, with a tint that eases out the same way, so the page
   dissolves into the top of the screen.
   - iPhone app: the page is drawn under the status bar; the fade covers it and a little more, tinted black, because
     the clock and battery icons there are always white.
   - Android and installed apps on computers: the system draws its own bar in the theme color, which app.js (topBar)
     keeps at the page's background; a short fade under that bar, in the same color, joins the page to it.
   - A browser tab: no fade (zero tall). */
.topfade {
  --fade: max(calc(env(safe-area-inset-top, 0px) * 1.6), var(--fade-min, 0px));
  --tint: var(--bg); --tint-0: 100%;   /* starts exactly in the bar's color */
  position: fixed; inset: 0 0 auto; height: var(--fade); z-index: 10; pointer-events: none;
}
@media (display-mode: standalone), (display-mode: minimal-ui) { .topfade { --fade-min: 32px; } :root { --top-fade: max(calc(env(safe-area-inset-top, 0px) * 1.6), 32px); } }
:root[data-ios-app] .topfade { --tint: #111111; --tint-0: 88%; }   /* set by topBar() in app.js */
.topfade i { position: absolute; inset: 0; }
.topfade i:nth-child(1) { -webkit-backdrop-filter: blur(1px); backdrop-filter: blur(1px); -webkit-mask-image: linear-gradient(#000 45%, transparent 100%); mask-image: linear-gradient(#000 45%, transparent 100%); }
.topfade i:nth-child(2) { -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); -webkit-mask-image: linear-gradient(#000 35%, transparent 85%); mask-image: linear-gradient(#000 35%, transparent 85%); }
.topfade i:nth-child(3) { -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); -webkit-mask-image: linear-gradient(#000 25%, transparent 70%); mask-image: linear-gradient(#000 25%, transparent 70%); }
.topfade i:nth-child(4) { -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); -webkit-mask-image: linear-gradient(#000 15%, transparent 55%); mask-image: linear-gradient(#000 15%, transparent 55%); }
.topfade i:nth-child(5) { -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); -webkit-mask-image: linear-gradient(#000 0%, transparent 40%); mask-image: linear-gradient(#000 0%, transparent 40%); }
.topfade::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(
    color-mix(in srgb, var(--tint) var(--tint-0, 88%), transparent) 0%,
    color-mix(in srgb, var(--tint) 80%, transparent) 30%,
    color-mix(in srgb, var(--tint) 62%, transparent) 48%,
    color-mix(in srgb, var(--tint) 38%, transparent) 63%,
    color-mix(in srgb, var(--tint) 18%, transparent) 78%,
    color-mix(in srgb, var(--tint) 6%, transparent) 90%,
    transparent 100%);
}
/* Page titles the iOS 26 way (Developer options → Page titles → iOS 26; app.js TITLE_LOOK, barTitle; 30 Oct): the big
   title scrolls away with the page (My week's no longer stays at the top), and once it has gone up under the top a
   small one shows there, centred in a 44 px bar under the status bar, as an iPhone app's navigation bar does: 17 px,
   bold, in the page's own type. Under it, from the first pixel scrolled, a soft blur that fades out downwards (iOS 26's
   scroll edge effect): the status bar's fade above (.topfade), as tall as the bar and 28 px more. Not on Friends. */
.bartitle, .barfade { display: none; }
:root[data-title-look="ios"] .barfade { display: block; }
:root[data-title-look="ios"] .bartitle { display: flex; }
.topfade.barfade { --fade: calc(env(safe-area-inset-top, 0px) + 44px + 28px); opacity: 0; transition: opacity .2s; }
/* (unlike the status bar's fade, which thins out from the top: the whole bar covered, then it fades over its last 28 px) */
.topfade.barfade i:nth-child(1) { -webkit-mask-image: linear-gradient(#000 calc(100% - 8px), transparent); mask-image: linear-gradient(#000 calc(100% - 8px), transparent); }
.topfade.barfade i:nth-child(2) { -webkit-mask-image: linear-gradient(#000 calc(100% - 14px), transparent calc(100% - 4px)); mask-image: linear-gradient(#000 calc(100% - 14px), transparent calc(100% - 4px)); }
.topfade.barfade i:nth-child(3) { -webkit-mask-image: linear-gradient(#000 calc(100% - 20px), transparent calc(100% - 8px)); mask-image: linear-gradient(#000 calc(100% - 20px), transparent calc(100% - 8px)); }
.topfade.barfade i:nth-child(4) { -webkit-mask-image: linear-gradient(#000 calc(100% - 26px), transparent calc(100% - 12px)); mask-image: linear-gradient(#000 calc(100% - 26px), transparent calc(100% - 12px)); }
.topfade.barfade i:nth-child(5) { -webkit-mask-image: linear-gradient(#000 calc(100% - 32px), transparent calc(100% - 16px)); mask-image: linear-gradient(#000 calc(100% - 32px), transparent calc(100% - 16px)); }
.topfade.barfade::after {
  background: linear-gradient(
    color-mix(in srgb, var(--tint) 94%, transparent) 0%,
    color-mix(in srgb, var(--tint) 86%, transparent) calc(100% - 34px),
    color-mix(in srgb, var(--tint) 45%, transparent) calc(100% - 16px),
    color-mix(in srgb, var(--tint) 12%, transparent) calc(100% - 6px),
    transparent 100%);
}
.bartitle {
  position: fixed; z-index: 11; top: 0; left: 0; right: 0; height: calc(env(safe-area-inset-top, 0px) + 44px);
  padding: env(safe-area-inset-top, 0px) 64px 0; align-items: center; justify-content: center; pointer-events: none;
  font: 700 17px/22px var(--font-body); letter-spacing: -0.01em; color: var(--ink);
  opacity: 0; transform: translateY(6px); transition: opacity .18s, transform .18s;
}
.bartitle span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.bar-scrolled .barfade { opacity: 1; }
body.bar-title .bartitle { opacity: 1; transform: none; }
body.noblur .barfade i { -webkit-backdrop-filter: none; backdrop-filter: none; }
:root[data-ios-app] .topfade.barfade { --tint: var(--bg); z-index: 9; }   /* the installed iPhone web app: under the black status bar's fade, in the page's color */
:root[data-title-look="ios"] #week-h { position: static; }
:root[data-title-look="ios"] #week-h::before { display: none; }
@media (prefers-reduced-motion: reduce) { .bartitle { transform: none; } }
/* "Offline": a pill at the top of the screen while the saved copy is shown */
.net {
  position: fixed; z-index: 30; top: calc(env(safe-area-inset-top, 0px) + 10px); left: 50%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
  color: var(--strong-ink); background: var(--strong); border-radius: 999px; padding: 4px 10px; box-shadow: 0 2px 10px rgba(0, 0, 0, .2);
}
.net::before { content: ""; width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid currentColor; }

/* the big title of a page: "Everyone" on Map and Friends (the group you see; one group for now, more later), "My week" */
/* 36 px (was 44): the Figma's title is 34 px of Inter, whose capitals are taller (0.73 of the size against Bricolage's
   0.66), so 36 px of Bricolage looks the same size */
.page-title { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 36px; line-height: 1.1; letter-spacing: -0.02em; text-wrap: balance; }
/* the moment the wheel points at, and how far from now: "3 Nov, 18:15 (+3 days 14 h)" (on Map just above the wheel).
   In Figtree, like the chips and the tabs: on the map the title is the one line in the display face, the rest is the
   app's working layer. 21 px matches the Figma's 20.6 px of Inter (same capital height); figures all one width, so the
   time doesn't jiggle while the wheel turns */
.when { margin: 6px 0 0; font-family: var(--font-body); font-weight: 700; font-size: 21px; line-height: 1.3; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.when-off { color: color-mix(in srgb, var(--ink) 72%, transparent); }   /* the Figma's 75% white */
.when-off:empty { display: none; }

/* ---------- The tab bar (bottom of every page, 25 Oct; the Figma's sizes since 25 Oct evening) ----------
   Five 57 px tabs spread over 344 px (on wider screens too), 25 px icons (30 until 3 Nov 2026), 11 px labels (the Figma's 9.9 px are Inter,
   whose small letters are taller: 0.55 of the size against Figtree's 0.50). The icons are SVG files in tabs/
   used as masks, so only their shape counts and they take the tab's color: in the Figma a resting icon (78%) is brighter
   than its label (50%), and the selected tab is white.
   Where a tap counts (27 Oct, user: a tap on a tab sometimes scrolled the page instead): the whole bar, split between
   the four tabs. Each tab's area (its ::after) runs halfway to the next tab's middle, the outer ones to the screen's
   edge, and from the bar's top to the bottom of the screen; the tabs themselves are drawn where they were. A finger
   on the bar never scrolls the page (touch-action: none), and app.js takes a finger that slid a little as a tap. */
.tabbar {
  --tab-l: max(clamp(16px, 8.25vw, 34px), env(safe-area-inset-left, 0px));   /* the Figma's 89 of 1080 */
  --tab-r: max(clamp(16px, 8.25vw, 34px), env(safe-area-inset-right, 0px));
  --tab-sp: calc((min(100vw, 412px) - var(--tab-l) - var(--tab-r) - 57px) / 4);   /* from one tab's middle to the next (five tabs since 2 Nov 2026) */
  --tab-out: min(calc((100vw - min(100vw, 412px)) / 2), 24px);   /* beyond the bar on a phone wider than 412 px */
  position: fixed; z-index: 20; left: 0; right: 0; bottom: 0; max-width: 412px; margin: 0 auto;
  display: flex; justify-content: space-between; height: calc(var(--tabbar) + var(--tab-pad));
  padding: 6px var(--tab-r) var(--tab-pad) var(--tab-l);
  touch-action: none;
}
.tabbar a {
  position: relative; flex: 0 1 57px; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 4px;
  color: color-mix(in srgb, var(--ink) 50%, transparent); text-decoration: none; -webkit-tap-highlight-color: transparent;
  font-size: 11px; font-weight: 700; line-height: 12px; letter-spacing: 0.01em;
}
.tabbar a > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tabbar a::after { content: ""; position: absolute; top: -6px; bottom: calc(-1 * var(--tab-pad)); left: calc(50% - var(--tab-sp) / 2); right: calc(50% - var(--tab-sp) / 2); }
.tabbar a:first-child::after { left: calc(-1 * (var(--tab-l) + var(--tab-out))); }
.tabbar a:last-child::after { right: calc(-1 * (var(--tab-r) + var(--tab-out))); }
.tabbar a:hover, .tabbar a[aria-current="page"] { color: var(--ink); }
/* Friends: a blue dot on the icon's top right while friend requests wait for your answer (3 Nov 2026, Timur: "the menu
   icon has blue (#127DFF) dot"; a red count until then), a ring of the page's color round it */
.tab-badge { position: absolute; top: 0; left: calc(50% + 6px); z-index: 1; width: 10px; height: 10px; border-radius: 50%;
  background: var(--fr-blue); box-shadow: 0 0 0 2px var(--bg); pointer-events: none; }
.tab-badge[hidden] { display: none; }
.tabbar a:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 10px; }
/* the resting 78% is the icon's opacity, not its color's, so where its strokes overlap (Today's rings on the calendar,
   Friends' arm on the body) they don't add up to a darker spot */
.tab-ic { position: relative; display: block; width: 25px; height: 25px; flex: none; color: var(--tab-ic); opacity: var(--tab-ic-rest); transition: opacity .15s; }
.tabbar a:hover .tab-ic, .tabbar a[aria-current="page"] .tab-ic { opacity: 1; }
.tab-ic::before { content: ""; position: absolute; inset: 0; background: currentColor; -webkit-mask: var(--ic) center / contain no-repeat; mask: var(--ic) center / contain no-repeat; }
.tabbar a[aria-current="page"] .tab-ic::before { -webkit-mask-image: var(--ic-on, var(--ic)); mask-image: var(--ic-on, var(--ic)); }
/* Today: inline SVG with today's date (app.js renderTabDay), an outline at rest and, when selected, a filled calendar
   with the date cut out of it (the Figma's active state) */
.tab-ic.svg::before { content: none; }
.tab-svg { display: block; width: 100%; height: 100%; overflow: visible; }
.tab-day-n { font: 800 10px var(--font-body); font-variant-numeric: tabular-nums; text-anchor: middle; }   /* (of the icon's 25: the Figma's Inter Extra Bold, its capitals' height) */
.tab-svg .on, .tabbar a[aria-current="page"] .tab-svg .off { display: none; }
.tabbar a[aria-current="page"] .tab-svg .on { display: inline; }
/* you: your avatar, as friends see it, in place of an icon */
#who .av { width: 25px; height: 25px; font-size: 10px; }
/* A tapped tab's icon settles in: it springs from small to full size while it fills in (option A of the "Tab icon
   animations" canvas, since 26 Oct ~00:50; option C, a hop, for half an hour before); Friends also waves its arm (from
   option B; it blinked too for a moment, user: "shouldn't blink"). app.js hopTab sets .hop on the tab for a second.
   Transforms and opacity only, so it costs next to nothing; off with reduced motion */
.tabbar a.hop .tab-ic, #who.hop .av { animation: tab-settle .42s cubic-bezier(.34, 1.56, .64, 1); }
@keyframes tab-settle { 0% { transform: scale(.72); opacity: .35; } 35% { opacity: 1; } 100% { transform: none; opacity: 1; } }
.f-arm { transform-box: view-box; transform-origin: 3.7px 11.235px; }   /* (the shoulder, of the icon's 25) */
.tabbar a.hop .f-arm { animation: tab-wave .75s .1s ease-in-out; }
@keyframes tab-wave { 0%, 100% { transform: none; } 25% { transform: rotate(-30deg); } 50% { transform: rotate(8deg); } 75% { transform: rotate(-18deg); } }
@media (prefers-reduced-motion: reduce) { .tabbar a.hop .tab-ic, .tabbar a.hop .tab-ic *, #who.hop .av { animation: none; } }
/* your tab, selected: a soft rounded square behind the avatar and name (the Figma, 26 Oct; was a ring round the
   avatar), 57.5 by 49 px, from 4.8 px above the avatar to 3.4 px below the name. The name turns white like the other
   tabs' labels (26 Oct, user; the Figma had it at 50%), and a long one ends in "…" 5 px inside the square, at rest too,
   so it doesn't change as the tab is picked (26 Oct, user: "if the name is too long, it should be shortened with ...") */
#who { position: relative; }
#who > span:last-child { max-width: 47.5px; }
#who[aria-current="page"]::before { content: ""; position: absolute; z-index: -1; left: 50%; width: 57.5px; margin-left: -28.75px; top: -4.8px; bottom: -3.4px; border-radius: 15.6px; background: color-mix(in srgb, var(--ink) 15%, transparent); }
/* under the tab bar: the page fades out (a progressive blur and the page's color, as at the top) */
.botfade { position: fixed; z-index: 19; left: 0; right: 0; bottom: 0; height: calc(var(--tabbar) + var(--tab-pad) + 26px); pointer-events: none; }
.botfade i { position: absolute; inset: 0; }
.botfade i:nth-child(1) { -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); -webkit-mask-image: linear-gradient(transparent, #000 40%); mask-image: linear-gradient(transparent, #000 40%); }
.botfade i:nth-child(2) { -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); -webkit-mask-image: linear-gradient(transparent 20%, #000 60%); mask-image: linear-gradient(transparent 20%, #000 60%); }
.botfade i:nth-child(3) { -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); -webkit-mask-image: linear-gradient(transparent 35%, #000 75%); mask-image: linear-gradient(transparent 35%, #000 75%); }
.botfade i:nth-child(4) { -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); -webkit-mask-image: linear-gradient(transparent 50%, #000 90%); mask-image: linear-gradient(transparent 50%, #000 90%); }
.botfade::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(transparent, color-mix(in srgb, var(--bg) 55%, transparent) 30%, color-mix(in srgb, var(--bg) 88%, transparent) 60%, var(--bg));
}
body:has(#tabs[hidden]) .botfade { display: none; }
/* The iPhone app on iOS 26 draws the tab bar itself, in Liquid Glass, floating over the page (app.js setupNativeTabs,
   ios/Schedule/Web/Tabs.swift). This one stays for its links, unseen; the space under the page is the app's bar
   (--native-inset-bottom, so --tab-pad), and the page runs on under the glass instead of fading out */
html[data-native-tabs] { --tabbar: 0px; --page-end: calc(var(--tab-pad) + 28px); }
html[data-native-tabs] #tabs { visibility: hidden; padding-top: 0; }   /* (exactly the app's bar's height) */
html[data-native-tabs] .botfade { display: none; }

/* ---------- Friends (#friends): the 3D map on the whole screen, and a sheet over it ----------
   (option b, prototype of 26 Oct, the user's Figma: Map and Friends one screen again.) The map layer (#map-view) is
   fixed and stays still; #friends-view is fixed too and app.js moves it up and down (SHEET, 28 Oct: the page doesn't
   scroll here): an empty stretch at the top (#sheet-top, with the title) lets taps and drags through to the map, then
   the sheet: the chips, the moment, the wheel and the list, whose header and first row peek out --peek px above the
   tab bar. All the way up, the wheel is under the status bar's fade and the rows scroll in their own box. */
.map-view { position: fixed; inset: 0; z-index: 1; display: block; overflow: hidden; }
body[data-view="friends"] { --peek: 112px; }   /* the list's header (62 px) and the top of the first row */
@media (max-height: 740px) { body[data-view="friends"] { --peek: 88px; } }   /* small phones: only the list's header, so the campus still fits */
body[data-view="friends"] .page { padding-top: 0; }
body[data-view="friends"] footer, body[data-view="friends"] .preview { display: none; }
/* the page doesn't scroll here: no pull-to-refresh (27 Oct, user: pulling the list down sometimes refreshed the app),
   no bounce of the whole page (on an iPad it took swipes meant for the list, 28 Oct); the other tabs keep both */
:root:has(> body[data-view="friends"]), body[data-view="friends"] { overflow: hidden; overscroll-behavior: none; }
/* The Figma's "scroll edge effect": the map blurs away under the title (top) and under the chips, the wheel and the tabs
   (bottom). One blur each, faded in by a mask (as in the Figma), plus a little of the page's color so the words stay
   readable on the light map. The bottom one (.sheet-scrim) is part of the sheet and moves up with it, so the moment and
   the wheel stay readable wherever the list is. The frame-rate readout turns the blur off and on (body.noblur) to see
   what it costs. */
.map-scrim { position: absolute; z-index: 1; left: 0; right: 0; pointer-events: none; -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); }
.map-scrim.top {
  top: 0; height: calc(env(safe-area-inset-top, 0px) + 116px);
  -webkit-mask-image: linear-gradient(#000 25%, transparent); mask-image: linear-gradient(#000 25%, transparent);
  background: color-mix(in srgb, var(--bg) 45%, transparent);
}
.sheet-scrim {   /* from 66 px above two lines of chips to the end of the list, so the map beside the list is blurred too */
  position: absolute; z-index: 0; left: 50%; width: 100vw; margin-left: -50vw; pointer-events: none;
  top: -154px; bottom: -120px;   /* (on below the sheet, for its spring past the top) */
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  -webkit-mask-image: linear-gradient(transparent, #000 185px); mask-image: linear-gradient(transparent, #000 185px);
  background: color-mix(in srgb, var(--bg) 45%, transparent);
}
body.noblur .map-scrim, body.noblur .sheet-scrim { -webkit-backdrop-filter: none; backdrop-filter: none; }
/* "Covered" (see .sheet-dock::before): with the list all the way up the map is hidden behind the page's color, so it
   isn't blurred while the list scrolls (off once that color has faded in, back on at once when the list comes down) */
:root[data-sheet-look="cover"] body.sheet-up .map-scrim, :root[data-sheet-look="cover"] body.sheet-up .sheet-scrim {
  -webkit-backdrop-filter: none; backdrop-filter: none;
  transition: -webkit-backdrop-filter 0s .25s, backdrop-filter 0s .25s;
}
/* Everyone where Today's and My week's titles are (27 Oct, user; was 24 px under the status bar: 4 px lower on phones,
   4 px higher on computers) */
.map-head {
  position: absolute; z-index: 2; top: 0; left: 0; right: 0; pointer-events: none;
  padding: var(--title-top) 0 0;
}
/* the map under everything; its north-and-zoom control top right, on the title's line, the frame rate under it.
   No z-index on the map itself, so its buttons and popups can sit above the blur (z-index 3) while the model, the
   numbers and the pins stay under it */
.map-view .m3d { position: absolute; inset: 0; height: auto; min-height: 0; margin: 0; border: 0; border-radius: 0; }
/* as in the Figma: 40 px tall, centered on the title's line (its 36 px at 1.1), 14 px from the edge, so the arrow and the
   figure end 22 px in */
.map-view .m3d .north { z-index: 3; top: var(--title-top); left: auto; right: max(14px, env(safe-area-inset-right, 0px)); }
.map-view .m3d .tip, .map-view .m3d .status { z-index: 3; }
.map-view .m3d .help, .map-view .m3d .tools { display: none; }
.m3d .fps {
  position: absolute; z-index: 3; top: calc(var(--title-top) + 48px); right: max(16px, env(safe-area-inset-right, 0px));
  min-width: 92px; padding: 4px 7px; border: 0; border-radius: 6px; cursor: pointer; text-align: right;
  font: 500 10.5px/1.35 var(--font-mono); font-variant-numeric: tabular-nums; color: #fff; background: rgba(0, 0, 0, .62);
}
.m3d .fps[hidden] { display: none; }
.m3d .fps b { font-weight: 600; font-size: 13px; }
.m3d .fps[data-level="ok"] b { color: #5ee08a; }
.m3d .fps[data-level="slow"] b { color: #ffd60a; }
.m3d .fps[data-level="bad"] b { color: #ff6b5e; }
.m3d .fps::after { content: " · blur"; }
body.noblur .m3d .fps::after { content: " · no blur"; }
/* The sheet over the map: above the map layer (z-index 2), in the page's column (as .page), but only the sheet takes
   taps and drags; the stretch above it is as tall as the window minus the tab bar, the peek, the dock and 8 px, so the
   list's header sits --peek px above the tab bar with the sheet down. app.js moves it all up (a transform), by as much
   as it is taller than the window. */
#friends-view {
  position: fixed; z-index: 2; top: 0; left: 0; right: 0; max-width: 1060px; margin: 0 auto; gap: 0; pointer-events: none;
  /* its own layer from the start, painted ahead (the rows below the screen too), so the script moving it is only a
     move for the graphics chip, and the spring's animation doesn't have to make the layer first: on Timur's phone the
     first swipe's let go stood still ~100-170 ms before the spring, with no script running (30 Oct, the trace) */
  will-change: transform;
  padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px));
}
.sheet-top { position: relative; height: calc(var(--win-h) - var(--tabbar) - var(--tab-pad) - var(--peek) - var(--dock-h) - 8px); }
/* the sheet reaches the bottom of the window with it all the way up (its top then just above the window, so the
   moment's line is gone and the wheel is under the status bar's fade); the list fills the rest. Below it the list's
   color goes on (::after), and so do the blur and the fill, for the spring past the top. */
.sheet {
  position: relative; pointer-events: auto; display: flex; flex-direction: column;
  height: calc(var(--win-h) - var(--dock-top) + var(--when-h));
}
.sheet::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 120px; background: var(--surface); pointer-events: none; }
/* beside the sheet, from its top down, the whole width of the screen takes a finger as the sheet does (28 Oct, Timur's
   iPad: "I can't pull up from the sides"); with a mouse the map there stays the map's */
.sheet-grab { position: absolute; z-index: 0; left: 50%; width: 100vw; margin-left: -50vw; top: 0; bottom: 0; }
@media (hover: hover) and (pointer: fine) { .sheet-grab { display: none; } }
/* with the sheet up the moment's line above the wheel is above the window, and fades (26 Oct, user: more friends on
   screen; the list's header still shows the moment's time and the wheel the day; the Now button is right of the
   wheel, so it stays). What is behind the wheel then: see .sheet-dock::before */
.sheet-dock { position: relative; z-index: 3; flex: none; width: 100%; max-width: 560px; margin: 0 auto 8px; display: flex; flex-direction: column; }
.sheet-dock .map-when { transition: opacity .15s, visibility .15s; }
body.sheet-up .sheet-dock .map-when { opacity: 0; visibility: hidden; }
/* the list: the header, then the rows' own box, which scrolls with the sheet up only (body.sheet-up), by the phone's
   own scrolling (app.js SHEET); room at its end for the tab bar. Its scroll bar is drawn (.rows-ind; Timur: "Let's add
   back the scroll bar (just a visual indicator of the length and position)", "make the bar more transparent. And leave
   4px gap at the top"), the browser's own is off */
#board-wrap { position: relative; z-index: 1; border: 0; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; border-radius: 16px 16px 0 0; }   /* no border, as in the Figma (it also kept the header's round corners from showing) */
.board-clip { flex: 1 1 auto; min-height: 0; overflow: hidden auto; overscroll-behavior-y: contain; padding-bottom: var(--page-end); scrollbar-width: none; }
.board-clip::-webkit-scrollbar { display: none; }
/* (a scrolling box from the start, so the list going up doesn't have to make its layer and paint every row then, the
   moment the sheet's spring starts (30 Oct, the first swipe's trace); with the sheet down a finger on it is the sheet's
   only, as when the box didn't scroll then) */
body:not(.sheet-up) .board-clip { touch-action: none; }
.rows-ind { position: absolute; z-index: 13; top: 0; right: 3px; width: 3px; height: 40px; border-radius: 2px; background: color-mix(in srgb, var(--ink) 20%, transparent); opacity: 0; transition: opacity .3s; pointer-events: none; }
.rows-ind.on { opacity: 1; transition: opacity .1s; }
/* What is behind the wheel and round the list once it is pulled all the way up (body.sheet-up). Three looks, picked in
   Settings' developer options (app.js SHEET_LOOK, on <html> as data-sheet-look; 28 Oct, user: "default frosted glass
   everywhere"). (Since the own sheet, 28 Oct, the rows scroll in their own box under the header, so none pass under
   the wheel in any look.)
   - "frost" (the default): the map stays, blurred, beside the list; behind the wheel a frosted band from the top of
     the screen down to the list's header, and the same behind the header's round corners.
   - "cover": the page's color fades in behind the wheel and round the list (.sheet-fill), and the two big blurs turn
     off (the 26 Oct look, the lightest).
   - "map": the map blurred round the list and the wheel with nothing over it (27 Oct evening, the only look until 28
     Oct; its rows were clipped at a line in the stuck header then, a frame or more behind an iPhone's scrolling). */
.sheet-dock::before, .sheet-fill, .board-head::before { content: ""; position: absolute; pointer-events: none; opacity: 0; transition: opacity .2s; }
.sheet-dock::before, .sheet-fill { z-index: -1; left: 50%; width: 100vw; margin-left: -50vw; }
.sheet-dock::before { top: calc(var(--when-h) - var(--dock-top)); bottom: -8px; }
.sheet-fill { z-index: 0; top: calc(var(--dock-h) + 8px - 40px); bottom: -120px; }
/* (it starts 40 px up, under the wheel's, so the two never leave a seam: with the list's top pulled against the
   page's edge, the phone's stretch opened a line of map between them; 26 Oct, user) */
.board-head::before { z-index: -2; left: 0; right: 0; top: 0; height: 16px; }   /* behind the header's round top corners */
:root[data-sheet-look="cover"] .sheet-dock::before, :root[data-sheet-look="cover"] .sheet-fill, :root[data-sheet-look="cover"] .board-head::before { background: var(--bg); }
:root[data-sheet-look="cover"] body.sheet-up .sheet-dock::before, :root[data-sheet-look="cover"] body.sheet-up .sheet-fill, :root[data-sheet-look="cover"] body.sheet-up .board-head::before { opacity: 1; }
/* (the frosted band comes at once when the list sticks, so rows flung up past the header are never seen sharp behind
   the wheel (28 Oct, the Simulator: they were, during its 0.2 s fade); it fades out, its blur off once it has) */
:root[data-sheet-look="frost"] .sheet-dock::before, :root[data-sheet-look="frost"] .board-head::before {
  background: var(--frost); transition: opacity .2s, -webkit-backdrop-filter 0s .2s, backdrop-filter 0s .2s;
}
/* only as wide as the list (the dock is), not the screen: once the list has scrolled under it the band shows the list's
   own color, blurred, and beside the list that met the blurred map as a step at the header's top (28 Oct, Timur on
   Android, twice). So the map beside the list now runs up to the top unbroken, and above the header the band reads as
   the list going on up under the glass */
:root[data-sheet-look="frost"] .sheet-dock::before { left: 0; right: 0; width: auto; margin-left: 0; }
:root[data-sheet-look="frost"] body.sheet-warm .sheet-dock::before, :root[data-sheet-look="frost"] body.sheet-warm .board-head::before {
  /* (30 Oct) drawn once, all but invisibly, when Friends first shows (app.js warmSheet), so the graphics chip has readied
     this blur before the first swipe's spring brings it on: on Timur's phone that spring stood still 60-75 ms, the first
     time only, with nothing of the page's running. Before the sheet-up rule, so that one wins when both apply */
  opacity: .02; -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); transition: none;
}
:root[data-sheet-look="frost"] body.sheet-up .sheet-dock::before, :root[data-sheet-look="frost"] body.sheet-up .board-head::before {
  opacity: 1; -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); transition: none;
}
:root[data-sheet-look] body.noblur .sheet-dock::before, :root[data-sheet-look] body.noblur .board-head::before { -webkit-backdrop-filter: none; backdrop-filter: none; }
/* "map": the list's color only on the header and the rows' box */
:root[data-sheet-look="map"] #board-wrap { background: none; }
:root[data-sheet-look="map"] .board-clip { background: var(--surface); }
/* the "In class" chips, on top of the moment: the first line sits just above it and more lines go on top, so chips
   coming and going never move the ones below; they go with the list pulled up. Black pills in the dark (white in the
   light); the building number in the map's own face (Barlow Condensed, as on the map's number labels), so a chip and
   its building read as the same thing */
.sheet-dock .campus { position: absolute; left: 0; right: 0; bottom: calc(100% + 9px); flex-wrap: wrap-reverse; align-content: flex-start; gap: 9px; pointer-events: none; transition: opacity .2s, visibility .2s; }
.sheet-dock .campus > * { pointer-events: auto; }
body.sheet-up .sheet-dock .campus { opacity: 0; visibility: hidden; }
.sheet-dock .bchip { height: 35px; gap: 5px; padding: 0 6px 0 9px; background: var(--float); border: 0; box-shadow: 0 2px 10px rgba(0, 0, 0, .14); }
.sheet-dock .bchip b { font: 700 14px/1 "Barlow Condensed", var(--font-body); letter-spacing: 0.02em; }   /* the map's numbers' size */
.sheet-dock .bchip b.pl { font: 700 13px/1 var(--font-body); letter-spacing: 0; }
.sheet-dock .bchip .avs .av { width: 23px; height: 23px; font-size: 10.5px; box-shadow: 0 0 0 1.5px var(--float); }
.sheet-dock .bchip .avs .av + .av { margin-left: -9px; }
.sheet-dock .bchip .av-star path { stroke: var(--float); }
.sheet-dock .campus .none { background: var(--float); border-radius: 999px; padding: 8px 12px; font-size: 13px; }
/* the moment the wheel points at */
.map-when { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 43px; margin-bottom: 7px; }
.map-when .when { margin: 0; min-width: 0; pointer-events: auto; }
/* the wheel, and its Now button right of it: a circle as tall as the wheel on the same glass, dim at now (26 Oct, user:
   "keep the reset button next to the wheel"; until then at the right end of the moment's line, hidden at now) */
.wheel-row { display: flex; align-items: center; gap: 8px; }
.wheel-row .wheel-panel { flex: 1 1 auto; min-width: 0; }
.wheel-row .shift-reset {
  flex: none; width: 66px; height: 66px; min-height: 0; padding: 0; justify-content: center; border: 0; border-radius: 50%;
  color: var(--ink); background: var(--glass); box-shadow: var(--glass-shadow); pointer-events: auto;
  -webkit-tap-highlight-color: transparent;   /* no blue flash on a tap (Android; 26 Oct, user): its arrow turns instead */
}
/* dim at now by the icon's opacity, not its color, so where the arrowhead and the arc overlap they don't add up to a
   darker spot (26 Oct, user; as with the tab icons) */
.wheel-row .shift-reset svg { display: block; transition: opacity .2s; }
.wheel-row .shift-reset:disabled { cursor: default; }
.wheel-row .shift-reset:disabled svg { opacity: .28; }
@media (hover: hover) { .wheel-row .shift-reset:not(:disabled):hover { background: color-mix(in srgb, var(--ink) 12%, var(--glass)); } }
.wheel-row .shift-reset:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* The look-ahead wheel, flat on a 66 px pill (the Figma): notches every 5 min, 8.75 px apart, 1.1 px wide, from a dot
   (nobody on the map) up to 26 px tall, all at half strength, past ones dimmer; TODAY / TOMORROW at the top left of
   each day, the day you're in pinned on the left (app.js loadWheel). The playhead: 3.4 px, 47.5 px tall, white at
   75%, round ends (the Figma, 25 Oct ~23:45); no tail since it sits between the map and the list (26 Oct, the Figma). */
.wheel-panel { position: relative; height: 66px; border-radius: 33px; background: var(--glass); box-shadow: var(--glass-shadow); pointer-events: auto; }
.wheel-panel .look-wheel { height: 66px; border: 0; border-radius: 33px; background: none; }
/* speed lines behind the notches while the wheel points into the future (26 Oct prototype, app.js speedFrame): drawn in
   the ink's color, fading out towards the ends like the notches */
.wheel-panel .speed {
  position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 33px; pointer-events: none; color: var(--ink);
  -webkit-mask-image: linear-gradient(90deg, transparent 10px, #000 44px, #000 calc(100% - 44px), transparent calc(100% - 10px));
  mask-image: linear-gradient(90deg, transparent 10px, #000 44px, #000 calc(100% - 44px), transparent calc(100% - 10px));
}
/* notches fade out 8 to 20 px from the ends; the labels' strip (the top 20 px, just above the tallest notches) only on
   the right, so the pinned day's label stays crisp at the left (two mask layers, added) */
.wheel-panel .law canvas {
  -webkit-mask: linear-gradient(90deg, transparent 8px, #000 20px, #000 calc(100% - 20px), transparent calc(100% - 8px)) 0 0 / 100% 100% no-repeat,
                linear-gradient(90deg, #000 calc(100% - 20px), transparent calc(100% - 8px)) 0 0 / 100% 20px no-repeat;
  mask: linear-gradient(90deg, transparent 8px, #000 20px, #000 calc(100% - 20px), transparent calc(100% - 8px)) 0 0 / 100% 100% no-repeat,
        linear-gradient(90deg, #000 calc(100% - 20px), transparent calc(100% - 8px)) 0 0 / 100% 20px no-repeat;
}
.wheel-panel .law-head { top: 8.75px; bottom: auto; height: 47.5px; width: 3.4px; margin-left: -1.7px; border-radius: 2px; background: color-mix(in srgb, currentColor 75%, transparent); box-shadow: none; }
/* The cards at the top of every page ("Are you in the library?", invites to a group) float under the title on the map,
   out of the way while the list is pulled up */
.top-cards { display: contents; }
body[data-view="friends"] .top-cards { display: flex; flex-direction: column; gap: 10px; position: fixed; z-index: 5; top: calc(var(--title-top) + 54px); left: max(16px, env(safe-area-inset-left, 0px)); right: max(16px, env(safe-area-inset-right, 0px)); max-width: 528px; max-height: calc(100% - var(--title-top) - 54px - var(--tabbar) - var(--tab-pad) - var(--peek) - 230px); overflow-y: auto; transition: opacity .2s, visibility .2s; }
body[data-view="friends"] .here, body[data-view="friends"] .inv { box-shadow: 0 6px 22px rgba(0, 0, 0, .14); }
body.sheet-up .top-cards { opacity: 0; visibility: hidden; }

/* The list's header (the Figma): "13 friends (3 hidden)" and the search button, then the hours over everyone's
   timelines; it sticks under the moment and the wheel while the list scrolls. Search opens in its place. */
.board-head { position: relative; z-index: 12; flex: none; border-bottom: 1px solid var(--line-soft); }
/* its round top corners stay round while it sticks and the rows scroll under it: its background (::after) is rounded,
   with a strip behind the corners (::before: frosted, or the page's color; see .sheet-dock::before). With the list down
   that strip is outside the list's own round corners, so it doesn't show. */
.board-head::after { content: ""; position: absolute; left: 0; right: 0; pointer-events: none; }
.board-head::after { z-index: -1; top: 0; bottom: 0; background: var(--surface); border-radius: 16px 16px 0 0; }
.bh-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 6px 0 14px; min-height: 33px; }
.board-head.searching .bh-top { display: none; }
.friends-count { margin: 0; font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.bh-search { flex: none; width: 40px; height: 40px; margin: -8px 0 -8px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--ink); cursor: pointer; }
.bh-search:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.bh-search:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.board-head .bsearch { border-bottom: 0; padding: 10px 10px 2px 14px; gap: 8px; }
.board-head .q-count:empty { display: none; }
.q-done { flex: none; padding: 8px 6px; border: 0; background: transparent; color: var(--ink); font: 600 15px var(--font-body); cursor: pointer; }
.q-done:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 8px; }
/* the hours: Figtree, bold, at half the ink (the Figma), where the list's own axis row was */
.board-head .brow.axis { position: static; border: 0; background: none; padding: 5px 14px 6px; }
.board-head .axis-track span { font: 700 13px var(--font-body); color: color-mix(in srgb, var(--ink) 50%, transparent); }
.board-head .axis-track span.now { color: var(--live); }
.board.shifted .board-head .axis-track span.now { color: var(--ink); }
#board > .brow:first-child { border-top: 0; }
/* a friend's week (reached from Friends) and your own: the title */
#week-view .page-title { margin-bottom: -12px; }
/* My week: the title stays at the top and the week scrolls under it, blurring away behind it like the map under
   Everyone on Friends (27 Oct, user: "fixed header that displays over the content the same way the friends tab
   Everyone"; the same blur, mask and tint as .map-scrim.top, reaching 92 px below the title's top as there). The blur
   shows only once the page has scrolled (body.head-stuck, app.js headStuck), so the cards at the top of the page
   aren't blurred before that. A friend's week keeps its header in the page. */
#week-h { --head-top: calc(28px + env(safe-area-inset-top, 0px)); position: sticky; z-index: 6; top: var(--head-top); }
#week-h::before {
  content: ""; position: fixed; z-index: -1; top: 0; left: 0; right: 0; height: calc(var(--head-top) + 92px); pointer-events: none;
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  -webkit-mask-image: linear-gradient(#000 25%, transparent); mask-image: linear-gradient(#000 25%, transparent);
  background: color-mix(in srgb, var(--bg) 45%, transparent);
  opacity: 0; transition: opacity .15s;
}
body.head-stuck #week-h::before { opacity: 1; }
body.noblur #week-h::before { -webkit-backdrop-filter: none; backdrop-filter: none; }

/* ---------- Avatars ---------- */
.av {
  width: 36px; height: 36px; border-radius: 50%; flex: none;
  background: var(--pc, #111); color: #fff;
  display: inline-grid; place-items: center; overflow: hidden;
  font-family: var(--font-display); font-weight: 700; font-size: 15px; line-height: 1;
}
.av { position: relative; }
.av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 50%; }
/* a starred friend (map pins, edge avatars, popups and "In class" chips): a star sitting on top of the avatar */
.av.star { overflow: visible; }
.av-star { position: absolute; z-index: 2; left: 50%; top: 0; width: 60%; height: 60%; transform: translate(-50%, -60%); overflow: visible; pointer-events: none; }
.av-star path { fill: var(--star); stroke: var(--surface); stroke-width: 3.2; stroke-linejoin: round; paint-order: stroke; }
.av.sm { width: 22px; height: 22px; font-size: 11px; }

/* ---------- Login ---------- */
.login { display: flex; justify-content: center; }
.login-card {
  width: 100%; max-width: 420px; background: var(--surface); border: 1px solid var(--line); border-radius: 16px;
  padding: 24px; display: flex; flex-direction: column; gap: 16px;
}
.login-lede { margin: -6px 0 0; color: var(--muted); }
.field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 600; color: var(--muted); }
.pw-wrap { display: flex; gap: 8px; }
.field input {
  flex: 1; min-width: 0; font: inherit; font-family: var(--font-mono); font-size: 17px; font-weight: 400; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 11px 12px;
}
.field input:focus { outline: 2px solid var(--strong); outline-offset: 1px; border-color: transparent; }
.pw-show { font: inherit; font-size: 13px; font-weight: 600; color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 0 14px; cursor: pointer; }
.go { font: inherit; font-weight: 700; font-size: 16px; color: var(--strong-ink); background: var(--strong); border: 0; border-radius: 10px; padding: 12px 16px; cursor: pointer; }
.go:disabled { opacity: .6; cursor: progress; }
.go:focus-visible, .pw-show:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.err { margin: 0; color: var(--live); font-weight: 600; min-height: 1.5em; }
.err:empty { min-height: 0; margin-top: -16px; }

/* Signing in with a phone number, signing up (3 Nov 2026; app.js "Phone sign-in and sign-up") */
.login { flex-direction: column; align-items: center; gap: 14px; }
.login-inv { width: 100%; max-width: 420px; }
.login-alt { align-self: center; font: inherit; font-size: 14px; font-weight: 600; color: var(--muted); background: none; border: 0; padding: 6px 8px; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, var(--muted) 40%, transparent); }
.login-alt:disabled { text-decoration: none; cursor: default; opacity: .7; }
.login-alt:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 6px; }
.login-row { display: flex; justify-content: space-between; gap: 8px; margin-top: -6px; }
.login-lede b { color: var(--ink); font-weight: 600; }
.field select {
  font: inherit; font-size: 17px; font-weight: 400; color: var(--ink); background: var(--bg); border: 1px solid var(--line);
  border-radius: 10px; padding: 11px 12px; min-height: 46px;
}
.field select:focus { outline: 2px solid var(--strong); outline-offset: 1px; border-color: transparent; }
.su-top { display: flex; align-items: flex-end; gap: 14px; }
.su-name { flex: 1; min-width: 0; }
.su-photo {
  position: relative; flex: none; width: 72px; height: 72px; border-radius: 50%; padding: 0; cursor: pointer; overflow: hidden;
  background: color-mix(in srgb, var(--ink) 7%, transparent); border: 1.5px dashed color-mix(in srgb, var(--ink) 30%, transparent);
  display: grid; place-items: center; color: var(--muted); -webkit-tap-highlight-color: transparent;
}
.su-photo svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.su-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: none; }
.su-photo.has { border-style: solid; border-color: transparent; }
.su-photo.has img { display: block; }
.su-photo.has svg { display: none; }
.su-photo:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.su-photo-note { margin: -8px 0 0; font-size: 13px; color: var(--muted); }
.su-friend { align-items: flex-start; font-size: 15px; line-height: 1.35; }
.su-friend input { margin-top: 1px; }
.su-friend b { font-weight: 700; }
/* "Ana invited you": on the sign-in screen and the install page */
.inv-who { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px; background: color-mix(in srgb, #127DFF 10%, var(--surface)); }
.inv-who p { margin: 0; font-size: 15px; }
.inv-who b { font-weight: 700; }
.inv-av { width: 40px; height: 40px; flex: none; }
.gate-inv { display: flex; flex-direction: column; gap: 10px; }
.hold { display: flex; flex-direction: column; gap: 8px; margin: 0; }
.hold-row { display: flex; gap: 8px; }
.hold-row input { flex: 1; min-width: 0; font: inherit; font-family: var(--font-mono); font-size: 16px; color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 9px 12px; }
.gate-note.ok, #hold-msg.ok { color: var(--ink); }
#hold-msg:empty { display: none; }

/* ---------- Install screen (a phone's browser tab: the app opens only once installed) ---------- */
.gate { display: flex; justify-content: center; }
.gate-card {
  width: 100%; max-width: 420px; background: var(--surface); border: 1px solid var(--line); border-radius: 16px;
  padding: 24px; display: flex; flex-direction: column; gap: 18px;
}
.gate-lede { margin: -8px 0 0; color: var(--muted); }
.gate-lede b, .gate-note b { color: var(--ink); font-weight: 600; }
.gate .install-steps { margin: 0; }
.gate .go { display: block; text-align: center; text-decoration: none; }
.gate-note { margin: 0; font-size: 13.5px; color: var(--muted); }
.gate h2 { display: flex; align-items: center; gap: 12px; }
.gate-spin { width: 20px; height: 20px; flex: none; border-radius: 50%; border: 2.5px solid var(--line); border-top-color: var(--ink); animation: gate-spin .8s linear infinite; }
@keyframes gate-spin { to { transform: rotate(360deg); } }
.gate-link { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 7px 7px 12px; background: var(--bg); border: 1px solid var(--line); border-radius: 10px; }
.gate-link span { font-size: 14px; overflow-wrap: anywhere; -webkit-user-select: all; user-select: all; }
.gate-copy { font: inherit; font-size: 13px; font-weight: 600; color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; cursor: pointer; flex: none; }
.gate-copy:focus-visible, .gate-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.gate-extra { grid-column: 2; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.gate-extra .go, .gate-extra .gate-link { align-self: stretch; }
.gate-btn { display: inline-block; font: inherit; font-size: 14px; font-weight: 600; color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 7px 14px; text-decoration: none; }
@media (max-width: 680px) { .gate-card { padding: 20px; } }

.switch { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; user-select: none; }
.switch input { appearance: none; -webkit-appearance: none; flex: none; width: 36px; height: 20px; margin: 0; border-radius: 999px; background: var(--line); position: relative; cursor: pointer; transition: background-color .15s; }
.switch input::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--surface); box-shadow: 0 1px 2px rgba(0, 0, 0, .25); transition: transform .15s; }
.switch input:checked { background: var(--strong); }
.switch input:checked::after { transform: translateX(16px); background: #fff; }   /* (white on the black track: in the dark the surface's color hid it; 28 Oct) */
.switch input:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.preview { margin: 0; align-self: flex-start; font-size: 13px; font-weight: 600; color: var(--live); border: 1px solid var(--live); border-radius: 999px; padding: 3px 12px; }

/* ---------- Subject marks ---------- */
.ic { width: 14px; height: 14px; flex: none; vertical-align: -2px; margin-right: 5px; }
.subj { color: var(--c-text); white-space: nowrap; }
[data-clang="he"] .subj { white-space: normal; }   /* the official Hebrew names can be wider than a phone */
.sw { width: 12px; height: 12px; border-radius: 3px; flex: none; background: var(--c); }
/* the week's legend: a lecture's block is plain, a practice's striped (no outlines or top edges since 27 Oct) */
.sw.lec { background: color-mix(in srgb, var(--muted) 40%, transparent); }
.sw.prac { background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--muted) 55%, transparent) 0 1.5px, transparent 1.5px 4px); }
/* workshops, fieldwork, projects and other kinds (29 Oct 2026): dotted */
.sw.hands { background: radial-gradient(circle, color-mix(in srgb, var(--muted) 75%, transparent) 1px, transparent 1.5px) 0 0 / 4px 4px; }

/* ---------- Now: header ---------- */
/* Today's title (the user's Figma, 26 Oct): the weekday as the page title (36 px), 2 px, then the date in bold and the
   semester week; 24 px down to the cards (the page's gap is 36 px, on phones 30 px: see the end) */
.today-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: -12px; }
.t-meta { margin: 0; color: var(--muted); font-size: 14px; line-height: 21px; display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; overflow: hidden; }
.t-meta b { font-weight: 700; margin-inline-end: 4px; }
/* the day's summary after the semester week, "· 4 classes, until 18:00", in one piece; its dot sits in the gap before
   it, so when it wraps onto a line of its own the dot is left of the line and cut off (.t-meta's overflow) */
.t-meta .t-sum { position: relative; white-space: nowrap; }
.t-meta .t-sum::before { content: '·'; position: absolute; left: -12px; width: 12px; text-align: center; }
/* BGU's calendar for the day (calendar.js, 27 Oct): a quiet filled box under the date line, a line per thing; 16 px
   to the first card (24 less 8), the same as from the cards to the minigame under them (user: "even") */
.t-note { margin: 10px 0 -8px; padding: 9px 14px; border-radius: 14px; background: color-mix(in srgb, var(--ink) 6%, transparent); color: var(--ink); font-size: 14px; line-height: 20px; }
.t-note[hidden] { display: none; }
.t-note-l { display: block; }
.t-note b { font-weight: 700; }
/* only for screen readers (a heading the design leaves out) */
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---------- Now: your cards ---------- */
#me-now { display: flex; flex-direction: column; gap: 12px; }
.now-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: 12px; }
/* a class (or an exam) as a card: the course's fill, no outline (the user's Figma, 26 Oct; a colored top edge and an
   outline before) */
.ncard {
  min-width: 0; border-radius: 14px; padding: 18px 16px 16px;
  background: var(--c-fill); border: 1px solid color-mix(in srgb, var(--c) 45%, transparent);   /* the outline back, user, 26 Oct evening (no top edge) */
  display: flex; flex-direction: column; gap: 3px;
}
.ncard .cd { color: color-mix(in srgb, var(--ink) 50%, transparent); }
.nwhen { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin-bottom: 4px; font-size: 13px; }
.st { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--c-text); }
.st.live { color: var(--live); }
.st .now-ic { flex: none; display: block; }   /* the Friends list's Now: a still clock (app.js NOW_IC) */
.cd { color: var(--muted); }
.ncard h3 { margin: 0; font-family: var(--font-display); font-size: 20px; font-weight: 700; line-height: 1.15; color: var(--c-text); text-wrap: balance; }
.nk { margin: 0; font-size: 14px; font-weight: 600; color: var(--c-text); }
.nroom { margin: 6px 0 0; font-size: 18px; font-weight: 500; color: var(--ink); }
.nwho { margin: 0; font-family: var(--font-he); font-size: 13px; color: var(--muted); }
.ntags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
/* Will go / won't go on Today's cards (2 Nov 2026, Timur; app.js attendHTML): two small pills, the answer filled in the
   class's colour; the Friends list shows it as a tag (.st.att) */
.natt { display: flex; gap: 6px; margin-top: 10px; }
.natt-b {
  font: 600 12px/1 var(--font-body); padding: 7px 12px; border-radius: 999px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--c) 50%, transparent); background: transparent; color: var(--c-text);
}
.natt-b.on { background: var(--c); border-color: var(--c); color: #fff; }
.natt-b:focus-visible { outline: 2px solid var(--c); outline-offset: 2px; }
.ncard.done .natt { display: none; }
/* att-go, not go: .go is the sign-in screen's black button (3 Nov 2026, Timur: the tag looked like a button) */
.st.att-skip { color: var(--muted); }
.st.att-go { color: var(--p-green); }
.ntag { font-size: 11.5px; font-weight: 600; padding: 2px 8px; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--c) 50%, transparent); color: var(--c-text); }
.prog { display: block; height: 4px; margin-top: 10px; border-radius: 2px; overflow: hidden; background: color-mix(in srgb, var(--c) 22%, transparent); }
.prog i { display: block; height: 100%; border-radius: 2px; background: var(--c); }
.empty { list-style: none; background: var(--surface); border-radius: 14px; padding: 17px; display: flex; flex-direction: column; gap: 4px; }
.empty b { font-family: var(--font-display); font-size: 18px; font-weight: 700; }
.empty span { color: var(--muted); }
/* Today with no courses yet (app.js renderDay, NONE_ILL) */
.empty.none { align-items: center; text-align: center; padding: 22px 18px 20px; gap: 6px; }
.empty.none span { max-width: 32ch; text-wrap: pretty; }
.none-gif { display: block; width: 160px; height: auto; margin: -4px 0 6px; }
.t-add { margin-top: 10px; display: inline-flex; align-items: center; gap: 8px; text-decoration: none; }
.t-add svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }

/* ---------- Now: who is in which building ---------- */
.shift { display: flex; flex-direction: column; gap: 10px; background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 10px 16px 16px; }
.shift-top { display: flex; align-items: center; gap: 12px; min-height: 34px; }
.shift-label { flex: 1 1 auto; font-size: 12px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.shift-label.on { color: var(--ink); }   /* how far ahead the wheel is, in place of "Look ahead" */
.shift-reset { display: inline-flex; align-items: center; gap: 6px; flex: none; min-height: 34px; padding: 6px 12px 6px 10px; font: inherit; font-size: 13px; font-weight: 600; color: var(--ink); background: transparent; border: 1px solid var(--line); border-radius: 999px; cursor: pointer; }
.shift-reset[hidden] { display: none; }
.shift-reset:hover { border-color: var(--muted); }
.shift-reset:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* the look-ahead wheel: look-ahead-wheel.js draws it in `color` and adds its own styles (.law); these set its colors per theme */
.look-wheel { --law-edge: var(--wheel-edge); --law-mid: var(--wheel-mid); --law-line: var(--line); --law-accent: var(--ink); height: 60px; color: var(--ink); border-radius: 12px; }
.board.shifted .track::before { background: var(--ink); }
.board.shifted .axis-track span.now { color: var(--ink); }
.campus { position: relative; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; align-content: flex-start; }   /* lines stay at the top when the row keeps its height (renderCampus) */
.bchip { display: inline-flex; align-items: center; gap: 8px; background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 4px 6px 4px 12px; font-size: 13px; }
.bchip b { font-family: var(--font-mono); font-weight: 500; }
.bchip b.pl { font-family: var(--font-body); font-weight: 600; }   /* a place: "📚 Library" */
.bchip .avs { position: relative; display: inline-flex; }
.bchip .avs .av { box-shadow: 0 0 0 2px var(--surface); }
.bchip .avs .av + .av { margin-left: -6px; }
button.bchip { font: inherit; font-size: 13px; color: var(--ink); cursor: pointer; }
button.bchip:hover { border-color: var(--muted); }
button.bchip:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.campus .none { color: var(--muted); font-size: 14px; }

/* ---------- Everyone: the 3D campus map ----------
   The map page's own look (its colors, Barlow Condensed numbers, square buttons), kept inside .m3d.
   --ground: around the campus, the colour at the edge of the ground image (campus/ground-light.webp, ground-dark.webp),
   so the map's edges blend in; --map-dark: which ground image map3d.js shows (1 = dark). */
.m3d {
  --paper: #F4F5F1; --ink: #1C2228; --muted: #59626A; --rule: #CDD3CA; --ground: #F7F7F7; --route: #2140E3; --map-dark: 0;
  --gate-chip: rgba(196, 98, 18, 0.86); --gate-ink: #FFFFFF; --chip: rgba(28, 34, 40, 0.6); --chip-ink: #FFFFFF;
  --btn: #F5F5F5; --btn-ink: #1F1F1F; --btn-line: #D4D4D4; --btn-hover: #8A8A8A; --btn-on: #3D3D3D; --btn-on-ink: #FFFFFF;   /* buttons: neutral grays */
  --f-display: "Barlow Condensed", "Arial Narrow", "Roboto Condensed", sans-serif;
  --f-body: "IBM Plex Sans Hebrew", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --f-mono: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
  position: relative; height: min(78vh, 720px); min-height: 360px; overflow: hidden;
  border: 1px solid var(--line); border-radius: 16px; background: var(--ground);
  font-family: var(--f-body); font-size: 14px; line-height: 1.45; color: var(--ink);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .m3d {
    --paper: #13181D; --ink: #E4E8EB; --muted: #98A2AB; --rule: #2B343C; --ground: #373737; --route: #8A9BFF; --map-dark: 1;
    --chip: rgba(10, 13, 16, 0.6); --chip-ink: #F1F3F5; --gate-chip: rgba(227, 149, 82, 0.9); --gate-ink: #1B1209;
    --btn: #262626; --btn-ink: #E5E5E5; --btn-line: #404040; --btn-hover: #8A8A8A; --btn-on: #D4D4D4; --btn-on-ink: #171717;
  }
}
:root[data-theme="dark"] .m3d {
  --paper: #13181D; --ink: #E4E8EB; --muted: #98A2AB; --rule: #2B343C; --ground: #373737; --route: #8A9BFF; --map-dark: 1;
  --chip: rgba(10, 13, 16, 0.6); --chip-ink: #F1F3F5; --gate-chip: rgba(227, 149, 82, 0.9); --gate-ink: #1B1209;
  --btn: #262626; --btn-ink: #E5E5E5; --btn-line: #404040; --btn-hover: #8A8A8A; --btn-on: #D4D4D4; --btn-on-ink: #171717;
}
.m3d .stage { position: absolute; inset: 0; touch-action: none; user-select: none; -webkit-user-select: none; }
.m3d .stage canvas { display: block; width: 100%; height: 100%; outline: none; opacity: 0; transition: opacity 360ms ease-out; }
.m3d.drawn .stage canvas { opacity: 1; }   /* the map's first frame fades in (map3d.js) */
.m3d .stage.pointing canvas { cursor: pointer; }
.m3d .poster img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: 100%; object-fit: contain; pointer-events: none; }   /* only when the 3D map can't start, or has lost its graphics context */
.m3d.lost .stage canvas, .m3d.lost .labels { visibility: hidden; }   /* (map3d.js: the context lost; the poster shows until it comes back) */
/* "Loading…" (or why the 3D map couldn't start): plain text on white in the light, black in the dark, at 50%, no
   border (27 Oct, user: "minimalistic"); halfway between the Everyone title and the "In class" pill, not the middle of
   the screen behind the sheet (app.js placeMapStatus sets its top) */
.m3d .status {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); max-width: min(360px, 80%);
  padding: 8px 14px; border-radius: 18px; background: color-mix(in srgb, var(--float) 50%, transparent); color: var(--ink);
  font-family: var(--font-body); font-size: 13px; line-height: 1.4; text-align: center;
}
/* building numbers float over the model; they and the pins fade in once the buildings have risen (.revealing) */
.m3d .labels { position: absolute; inset: 0; pointer-events: none; overflow: hidden; transition: opacity 420ms ease-out; }
.m3d.revealing .labels { opacity: 0; }
.m3d .lbl {
  position: absolute; left: 0; top: 0; pointer-events: none;
  font: 700 14px/1 var(--f-display); letter-spacing: 0.02em; color: var(--chip-ink); background: var(--chip);
  border: 0; border-radius: 3px; padding: 3px 5px 2px; white-space: nowrap; will-change: transform;
}
.m3d .lbl.part { font-weight: 600; font-size: 13px; }
.m3d .lbl.ncamp { background: transparent; color: #FFFFFF; text-shadow: 0 0 3px #000, 0 0 6px rgba(0, 0, 0, 0.7); }
.m3d .lbl.gate { background: var(--gate-chip); color: var(--gate-ink); padding: 3px 4px; line-height: 0; cursor: default; }
.m3d .lbl.gate svg { display: block; width: 15px; height: 15px; }
.m3d .lbl.off, .m3d .m-pin.off { visibility: hidden; }
/* friends in class: a pin of avatars beside the building's number */
.m3d .pins { position: absolute; inset: 0; }
/* the dust of someone whose last class of the day has ended (map3d.js crumble), over the pins */
.m3d .m-dust { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.m3d .m-pin {
  position: absolute; left: 0; top: 0; pointer-events: none; will-change: transform;
  display: inline-flex; padding: 3px; background: var(--surface); border-radius: 999px;
  box-shadow: 0 0 0 1px var(--line), 0 2px 6px rgba(0, 0, 0, .22);
}
/* the tail (28 Oct, the Figma's shape: map3d.js TAIL_SVG): from the pill's left side (right side on a .flip pin) to its
   tip 5.55 px out; the shape sits 1 px closer than the Figma's (its sides end on the pill's edge) because its outline is
   drawn outside it and so runs on into the pill's line without a step. A pin grows out of and shrinks into that tip
   (transform-origin; map3d.js popPin and the liquid; its place is its `translate`, so `scale` works about the tip). */
.m3d .m-pin { transform-origin: -5.5527px 50%; }
.m3d .m-pin.flip { transform-origin: calc(100% + 5.5527px) 50%; }
.m3d .m-tail { position: absolute; left: -5.7527px; top: 50%; width: 8px; height: 11.979px; margin-top: -5.9896px; overflow: visible; pointer-events: none; }
.m3d .m-pin.flip .m-tail { left: auto; right: -5.7527px; transform: scaleX(-1); }
.m3d .m-tail .ring { fill: none; stroke: var(--line); stroke-width: 2; }
.m3d .m-tail .fill { fill: var(--surface); }
.m3d .m-pin .av { position: relative; z-index: 1; width: 26px; height: 26px; font-size: 12px; box-shadow: 0 0 0 2px var(--surface); }
.m3d .m-pin .av + .av { margin-left: -6px; }
.m3d .m-pin .av.me { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--ink); }
/* people walking between classes (28 Oct 2026; map3d.js, Walking): a drop like a pin, without its pointer, moving along
   the walkways; while it leaves or joins a pin, both draw no background and the liquid shape under them does (.m-goo) */
.m3d .m-walk { position: absolute; left: 0; top: 0; pointer-events: none; will-change: transform; }
.m3d .m-walk.off, .m3d .m-pin.empty { visibility: hidden; }
.m3d .m-wb {
  display: inline-flex; padding: 3px; background: var(--surface); border-radius: 999px;
  box-shadow: 0 0 0 1px var(--line), 0 2px 6px rgba(0, 0, 0, .22);
}
.m3d .m-wb .av { position: relative; z-index: 1; width: 26px; height: 26px; font-size: 12px; box-shadow: 0 0 0 2px var(--surface); }
.m3d .m-wb .av + .av { margin-left: -6px; }
.m3d .m-wb .av.me { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--ink); }
.m3d .m-walk.goo .m-wb, .m3d .m-pin.goo { background: transparent; box-shadow: none; }
.m3d .m-pin .av.gap { visibility: hidden; flex: none; }
/* 4 avatars at most, then "+n" (2 Nov 2026, Timur; map3d.js capRow): the rest stay in the row, hidden, and the chip,
   an avatar's size, sits under the last avatar's right edge as the avatars overlap */
.m3d :is(.m-pin, .m-wb) > .av.over { display: none; }
.m3d .m-more {
  position: relative; z-index: 0; flex: none; width: 26px; height: 26px; border-radius: 50%; margin-left: -6px;
  display: inline-grid; place-items: center; padding-left: 3px; box-sizing: border-box;
  background: var(--line-soft); color: var(--ink); box-shadow: 0 0 0 2px var(--surface);
  font: 700 11px/1 var(--font-display); letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.m3d .m-more[hidden] { display: none; }
.m3d :is(.m-pin, .m-wb) > .m-more:first-child, .m3d .m-pin > .m-tail + .m-more { margin-left: 0; padding-left: 0; }
/* on campus now (29 Oct, Timur: "add to the people who are on campus a green dot in the right bottom corner of their
   avatar on the map bubble"; app.js onNow): the dot sits on the avatar's circle at 45°, ringed in the bubble's colour.
   So that it shows, each avatar lies over the one to its right (Timur: "we also need to change the avatars order (so
   that the leftmost is on top)"): z-index by place from the end (nth-last-child, so it holds while avatars come, go
   and leave gaps); beyond 19 from the end all alike. */
.m3d :is(.m-pin, .m-wb) > .av { z-index: 20; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(1) { z-index: 1; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(2) { z-index: 2; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(3) { z-index: 3; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(4) { z-index: 4; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(5) { z-index: 5; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(6) { z-index: 6; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(7) { z-index: 7; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(8) { z-index: 8; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(9) { z-index: 9; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(10) { z-index: 10; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(11) { z-index: 11; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(12) { z-index: 12; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(13) { z-index: 13; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(14) { z-index: 14; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(15) { z-index: 15; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(16) { z-index: 16; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(17) { z-index: 17; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(18) { z-index: 18; }
.m3d :is(.m-pin, .m-wb) > .av:nth-last-child(19) { z-index: 19; }
.m3d :is(.m-pin, .m-wb) .av.oncampus { overflow: visible; }
.m3d :is(.m-pin, .m-wb) .av.oncampus::after {
  content: ''; position: absolute; z-index: 3; right: -1px; bottom: -1px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--p-green); box-shadow: 0 0 0 1.5px var(--surface); pointer-events: none;
}
@media (max-width: 860px) { .m3d :is(.m-pin, .m-wb) .av.oncampus::after { width: 8px; height: 8px; } }
.m3d .m-goo { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.m3d .m-goo .goo-fill { flood-color: var(--surface); }
.m3d .m-goo .goo-line { flood-color: var(--line); }
/* your location (the phone's GPS), only on campus */
.m3d .m-me { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.m3d .m-me.off { visibility: hidden; }
.m3d .m-me i { position: absolute; border-radius: 50%; }
.m3d .m-me .acc { left: calc(var(--r, 0px) * -1); top: calc(var(--r, 0px) * -1); width: calc(var(--r, 0px) * 2); height: calc(var(--r, 0px) * 2); background: rgba(10, 132, 255, .16); border: 1px solid rgba(10, 132, 255, .45); }
.m3d .m-me.noacc .acc { display: none; }
.m3d .m-me .dot { left: -7px; top: -7px; width: 14px; height: 14px; background: #0A84FF; box-shadow: 0 0 0 2.5px #FFFFFF, 0 1px 5px rgba(0, 0, 0, .45); }
/* map chrome */
.m3d .tools { position: absolute; top: 44px; right: 10px; display: flex; flex-direction: column; gap: 6px; }   /* below the zoom readout */
.m3d .tools button[hidden], .m3d .zoom[hidden] { display: none; }
.m3d .tools button { font: 600 13px/1 var(--f-body); color: var(--btn-ink); background: var(--btn); border: 1px solid var(--btn-line); border-radius: 4px; cursor: pointer; }
.m3d .tools button { width: 34px; height: 34px; font-size: 18px; display: grid; place-items: center; padding: 0; }
.m3d .tools button.txt { width: auto; min-width: 34px; padding: 0 8px; font-size: 12px; height: 28px; }
.m3d .tools button[aria-pressed="true"] { background: var(--btn-on); color: var(--btn-on-ink); border-color: var(--btn-on); }
.m3d .tools button:hover { border-color: var(--btn-hover); }
.m3d button:focus-visible { outline: 2px solid var(--btn-hover); outline-offset: 2px; }
/* North and the zoom in one control (26 Oct, user: "combine the north and zoom button (pressing on it should reset both)";
   the Figma's "North", node 28:3894): the north arrow, which turns with the map and leans back as it tilts (map3d.js), and
   the zoom beside it, in IBM Plex Sans Hebrew 12 px semibold, no box. #E5E5E5 in the dark as drawn, the map's dark gray
   (--btn-ink) in the light. A tap faces north, looks straight down and goes back to 100%. The arrow is the Figma's own
   file used as a mask, so it takes the text's color. */
.m3d .north {
  position: absolute; top: 10px; right: 10px; box-sizing: border-box; height: 40px; padding: 0 8px; display: flex; align-items: center; gap: 4px;
  font: 600 12px/12px "IBM Plex Sans Hebrew", var(--font-body); font-variant-numeric: tabular-nums; white-space: nowrap;
  color: var(--btn-ink); background: none; border: 0; border-radius: 4px; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.m3d .north:active { opacity: .6; }
.m3d .north .arrow {
  flex: none; width: 12px; height: 16px; background: currentColor; transition: transform 80ms linear;
  -webkit-mask: url(icons/north-arrow.svg) center / 12px 16px no-repeat; mask: url(icons/north-arrow.svg) center / 12px 16px no-repeat;
}
.m3d .help { position: absolute; left: 10px; bottom: 10px; font-size: 11px; color: var(--btn-ink); background: var(--btn); border: 1px solid var(--btn-line); border-radius: 3px; padding: 3px 7px; pointer-events: none; }
.m3d .tip {
  position: absolute; pointer-events: none; padding: 5px 8px; border-radius: 3px;
  background: var(--ink); color: var(--paper); font-size: 12px; transform: translate(-50%, calc(-100% - 14px));
  /* long names wrap (26 Oct, user request): as wide as the text, up to 220 px, whatever side of the map it opens on */
  width: max-content; max-width: min(220px, calc(100vw - 24px)); overflow-wrap: break-word;
}
.m3d .tip-title { display: flex; align-items: baseline; gap: 4px; }
.m3d .tip-title span { min-width: 0; }
.m3d .tip b { font-family: var(--f-display); font-size: 14px; letter-spacing: 0.02em; flex: none; }
.m3d .tip.below { transform: translate(-50%, 18px); }
/* a gate's popup (2 Nov 2026): name, Hebrew name, open or closed at the map's moment (no coloured dot: Timur, "Remove the
   green/red dot"), the week's hours (today's line brighter) */
.m3d .tip.gate-tip { width: 196px; padding: 7px 10px 8px; }
.m3d .tip.gate-tip .tip-title { font-weight: 700; font-size: 13px; }
.m3d .tip .tip-he { opacity: .6; margin-top: 1px; }
.m3d .tip .tip-gst { margin-top: 6px; font-weight: 600; }
.m3d .tip .tip-gst .tip-state { display: block; }
.m3d .tip .tip-gst .tip-at { display: block; font-weight: 500; opacity: .6; }
.m3d .tip .tip-hours { margin-top: 6px; padding-top: 6px; display: grid; gap: 2px; border-top: 1px solid color-mix(in srgb, var(--paper) 22%, transparent); font-family: var(--f-mono); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.m3d .tip .tip-hours div { display: flex; justify-content: space-between; gap: 12px; opacity: .6; }
.m3d .tip .tip-hours div.on { opacity: 1; font-weight: 600; }
.m3d .tip .tip-note { margin-top: 5px; font-size: 10.5px; line-height: 1.3; opacity: .5; }
.m3d .tip .tip-who { margin: 6px 0 1px; padding: 7px 0 0; display: grid; gap: 8px; border-top: 1px solid color-mix(in srgb, var(--paper) 22%, transparent); }
/* one block per room: the room, then its people; a line between blocks */
.m3d .tip .tip-group { display: grid; gap: 6px; }
.m3d .tip .tip-group + .tip-group { border-top: 1px solid color-mix(in srgb, var(--paper) 22%, transparent); padding-top: 8px; }
.m3d .tip .tip-room { font-family: var(--f-mono); font-size: 11.5px; opacity: .7; }

/* A room entered by hand that the course catalogue doesn't confirm: a "?" in a ring after it (in the text's color,
   wherever the room is), with a bigger tap area than it looks; a tap opens .catpop with what the catalogue lists.
   The ring and the "?" are one drawing (a mask), so the "?" sits in the middle of the ring whatever the font, and
   the ring's middle is at half the height of a capital or a digit of the text around it (.35em above the baseline:
   IBM Plex's capitals are 0.7 em tall). Open, the ring fills in with the "?" cut out of it. */
.catq {
  --q: max(13px, .92em);
  position: relative; display: inline-block; width: var(--q); height: var(--q);
  vertical-align: calc(.35em - var(--q) / 2); margin-inline-start: .3em; padding: 0;
  font-size: inherit; color: inherit; background: none; border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.catq::before {
  content: ''; position: absolute; inset: 0; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='7.25' fill='none' stroke='%23000' stroke-width='1.3'/%3E%3Cpath d='M5.7 6.3a2.3 2.3 0 1 1 4.06 1.48C9.1 8.5 8 8.9 8 9.9' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='11.9' r='.9'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='7.25' fill='none' stroke='%23000' stroke-width='1.3'/%3E%3Cpath d='M5.7 6.3a2.3 2.3 0 1 1 4.06 1.48C9.1 8.5 8 8.9 8 9.9' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='11.9' r='.9'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}
.catq[aria-expanded="true"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cmask id='m'%3E%3Crect width='16' height='16' fill='%23fff'/%3E%3Cpath d='M5.7 6.3a2.3 2.3 0 1 1 4.06 1.48C9.1 8.5 8 8.9 8 9.9' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='11.9' r='.9'/%3E%3C/mask%3E%3Ccircle cx='8' cy='8' r='7.9' mask='url(%23m)'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cmask id='m'%3E%3Crect width='16' height='16' fill='%23fff'/%3E%3Cpath d='M5.7 6.3a2.3 2.3 0 1 1 4.06 1.48C9.1 8.5 8 8.9 8 9.9' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='11.9' r='.9'/%3E%3C/mask%3E%3Ccircle cx='8' cy='8' r='7.9' mask='url(%23m)'/%3E%3C/svg%3E");
}
.catq::after { content: ''; position: absolute; inset: -10px -8px; }
span.catq { cursor: inherit; }   /* the map's building popup: only the sign, nothing to tap */
span.catq::after { content: none; }
.catpop {
  position: fixed; z-index: 90; max-width: min(280px, calc(100vw - 24px)); padding: 10px 13px;
  font: 500 13.5px/1.4 var(--font-body); color: var(--ink); background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
}
.catpop::before {
  content: ''; position: absolute; top: -6px; left: calc(var(--tail, 50%) - 6px); width: 10px; height: 10px;
  background: var(--surface); border: solid var(--line); border-width: 1px 0 0 1px; transform: rotate(45deg);
}
.catpop.above::before { top: auto; bottom: -6px; border-width: 0 1px 1px 0; }
.catpop[hidden] { display: none; }
.m3d .tip .tip-who ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.m3d .tip .tip-who li { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; }
.m3d .tip .tip-who .av { box-shadow: 0 0 0 1.5px var(--paper); }
.m3d .tip .tg-short { font-weight: 500; opacity: .5; }
/* a clicked or tapped popup stays open and its people can be picked */
.m3d .tip.pinned { pointer-events: auto; }
.m3d .tip.pinned .tip-who li { margin: 0 -6px; padding: 2px 6px; border-radius: 4px; cursor: pointer; }
.m3d .tip.pinned .tip-who li:hover { background: color-mix(in srgb, var(--paper) 14%, transparent); }
.m3d .tip.pinned .tip-who li:focus-visible { outline: 2px solid var(--paper); outline-offset: 0; }
/* a list too tall for the map scrolls (placeTip caps its height to the room left). It reaches 6px past the
   sides so the rows' hover background isn't clipped; the separator becomes a background line that stays put. */
.m3d .tip .tip-who.scroll {
  margin-left: -6px; margin-right: -6px; padding: 8px 6px 2px; border-top: 0;
  background: linear-gradient(color-mix(in srgb, var(--paper) 22%, transparent), color-mix(in srgb, var(--paper) 22%, transparent)) 6px 0 / calc(100% - 12px) 1px no-repeat;
  overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--paper) 35%, transparent) transparent; scrollbar-gutter: stable;
}
.m3d .tip.pinned .tip-who.scroll li:focus-visible { outline-offset: -2px; }
/* faded edges where there is more to scroll to (the top fade starts under the separator line) */
.m3d .tip .tip-who.more-down { -webkit-mask-image: linear-gradient(#000 calc(100% - 28px), transparent); mask-image: linear-gradient(#000 calc(100% - 28px), transparent); }
.m3d .tip .tip-who.more-up { -webkit-mask-image: linear-gradient(#000 0 1px, transparent 1px, #000 22px); mask-image: linear-gradient(#000 0 1px, transparent 1px, #000 22px); }
.m3d .tip .tip-who.more-up.more-down {
  -webkit-mask-image: linear-gradient(#000 0 1px, transparent 1px, #000 22px, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(#000 0 1px, transparent 1px, #000 22px, #000 calc(100% - 28px), transparent);
}
/* off-screen people: half-size avatars on the map's edge, with the pin's white border */
.m3d .m-edge {
  position: absolute; left: 0; top: 0; pointer-events: none; will-change: transform;
  display: inline-flex; padding: 1.5px; background: var(--surface); border-radius: 999px;
  box-shadow: 0 0 0 1px var(--line), 0 1px 4px rgba(0, 0, 0, .22);
}
.m3d .m-edge .av { width: 13px; height: 13px; font-size: 6.5px; box-shadow: none; }
.m3d .m-edge.me { box-shadow: 0 0 0 1.5px var(--ink), 0 1px 4px rgba(0, 0, 0, .22); }
.m3d .m-edge.off { visibility: hidden; }
@media (max-width: 860px) {
  .m3d { height: 62vh; min-height: 360px; }
  .m3d .help { display: none; }
  .m3d .tools { top: auto; bottom: 10px; flex-direction: row; flex-wrap: wrap; justify-content: flex-end; left: 54px; }
  .m3d .tools button.txt { height: 34px; }
}
@media (max-width: 680px) {
  .m3d {
    margin-left: calc(-1 * max(16px, env(safe-area-inset-left, 0px))); margin-right: calc(-1 * max(16px, env(safe-area-inset-right, 0px)));
    border-radius: 0; border-left: 0; border-right: 0;
  }
}
@media (max-width: 860px) {
  .m3d .m-pin { padding: 2px; }
  .m3d .m-pin .av { width: 22px; height: 22px; font-size: 10.5px; }
  .m3d .m-pin .av + .av { margin-left: -5px; }
  .m3d .m-wb { padding: 2px; }
  .m3d .m-wb .av { width: 22px; height: 22px; font-size: 10.5px; }
  .m3d .m-wb .av + .av { margin-left: -5px; }
  .m3d .m-more { width: 22px; height: 22px; margin-left: -5px; font-size: 10px; }
  .m3d .m-edge .av { width: 11px; height: 11px; font-size: 5.5px; }
}
@media (prefers-reduced-motion: reduce) { .m3d .stage canvas, .m3d .labels, .m3d .north .arrow { transition: none; } }

/* ---------- Now: everyone, next 3 hours ---------- */
.board { background: var(--surface); border: 1px solid var(--line); border-radius: 16px; overflow: hidden; overflow: clip; }
.brow { position: relative; display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr) 28px; gap: 8px 20px; padding: 14px 16px; border-top: 1px solid var(--line-soft); align-items: center; }
/* the whole row opens that person's week */
.brow[data-href] { cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background-color 120ms; }
@media (hover: hover) {
  .brow[data-href]:hover { background: color-mix(in srgb, var(--ink) 3.5%, var(--surface)); }
  .brow.me[data-href]:hover { background: color-mix(in srgb, var(--strong) 10%, var(--surface)); }
}
.brow[data-href]:active { background: color-mix(in srgb, var(--ink) 7%, var(--surface)); }
.brow.axis { border-top: 0; padding-block: 12px 2px; }
.brow.me { background: color-mix(in srgb, var(--strong) 6%, var(--surface)); }
.brow.flash { animation: rowflash 1.8s ease-out; }
@keyframes rowflash { from { background: color-mix(in srgb, var(--ink) 14%, var(--surface)); } }
.bwho { display: grid; grid-template-columns: 36px minmax(0, 1fr); gap: 0 12px; align-items: start; min-width: 0; color: inherit; text-decoration: none; }
.bwho a { color: inherit; text-decoration: none; }
.bwho .bav { display: block; }
.bname a:hover b { text-decoration: underline; text-underline-offset: 3px; }
.bwho a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 6px; }
.tg { font-size: 12.5px; font-weight: 500; color: var(--muted); text-decoration: none; overflow-wrap: anywhere; }
.bwho .tg { display: inline-block; color: var(--muted); line-height: 1.35; }
.tg:hover, .bwho .tg:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
#week-tg { margin-top: -4px; }
#week-tg:empty { display: none; }
#week-tg .tg { font-size: 14px; }
#week-tg .tg-sep { margin: 0 7px; color: var(--muted); opacity: .6; font-size: 14px; }
#week-tg .wa span { font-variant-numeric: tabular-nums; }
.bname { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; line-height: 1.3; }
.bname b { font-weight: 700; font-size: 15.5px; }
.bname small { font-size: 12px; color: var(--muted); }
.bstat { margin: 2px 0 0; font-size: 14px; font-weight: 600; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; }
.bstat .st { font-size: 11px; }
.bsub { margin: 0; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.bsub .mono { font-size: 12.5px; }
.walk { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 600; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 0 7px; white-space: nowrap; }
.walk svg { flex: none; }
/* star a friend: they move to the top of the list and get a star on the map */
.star-btn {
  grid-column: 3; justify-self: end; width: 34px; height: 34px; margin-right: -8px; padding: 0;
  display: grid; place-items: center; border: 0; border-radius: 10px; background: transparent; cursor: pointer;
  color: color-mix(in srgb, var(--muted) 75%, transparent); -webkit-tap-highlight-color: transparent;
}
.star-btn svg { width: 21px; height: 21px; display: block; overflow: visible; }
.star-btn path { fill: transparent; stroke: currentColor; stroke-width: 1.7; stroke-linejoin: round; transition: fill 120ms; }
.star-btn[aria-pressed="true"] { color: var(--star); }
.star-btn[aria-pressed="true"] path { fill: currentColor; }
@media (hover: hover) {
  .star-btn:hover { color: var(--ink); background: var(--line-soft); }
  .star-btn[aria-pressed="true"]:hover { color: var(--star); }
}
.star-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
/* hidden friends (your own choice, only you see it): a tag and Hide/Show on search results, their names under the list */
/* On or off campus (the phone apps' geofences, 29 Oct; app.js campusBadge, campusDot): green on campus, grey off,
   nothing unknown. In the Friends list a dot on the avatar's bottom right, like the map's .oncampus; on a friend's week
   the dot by the words. Nothing that says "location". */
.cb { --cb-on: var(--p-green); display: inline-flex; align-items: center; align-self: center; flex: none; line-height: 1; user-select: none; }
.cb-dot { --cs-off: color-mix(in srgb, var(--ink) 38%, var(--surface)); }
.cb-dot:not(.vh) { width: 9px; height: 9px; border-radius: 50%; background: var(--cs-off); }
.cb-dot.on:not(.vh) { background: var(--cb-on); }
.bav .av:is(.cs-on, .cs-off) { overflow: visible; }
.bav .av:is(.cs-on, .cs-off)::after {
  content: ''; position: absolute; z-index: 3; right: -1px; bottom: -1px; width: 11px; height: 11px; border-radius: 50%;
  background: var(--p-green); box-shadow: 0 0 0 2px var(--surface); pointer-events: none;
}
.bav .av.cs-off::after { background: color-mix(in srgb, var(--ink) 38%, var(--surface)); }
.brow.me .bav .av::after { box-shadow: 0 0 0 2px color-mix(in srgb, var(--strong) 6%, var(--surface)); }
/* a friend's week: the same, larger, with the words */
.week-name { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; }
.cb-line { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.cb-line .cb { zoom: 1.25; }
.campus-log { font-size: 13px; color: var(--muted); }
.campus-log summary { cursor: pointer; font-weight: 600; color: var(--ink); }
.campus-log ol { margin: 8px 0 0; padding: 0; list-style: none; display: grid; gap: 6px; font-variant-numeric: tabular-nums; }
.campus-log li b { color: var(--ink); font-weight: 600; }
.htag { font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 0 6px; line-height: 16px; }
.hide-btn {
  border: 0; background: transparent; padding: 2px 4px; margin-left: -4px; border-radius: 6px; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--muted); text-decoration: underline; text-underline-offset: 3px;
  -webkit-tap-highlight-color: transparent;
}
.hide-btn:hover { color: var(--ink); }
.hide-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 0; }
.brow.hidden-p .bav, .brow.hidden-p .bname b { opacity: 0.55; }
.bhidden { margin: 0; padding: 12px 16px 14px; border-top: 1px solid var(--line-soft); font-size: 13.5px; color: var(--muted); }
.bhidden a { color: var(--ink); text-underline-offset: 3px; }
/* a friend's week: Star and Hide (from Everyone) */
.week-rel { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.week-rel:empty { display: none; }
.rel-btn {
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.rel-btn svg { width: 16px; height: 16px; display: block; overflow: visible; }
.rel-btn path { fill: transparent; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.rel-btn .eye-off path { stroke-linecap: round; }
.rel-btn[data-star][aria-pressed="true"] svg { color: var(--star); }
.rel-btn[data-star][aria-pressed="true"] path { fill: currentColor; }
.rel-btn[data-hide][aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--surface); }
@media (hover: hover) {
  .rel-btn:hover { background: var(--line-soft); }
  .rel-btn[data-hide][aria-pressed="true"]:hover { background: var(--ink); opacity: 0.88; }
}
.rel-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.rel-note { flex-basis: 100%; margin: 0; font-size: 13px; color: var(--muted); }
/* search, at the top of the list */
.bsearch { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--line-soft); }
.qwrap { position: relative; flex: 0 1 400px; min-width: 0; display: flex; align-items: center; }
.qwrap .q-ic { position: absolute; left: 13px; color: var(--muted); pointer-events: none; }
.bsearch input {
  width: 100%; min-width: 0; margin: 0; font: inherit; font-size: 16px; line-height: 1.25; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 999px; padding: 8px 38px 8px 37px;
  -webkit-appearance: none; appearance: none;
}
.bsearch input::placeholder { color: var(--muted); opacity: 1; }
.bsearch input:focus { outline: none; border-color: var(--ink); background: var(--surface); }
.bsearch input::-webkit-search-cancel-button, .bsearch input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
.q-clear { position: absolute; right: 4px; width: 30px; height: 30px; padding: 0; display: grid; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer; }
.q-clear:hover { color: var(--ink); background: var(--line-soft); }
.q-clear:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.q-count { font-size: 13px; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.bnone { margin: 0; padding: 22px 16px; color: var(--muted); font-size: 14px; }

.track { position: relative; height: var(--h, 26px); border-radius: 7px; background: color-mix(in srgb, var(--line-soft) 55%, transparent); }
.track::before { content: ""; position: absolute; left: 0; top: -4px; bottom: -4px; width: 2px; border-radius: 1px; background: var(--live); z-index: 3; }
.track .tick { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--line); z-index: 0; }
.track .idle { position: absolute; inset: 0; display: flex; align-items: center; padding-left: 12px; font-size: 12px; color: var(--muted); }
.seg {
  position: absolute; z-index: 1; height: 20px; top: calc(3px + var(--lane, 0) * 23px);   /* (26 px, 30 px apart until 26 Oct: shorter rows) */
  border-radius: 5px; padding: 0 7px; min-width: 6px;
  display: flex; align-items: center; gap: 2px;
  background: var(--c-fill); border: 1px solid color-mix(in srgb, var(--c) 45%, transparent); border-left: 4px solid var(--c);
  color: var(--c-text); font-size: 12px; font-weight: 600; line-height: 1; white-space: nowrap; overflow: hidden;
}
.seg.hands { border-style: dotted; border-left-style: solid; background: radial-gradient(circle, color-mix(in srgb, var(--c) 35%, transparent) 1px, transparent 1.5px) 0 0 / 6px 6px, var(--c-fill); }
.seg.prac { border-style: dashed; border-left-style: solid; background: repeating-linear-gradient(135deg, var(--c-fill) 0 6px, color-mix(in srgb, var(--c-fill) 45%, var(--surface)) 6px 11px); }
.seg.cont { border-left: 1px solid color-mix(in srgb, var(--c) 45%, transparent); border-top-left-radius: 0; border-bottom-left-radius: 0; }
.seg .ic { margin-right: 3px; }
.seg .sb { font-family: var(--font-mono); font-weight: 500; opacity: .9; }
.seg span { overflow: hidden; text-overflow: ellipsis; }
.axis-track { position: relative; height: 18px; }
.axis-track span { position: absolute; top: 0; transform: translateX(-50%); font-family: var(--font-mono); font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.axis-track span.now { transform: none; color: var(--live); font-weight: 500; }
.axis-track span.end { transform: translateX(-100%); }

/* ---------- Week ---------- */
.week-top { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-bottom: -12px; }
.week-top h2 { font-size: clamp(26px, 4vw, 34px); line-height: 1.1; letter-spacing: -0.015em; }
/* a friend's week: their avatar next to the title and Telegram link */
.week-who { display: flex; align-items: center; gap: 14px; min-width: 0; }
.week-who > div { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; }
.week-av { display: inline-grid; flex: none; }
.week-av:empty { display: none; }
.week-av .av { width: 60px; height: 60px; font-size: 24px; }
@media (max-width: 560px) { .week-av .av { width: 52px; height: 52px; font-size: 21px; } .week-who { gap: 12px; } }
/* Back: a round button with a chevron, as in iOS (27 Oct, user: "an apple guidelines back button (arrow icon in a large
   circle)"; "← Everyone" and the like as an underlined link until then). 44 px, the smallest tap Apple allows; white
   with a soft shadow on the light page, a lighter gray on the dark one; the page it goes back to is its label for
   screen readers (data-t-aria) */
.back {
  display: inline-flex; align-items: center; justify-content: center; flex: none; align-self: flex-start;
  width: 44px; height: 44px; border-radius: 50%; color: var(--ink); background: var(--surface); box-shadow: 0 1px 6px rgba(0, 0, 0, .08);
  text-decoration: none; -webkit-tap-highlight-color: transparent; transition: transform .12s, background-color .15s;
}
.back svg { width: 22px; height: 22px; margin-left: -2px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.back:active { transform: scale(.92); }
@media (hover: hover) { .back:hover { background: color-mix(in srgb, var(--ink) 6%, var(--surface)); } }
.back:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .back { background: #262626; box-shadow: none; } }
:root[data-theme="dark"] .back { background: #262626; box-shadow: none; }
/* the week: no boxes or outlines round the numbers, the week and the classes (27 Oct, user: "Remove borders to make
   the design more minimalistic"; the classes keep their fills) */
.stats { margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px 20px; }
.stats div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.stats dt { font-size: 12px; color: var(--muted); }
.stats dd { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 22px; line-height: 1.15; }
.stats dd small { font-family: var(--font-body); font-weight: 500; font-size: 13px; color: var(--muted); margin-left: 4px; }

/* the same room above the legend (from the numbers) and below it (to the first day): 38 px between the letters on a
   phone and on a computer (27 Oct, user: equal, then "larger. These are different blocks", then "Make it 38"; it was
   43 and 23): the numbers 5 px closer, 17 px under the legend over the grid, 15 px over a phone's list */
#week-view .stats { margin-bottom: -5px; }
.legend { display: flex; flex-wrap: wrap; gap: 8px 18px; font-size: 13px; color: var(--muted); align-items: center; margin-bottom: 17px; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.weekcard { display: flex; flex-direction: column; gap: 14px; }
.week-cat { margin: 0; font-size: 12.5px; color: var(--muted); }
.week-scroll { overflow-x: auto; padding-bottom: 12px; }
.week { display: grid; min-width: 820px; }
.dayhead { grid-row: 1; padding: 0 8px 10px; display: flex; flex-direction: column; justify-content: flex-end; gap: 1px; border-left: 1px solid var(--line-soft); }
.dayhead .dn { font-family: var(--font-display); font-weight: 700; font-size: 16px; display: flex; gap: 8px; align-items: baseline; }
.dayhead .dn [lang="he"] { font-weight: 400; font-size: 13px; color: var(--muted); }
.dayhead .dh { font-size: 12px; color: var(--muted); }
.cell { border-top: 1px solid var(--line-soft); border-left: 1px solid var(--line-soft); }
.hour { grid-column: 1; align-self: start; transform: translateY(-0.55em); font-size: 11px; color: var(--muted); padding-right: 8px; text-align: right; }
.hour.last { align-self: end; transform: translateY(0.55em); }
/* today: the day name in red and a line at the current time */
.dayhead.today .dn, .dayhead.today .dn [lang="he"] { color: var(--live); }
.nowline { position: relative; z-index: 4; pointer-events: none; }
.nowline i { position: absolute; left: 0; right: 0; height: 2px; margin-top: -1px; border-radius: 1px; background: var(--live); }
.nowline i::before { content: ""; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--live); }

.block {
  --lane: 0; --lanes: 1; --inset: 0px;
  z-index: 2; margin: 3px 0; min-width: 0; justify-self: start;
  width: calc((100% - 6px - var(--inset)) / var(--lanes) - (var(--lanes) - 1) * 2px);
  margin-left: calc(3px + var(--inset) + ((100% - 6px - var(--inset)) / var(--lanes)) * var(--lane));
  border-radius: 8px; padding: 10px 9px 7px;   /* where the text was with the outline and the 4 px top edge (gone 27 Oct) */
  display: flex; flex-direction: column; gap: 1px; overflow: hidden;
  color: var(--ink); background: var(--c-fill);
}
.block.prac {
  background: repeating-linear-gradient(135deg, var(--c-fill) 0 7px, color-mix(in srgb, var(--c-fill) 45%, var(--surface)) 7px 13px);
}
.block.hands {
  background: radial-gradient(circle, color-mix(in srgb, var(--c) 30%, transparent) 1.2px, transparent 1.7px) 0 0 / 8px 8px, var(--c-fill);
}
.block.ghost { background: var(--surface); }
.block .bn { font-weight: 700; font-size: 13px; line-height: 1.2; color: var(--c-text); }
.block .bm { font-size: 11.5px; line-height: 1.25; font-weight: 600; color: var(--c-text); }
.block .bt { font-size: 11px; font-weight: 400; opacity: .85; }
.block .bw, .block .br { font-size: 11px; line-height: 1.25; overflow-wrap: anywhere; }
.block .bw { font-family: var(--font-he); font-weight: 600; margin-top: 2px; }
.block .br.na { color: var(--muted); font-family: var(--font-body); font-style: italic; }
.block.ghost .br.na { color: var(--live); font-style: normal; font-weight: 600; }
.block.short { gap: 0; padding-block: 6px 4px; }
.block.short .bn, .block.short .bm, .block.short .bw, .block.short .br { line-height: 1.2; }
.block.short .bw { margin-top: 0; }
.block .bk { font-weight: 600; font-size: 11.5px; }
/* classes on set dates (often labs): the day's topic, and the dates under the room */
.block .bx { font-size: 11px; line-height: 1.25; font-weight: 600; color: var(--c-text); overflow-wrap: anywhere; }
.block .bd { display: flex; align-items: center; gap: 4px; margin-top: 2px; font-size: 11px; line-height: 1.25; font-weight: 600; color: var(--c-text); }
.block .bd .ic { width: 12px; height: 12px; margin-right: 0; }
.block.short .bx, .block.short .bd { display: none; }
.wband {
  z-index: 1; margin: 3px; border-radius: 8px; padding: 7px 9px;
  background: repeating-linear-gradient(180deg, var(--c-fill) 0 10px, color-mix(in srgb, var(--c-fill) 60%, var(--surface)) 10px 20px);
  color: var(--c-text); font-size: 11.5px; font-weight: 600; line-height: 1.25;
  display: flex; flex-direction: column; gap: 1px; overflow: hidden;
}
.wband .bt { font-weight: 400; }
.gap { z-index: 0; margin: 3px; border-radius: 8px; border: 1px dashed var(--line); display: flex;   /* the break keeps its dashed outline (27 Oct, user) */ align-items: center; justify-content: center; font-size: 11.5px; color: var(--muted); }
.free { z-index: 0; margin: 3px; border-radius: 10px; background: repeating-linear-gradient(135deg, transparent 0 10px, var(--line-soft) 10px 11px); display: flex; align-items: center; justify-content: center; }
.free span { font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--muted); background: var(--bg); padding: 4px 10px; border-radius: 999px; }

.agenda { display: none; flex-direction: column; gap: 18px; }
.aday { display: flex; flex-direction: column; gap: 8px; }
.aday h3 { margin: 0; font-family: var(--font-display); font-size: 17px; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
.aday h3 small { font-family: var(--font-body); font-weight: 500; font-size: 13px; color: var(--muted); }
.aday ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.arow { position: relative; display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 10px; align-items: start; }
.arow .t { font-size: 12.5px; color: var(--muted); padding-top: 9px; }
.arow .block { --lanes: 1; --lane: 0; --inset: 0px; margin: 0; width: auto; justify-self: stretch; }
.arow .wband { margin: 0; }
.arow .gap { margin: 0; padding: 4px 8px; justify-content: flex-start; }
.aday.today h3::after { content: var(--t-today, "Today");   /* the word from strings.js (applyStatic) */ align-self: center; font-family: var(--font-body); font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--live); border: 1px solid currentColor; border-radius: 999px; padding: 1px 8px; }
.anow { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 10px; align-items: center; margin: -1px 0; }
.anow span { font-size: 12px; font-weight: 500; color: var(--live); }
.anow i { position: relative; height: 2px; margin-left: -9px; border-radius: 1px; background: var(--live); }   /* its dot in the gap left of the classes (the Figma) */
.anow i::before { content: ""; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--live); }
/* during a class or a break: over that row at the time's place in it (markNow sets top; the Figma, 27 Oct) */
.anow.over { position: absolute; z-index: 3; left: 0; right: 0; height: 18px; margin: -9px 0 0; pointer-events: none; }
.arow .t.covered { visibility: hidden; }   /* the row's hours under "Now 12:05" */

/* ---------- Tables ---------- */
.table-scroll { overflow-x: auto; background: var(--surface); border-radius: 14px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 11px 14px; vertical-align: top; border-bottom: 1px solid var(--line-soft); }
tr:last-child td { border-bottom: 0; }
th { font-size: 12px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); background: color-mix(in srgb, var(--line-soft) 60%, var(--surface)); }
.sub { display: block; font-size: 12.5px; color: var(--muted); }

/* ---------- Exams ---------- */
.exams { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 16px; align-items: start; }
.panel { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.panel h3 { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.pnote { margin: 0; font-size: 13px; color: var(--muted); }
.quizzes { list-style: none; margin: 0; padding: 0; background: var(--surface); border-radius: 14px; }
.quizzes li { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 4px 12px; padding: 12px 14px; border-bottom: 1px solid var(--line-soft); align-items: baseline; }
.quizzes li:last-child { border-bottom: 0; }
.quizzes li.past { opacity: .5; }
.quizzes .d { font-size: 13px; color: var(--muted); }
.quizzes .what { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.quizzes .wn { display: block; font-weight: 600; }
.quizzes .note, .quizzes .loc { font-size: 12.5px; color: var(--muted); padding-left: 19px; overflow-wrap: anywhere; }
.quizzes .cal { grid-column: 2; justify-self: start; margin-left: 14px; }
.quizzes .none { grid-column: 1 / -1; color: var(--muted); }
/* the finals table fits the screen, no scrolling sideways (4 Nov 2026, Timur; it was 400 px at least, 39 px wider than a
   393 px phone's page): narrower gutters, the course names wrapping, each date kept on one line */
#finals th, #finals td { padding-inline: 10px; }
#finals th:first-child, #finals td:first-child { padding-left: 14px; }
#finals .fd .mono { white-space: nowrap; }
#finals .subj { white-space: normal; }
.fd { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 10px; }
.fd .sub { flex-basis: 100%; }
.cal {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 600; color: var(--ink);
  text-decoration: none; border-radius: 6px; padding: 2px 6px; margin: -2px -6px;
}
.cal span { text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; }
.cal:hover { background: var(--line-soft); }
.cal:hover span { text-decoration-color: var(--ink); }
.cal:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.cal svg { flex: none; }

/* ---------- Today ---------- */
/* Now and today: breaks and the end-of-day note take a whole row; finished classes shrink and fade. The sections are
   24 px apart (the user's Figma, 26 Oct; 36 px on other pages), with no heading over the cards. */
#today-view { gap: 24px; }
#me-now .now-grid > .tbreak, #me-now .now-grid > .empty { grid-column: 1 / -1; }
.ncard.done { opacity: .5; align-self: start; padding-block: 12px; }
.ncard.done .nwhen { margin-bottom: 2px; }
.ncard.done h3 { font-size: 16px; }
.ncard.done h3 .st { margin-right: 9px; vertical-align: 2px; font-family: var(--font-body); }   /* Done before the icon (4 Nov 2026) */
.ncard.done .nwho, .ncard.done .ntags { display: none; }
/* the minigame ad (27 Oct, user; each game draws its own 104 px box with its own colors): the last block on Today, 16 px
   under the day's last card or the end-of-day note (the section's 14 + 2), as in the user's screenshot; all day since
   10 Nov 2026 (app.js renderDay); the cat's words in the app's fonts (the car's and the pizza's are fixed in their files) */
.t-game { margin-top: 2px; }
cat-game { font-family: var(--font-body); --cg-mono: var(--font-mono); }
/* a break between classes: the week's dashed outline round it (4 Nov 2026, Timur: "the same dotted outline as on the
   week page"), on the page's surface while it's on */
.tbreak { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 12px; padding: 9px 16px; border: 1px dashed var(--line); border-radius: 14px; font-size: 13px; color: var(--muted); }
.tbreak b { font-weight: 600; font-size: 14px; color: var(--ink); }
.tbreak.live { padding: 11px 16px; background: var(--surface); }
.tbreak.done { opacity: .5; }
/* Other groups today: the heading with its note under it, 20 px, then the list on the page's surface, no outline */
#others-wrap { gap: 20px; }
#others-wrap .shead { flex-direction: column; align-items: flex-start; gap: 5px; }
#others-wrap .shead p { line-height: 1; }
.olist { list-style: none; margin: 0; padding: 0; background: var(--surface); border-radius: 14px; }
.orow { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 14px; padding: 10px 14px 11px; border-bottom: 1px solid var(--line-soft); font-size: 14px; }
.orow:last-child { border-bottom: 0; }
.orow .on { flex: 1 1 260px; min-width: 0; }
.orow .or, .orow .ow { color: var(--muted); font-size: 13px; }
.orow .ost { margin-left: auto; font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.orow .ost.live { color: var(--live); }
.orow.done { opacity: .5; }

footer { font-size: 12.5px; color: var(--muted); display: flex; flex-direction: column; gap: 14px; }   /* (no rule above it since 27 Oct) */
/* "Build 99. Vibecoded by @btimur." only on the profile and settings page (26 Oct evening, user; the build in place of
   the bundle's date since 28 Oct); elsewhere the footer is just "Install the app" (computers in a browser tab), or
   nothing at all. Four taps on the build open the developer options (app.js) */
body:not([data-view="me"]) #footer-text { display: none; }
body:not([data-view="me"]) footer:has(> .install[hidden]) { display: none; }
footer p { margin: 0; }
footer a { color: inherit; }
.build-n { font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: default; touch-action: manipulation; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none; }
.dev-ver { font-family: var(--font-mono); font-size: 12px; }
/* the speed test (developer options): while it runs, a pill at the top and nothing else takes a tap */
.speed-run { position: fixed; inset: 0; z-index: 1000; touch-action: none; }
.speed-run[hidden] { display: none; }
.speed-pill { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 10px); left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 10px;
  max-width: calc(100% - 32px); padding: 6px 6px 6px 14px; border-radius: 999px; background: rgba(0, 0, 0, .78); color: #fff; font-size: 13px; font-weight: 500; white-space: nowrap; }
.speed-pill span { overflow: hidden; text-overflow: ellipsis; }
.speed-pill button { font: inherit; font-weight: 600; color: #fff; background: rgba(255, 255, 255, .18); border: 0; border-radius: 999px; padding: 5px 12px; cursor: pointer; }
.dev-speed-out { margin-top: 10px; display: grid; gap: 4px; }
.dev-speed-out .me-btns { margin-top: 4px; }
.dev-wifi-out { margin-top: 10px; display: grid; gap: 4px; }
.dev-wifi-out p { margin: 0; }
.dev-wifi-list { margin: 0; padding-left: 22px; max-height: 240px; overflow: auto; }
.dev-wifi-list code { font-size: 12px; }
#dev-wifi-place, #dev-wifi-room { flex-wrap: wrap; }
#dev-wifi-place label { flex-basis: calc(50% - 2px); }   /* (the three study places and A building: two rows of two) */
.dev-wifi-cover { display: grid; gap: 10px; margin-top: 6px; }
.dev-wifi-place small { opacity: .7; }
.dev-wifi-place ul { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 2px; }
.dev-wifi-place li { display: flex; justify-content: space-between; gap: 12px; }
.dev-wifi-place li.todo { opacity: .55; }
/* the Wi-Fi survey in any building (3 Nov 2026): the building and the room side by side, the GPS's line, the networks
   not sent, a building's rooms under its name and the numbers not scanned yet */
.dev-wifi-b { display: grid; grid-template-columns: 3fr 2fr; align-items: end; gap: 10px; margin: 10px 0 6px; }
.dev-wifi-gps.warn { color: var(--live); font-weight: 600; }
.dev-wifi-others summary { cursor: pointer; }
.dev-wifi-others ul { margin: 4px 0 0; padding-left: 18px; }
.dev-wifi-bs li small { display: block; opacity: .7; }
.dev-wifi-todo { margin: 6px 0 0; opacity: .55; overflow-wrap: anywhere; }
/* a switch's note right under it (developer options: the optimized map) */
.dev-sw-note { margin-top: 8px; }
.install { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.install-link { font: inherit; font-size: 14px; font-weight: 600; color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); border: 0; border-radius: 999px; padding: 8px 15px; cursor: pointer; display: inline-flex; align-items: center; gap: 8px; }
.install-link:hover { background: color-mix(in srgb, var(--ink) 12%, transparent); }
.install-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.install-help { font-size: 13.5px; color: var(--muted); max-width: 56ch; width: 100%; }
.install-help b { color: var(--ink); font-weight: 600; }
.install-steps { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 18px; counter-reset: install-step; }
.install-steps li { counter-increment: install-step; display: grid; grid-template-columns: 24px 1fr; column-gap: 10px; row-gap: 8px; align-items: start; }
.install-steps li::before { content: counter(install-step); grid-row: 1; width: 24px; height: 24px; border-radius: 50%; background: var(--ink); color: var(--surface); font-size: 12.5px; font-weight: 700; display: grid; place-items: center; }
.install-steps p { margin: 0; padding-top: 2px; }
.install-steps img { grid-column: 2; display: block; width: 100%; max-width: 280px; height: auto; border-radius: 12px; border: 1px solid var(--line); background: #000; }
.install-steps img.install-small { max-width: 163px; }

@media (max-width: 680px) {
  :root { --title-top: calc(20px + env(safe-area-inset-top, 0px)); }
  .page { gap: 30px; }
  #week-h { --head-top: calc(20px + env(safe-area-inset-top, 0px)); }   /* where the page's top padding puts it */
  .today-head { margin-bottom: -6px; }   /* still 24 px to Today's cards */
  .week-scroll, .legend .pat { display: none; }
  .legend { margin-bottom: 15px; }
  .agenda { display: flex; }
  .exams { grid-template-columns: minmax(0, 1fr); }
  .stats div:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .brow { grid-template-columns: minmax(0, 1fr); row-gap: 6px; padding: 10px 14px 12px; }   /* (14 / 16 px and 8 px until 26 Oct: shorter rows) */
  .brow .star-btn { position: absolute; top: 5px; right: 8px; margin: 0; }
  .brow:not(.me):not(.axis) .bwho { padding-right: 30px; }
  .bsearch { padding: 12px 14px; }
  .qwrap { flex: 1 1 auto; }
  .brow.axis { position: sticky; top: env(safe-area-inset-top, 0px); z-index: 11; background: var(--surface); border-bottom: 1px solid var(--line-soft); padding-bottom: 6px; }
  .brow.axis .bwho { display: none; }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }


/* ---------- "Are you in the 📚 library?" at the top of every page (app.js Places, renderHere) ---------- */
.here { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 10px 10px 10px 16px; }
.here.asking { border-color: var(--ink); box-shadow: 0 6px 22px rgba(0, 0, 0, .08); animation: here-in .32s cubic-bezier(.3, 1.4, .5, 1); }
/* A catalogue change to one of your groups (29 Oct 2026, the design's option A): an asking card on top of every page,
   the course in its colors, what it was and what it is now on the course's fill */
.changes { display: flex; flex-direction: column; gap: 10px; }
.chg { background: var(--surface); border: 1px solid var(--ink); border-radius: 14px; padding: 14px 14px 14px 16px; box-shadow: 0 6px 22px rgba(0, 0, 0, .08);
  display: flex; flex-direction: column; gap: 12px; animation: here-in .32s cubic-bezier(.3, 1.4, .5, 1); }
.chg-label { margin: 0; display: flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.chg-label svg { flex: none; }
.chg-head { display: flex; flex-direction: column; gap: 2px; }
.chg-name { margin: 0; font-family: var(--font-display); font-size: 20px; font-weight: 700; line-height: 1.15; letter-spacing: -0.01em; color: var(--c-text); text-wrap: balance; }
.chg-kind { margin: 0; font-size: 14px; font-weight: 600; color: var(--c-text); }
.chg-diff { margin: 0; background: var(--c-fill); border-radius: 10px; padding: 10px 12px; display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 12px; row-gap: 4px; align-items: baseline; }
.chg-diff dt { font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.chg-diff dt.now { color: var(--c-text); }
.chg-diff dd { margin: 0; font-family: var(--font-mono); font-size: 15px; line-height: 1.4; overflow-wrap: anywhere; }
.chg-diff dd.was { color: var(--muted); text-decoration: line-through; }
.chg-diff dd.now { font-weight: 500; color: var(--ink); }
.chg-note { margin: 0; font-size: 13.5px; line-height: 1.4; color: var(--muted); }
.chg-btns { display: flex; flex-wrap: wrap; gap: 8px; }
.chg .here-btn { min-height: 44px; padding-inline: 20px; }
.chg .here-btn:disabled { opacity: .5; cursor: default; }
/* Update in the ink's color, so it stays bright on the dark card too (the design's dark board) */
.chg .here-btn.yes { background: var(--ink); border-color: var(--ink); color: var(--surface); }
.chg .me-msg:empty { display: none; }
.chg-done { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 6px 6px 6px 16px; display: flex; align-items: center; gap: 12px; }
.chg-done svg { flex: none; color: var(--ink); }
.chg-done.updated svg { color: var(--p-green); }
.chg-done p { margin: 0; flex: 1 1 auto; min-width: 0; font-size: 15px; line-height: 1.35; }
.chg-done p b { font-weight: 700; }
.chg-undo { flex: none; min-height: 44px; font: inherit; font-size: 13px; color: var(--muted); background: none; border: 0; padding: 6px 10px; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.chg-undo:hover { color: var(--ink); }
.chg-undo:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }
@keyframes here-in { from { opacity: 0; transform: translateY(-6px) scale(.98); } to { opacity: 1; transform: none; } }
.here-q { margin: 0; flex: 1 1 auto; min-width: 0; font-size: 16px; line-height: 1.35; }
.here-q b { font-weight: 700; }
.here-until { color: var(--muted); font-size: 14px; white-space: nowrap; }
.here-btns { display: flex; gap: 8px; flex: none; margin-left: auto; }
.here-btn { font: inherit; font-size: 14px; font-weight: 700; min-width: 64px; min-height: 38px; padding: 8px 16px; border-radius: 999px; cursor: pointer; color: var(--ink); background: transparent; border: 1px solid var(--line); }
.here-btn:hover { border-color: var(--muted); }
.here-btn.yes { color: var(--strong-ink); background: var(--strong); border-color: var(--strong); }
.here-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* Where in the place (29 Oct 2026, Timur): after a Yes, the buttons 1-5 in the library, 2, −1, Столовая, 🏓 in Beit
   Studentim (.here-pick, no question in words, on the same line as "I left" when they fit); then the answer is the button by "I left"
   (.here-room, with a chevron), which opens the row again with it selected */
.here-pick { flex: 1 1 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.here-opt { font: inherit; font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; min-width: 42px; min-height: 38px; padding: 6px 13px; border-radius: 999px; cursor: pointer; color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); border: 0; }
.here-opt:hover { background: color-mix(in srgb, var(--ink) 14%, transparent); }
.here-opt.emo { margin: 0; font-size: 19px; line-height: 1; padding: 6px 10px; }
.here-opt.on { color: var(--surface); background: var(--ink); }   /* the ink, not --strong: that is black in the dark too, where the picked one was darker than the rest */
.here-opt:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.here-room { display: inline-flex; align-items: center; gap: 2px; min-width: 0; padding-right: 12px; }
.here-room .emo { margin: 0; font-size: 17px; line-height: 1; }
.here-chev { flex: none; opacity: .55; }
.emo { font-style: normal; margin-right: .25em; }

/* ---------- Before the phone asks for your location (app.js openGeoAsk): a card over the page, a sheet on phones ---------- */
.geo-ask { box-sizing: border-box; width: min(420px, calc(100% - 32px)); max-width: none; max-height: calc(100% - 32px); overflow: auto; margin: auto; padding: 22px 20px 18px; color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: 20px; box-shadow: 0 18px 60px rgba(0, 0, 0, .28); }
.geo-ask::backdrop { background: rgba(0, 0, 0, .45); }
.geo-ask[open] { animation: geo-in .28s cubic-bezier(.3, 1.3, .5, 1); }
@keyframes geo-in { from { opacity: 0; transform: translateY(14px) scale(.98); } to { opacity: 1; transform: none; } }
.geo-ask h2 { font-size: 21px; line-height: 1.2; outline: none; }
.geo-list { list-style: none; margin: 16px 0 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.geo-list li { display: grid; grid-template-columns: 36px 1fr; gap: 12px; align-items: start; }
.geo-list p { margin: 0; padding-top: 1px; }
.geo-list b { display: block; font-size: 15px; font-weight: 700; line-height: 1.3; }
.geo-list span:not(.geo-ic) { display: block; margin-top: 2px; font-size: 13.5px; line-height: 1.4; color: var(--muted); }
.geo-ic { width: 36px; height: 36px; border-radius: 50%; background: var(--bg); display: grid; place-items: center; }
.geo-ic svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.geo-next { margin: 18px 0 0; font-size: 13.5px; color: var(--muted); }
.geo-btns { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
@media (max-width: 560px) {
  .geo-ask { width: calc(100% - 24px); margin: auto auto max(12px, env(safe-area-inset-bottom), var(--native-inset-bottom, 0px)); }
  .geo-btns .me-btn { flex: 1; min-height: 44px; }
}
/* someone in a place on their 3-hour timeline (Everyone list) */
.seg.spot { border-style: dashed; border-left-style: solid; background: var(--surface); }

/* ---------- Your profile (#me) ---------- */
#me-view { gap: 12px; max-width: 560px; width: 100%; }
.me-title { margin-bottom: 12px; }   /* "Settings" (27 Oct, user; was a small "Profile"): the pages' title, where theirs is, 24 px to the first card as on Today */
/* no outlines on this page (27 Oct, user: "Edit the design of the settings page to match the today and my week. Remove
   unnecessary borders"): the cards on the page's surface with Today's 14 px corners; buttons, fields, switches and pills
   filled instead of outlined, as in the class editor (the list rows keep their thin lines between them, as on Today) */
.me-card { background: var(--surface); border-radius: 14px; padding: 18px 18px 20px; display: flex; flex-direction: column; gap: 4px; }
.me-card h3 { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 17px; line-height: 1.25; }
.me-note { margin: 0; font-size: 13.5px; color: var(--muted); }
.me-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.me-btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.me-btn { font: inherit; font-size: 14px; font-weight: 600; color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); border: 0; border-radius: 999px; padding: 8px 16px; min-height: 38px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.me-btn:not(.strong):hover:not(:disabled) { background: color-mix(in srgb, var(--ink) 12%, transparent); }
.me-btn.strong { color: var(--strong-ink); background: var(--strong); }
.me-btn.ghost { background: transparent; }
a.me-btn { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; box-sizing: border-box; }   /* (the update card's Update: a link, so each app opens it outside) */
.me-btn.ghost:hover:not(:disabled) { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.me-btn.danger { color: var(--live); background: color-mix(in srgb, var(--live) 10%, transparent); align-self: flex-start; }
.me-btn.danger:hover:not(:disabled) { background: color-mix(in srgb, var(--live) 15%, transparent); }
/* Privacy and Delete account (Settings, under Sign out), the Privacy link and Try again on the sign-in screen */
.me-gone { display: flex; flex-flow: row wrap; align-items: center; gap: 8px; }
.me-gone .me-note { flex-basis: 100%; }
.me-btn.me-delete { color: var(--live); background: transparent; }
.me-btn.me-delete:hover:not(:disabled) { background: color-mix(in srgb, var(--live) 8%, transparent); }
.login-privacy { align-self: center; margin-top: 20px; font-size: 13px; font-weight: 500; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, var(--muted) 40%, transparent); }
.retry-load { margin-top: 14px; align-self: stretch; }
.me-btn:disabled { opacity: .5; cursor: default; }
.me-btn:focus-visible, .me-row input:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.me-photo { display: flex; align-items: flex-start; gap: 16px; }
.me-main { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 4px; }
.me-av .av { width: 72px; height: 72px; font-size: 28px; }
.me-file { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.me-crop { display: flex; align-items: center; gap: 16px; margin-top: 16px; }
.me-crop img { width: 72px; height: 72px; border-radius: 50%; object-fit: cover; flex: none; background: var(--line-soft); }
.me-crop .me-btns { margin-top: 0; }
.me-msg { margin: 8px 0 0; font-size: 13.5px; font-weight: 600; color: var(--live); }
.me-msg.ok { color: var(--p-green-text); }
.me-msg:empty { display: none; }
.me-name { display: flex; flex-direction: column; gap: 4px; }
.me-field { display: block; }
.me-row { display: flex; gap: 8px; margin-top: 10px; }
.me-phone-now { margin: 8px 0 0; font-family: var(--font-mono); font-size: 17px; }
#me-phone-form .me-row input { flex: 1; min-width: 0; }
#me-phone-cancel { margin-top: 6px; }
/* the Friends tab's Invite friends and Find from contacts (3 Nov 2026) */
.fr-tools { display: flex; flex-wrap: wrap; gap: 8px; margin: -6px 0 2px; }
/* Add a course, just signed up */
.add-welcome { margin: 0; padding: 12px 14px; border-radius: 14px; background: color-mix(in srgb, #127DFF 10%, var(--surface)); font-size: 15px; }
.add-welcome b { font-weight: 700; }
.me-row input { flex: 1 1 auto; min-width: 0; font: inherit; font-size: 16px; color: var(--ink); background: var(--bg); border: 0; border-radius: 10px; padding: 9px 12px; }
.me-state { flex: none; font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; border-radius: 999px; padding: 3px 10px; color: var(--muted); background: color-mix(in srgb, var(--ink) 7%, transparent); }
.me-state.on { color: var(--p-green-text); background: var(--p-green-fill); }
.me-state.blocked { color: var(--live); background: color-mix(in srgb, var(--live) 10%, transparent); }
.me-fix { margin: 10px 0 0; font-size: 13.5px; color: var(--muted); background: var(--bg); border-radius: 10px; padding: 10px 12px; }
.me-fix b { color: var(--ink); font-weight: 600; }
.me-sub { margin-top: 18px; }
/* Walking speed (4 Nov 2026): a filled track up to the thumb (--p, app.js renderMeWalk), the value at the right of the heading */
.me-walk-v { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.me-range {
  -webkit-appearance: none; appearance: none; width: 100%; height: 28px; margin: 10px 0 6px; background: transparent; cursor: pointer;
  --track: linear-gradient(to right, var(--ink) var(--p, 45%), color-mix(in srgb, var(--ink) 12%, transparent) var(--p, 45%));
  -webkit-tap-highlight-color: transparent; touch-action: pan-y;
}
.me-range::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: var(--track); }
.me-range::-moz-range-track { height: 6px; border-radius: 999px; background: var(--track); }
.me-range::-webkit-slider-thumb { -webkit-appearance: none; width: 26px; height: 26px; margin-top: -10px; border-radius: 50%; background: #fff; border: 0; box-shadow: 0 1px 4px rgba(0, 0, 0, .3), 0 0 0 .5px rgba(0, 0, 0, .08); }
.me-range::-moz-range-thumb { width: 26px; height: 26px; border-radius: 50%; background: #fff; border: 0; box-shadow: 0 1px 4px rgba(0, 0, 0, .3); }
.me-range:focus-visible { outline: none; }
.me-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 30%, transparent), 0 1px 4px rgba(0, 0, 0, .3); }   /* the second heading in a card (Language (courses)) */
.me-seg { display: flex; gap: 3px; padding: 3px; margin: 10px 0 6px; background: var(--bg); border-radius: 12px; }
.me-seg label { flex: 1 1 0; min-width: 0; position: relative; cursor: pointer; }
.me-seg input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.me-seg span { display: block; text-align: center; font-size: 14px; font-weight: 600; color: var(--muted); padding: 8px 6px; border-radius: 9px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-seg input:checked + span { color: var(--ink); background: var(--surface); box-shadow: 0 1px 3px rgba(0, 0, 0, .12); font-weight: 700; }
.me-seg input:focus-visible + span { outline: 2px solid var(--ink); outline-offset: 1px; }
.me-seg.two-rows { flex-wrap: wrap; }   /* four options, two a row (the wheel's animation, a prototype) */
.me-seg.two-rows label { flex: 1 1 calc(50% - 2px); }
.me-out { gap: 8px; }
@media (max-width: 680px) {
  .here { padding: 10px 10px 10px 14px; }
  .here-q { flex-basis: 100%; }
  .me-card { padding: 16px 16px 18px; }
}

/* ---------- Groups (cliques): who sees whom ---------- */
/* the profile page's Groups card */
.grp-list, .grp-people { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; }
.grp-list li + li .grp-row { border-top: 1px solid var(--line-soft); }
.grp-row { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto 12px; align-items: center; gap: 12px; padding: 10px 2px; color: inherit; text-decoration: none; border-radius: 10px; -webkit-tap-highlight-color: transparent; }
@media (hover: hover) { .grp-row:hover .grp-name b { text-decoration: underline; text-underline-offset: 3px; } }
.grp-row:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.grp-emo { width: 40px; height: 40px; border-radius: 12px; background: var(--bg); display: grid; place-items: center; font-size: 21px; line-height: 1; font-family: var(--font-display); font-weight: 700; color: var(--muted); flex: none; }
.grp-emo.big { width: 56px; height: 56px; border-radius: 16px; font-size: 30px; }
.grp-name { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.grp-name b { font-weight: 700; font-size: 15.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grp-name small { font-size: 12.5px; color: var(--muted); }
.grp-avs { display: flex; padding-left: 6px; }
.grp-avs .av { width: 24px; height: 24px; font-size: 10.5px; margin-left: -6px; box-shadow: 0 0 0 2px var(--surface); }
.grp-chev { color: var(--muted); font-size: 22px; line-height: 1; }
.grp-none { padding: 10px 0 2px; font-size: 14px; color: var(--muted); }
.grp-count { margin-top: 8px; }
.grp-count:empty { display: none; }
.grp-form { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; }
#grp-new { margin-top: 16px; }
.grp-form .me-row { flex-wrap: wrap; }
.grp-form .me-row input { flex: 1 1 180px; }
/* the name with the emoji picked so far, the picker, then Create / Save (app.js groupFormHTML) */
.grp-form .grp-name-row { flex-wrap: nowrap; align-items: center; }
.grp-form .grp-name-row input { flex: 1 1 auto; }
.emo-now { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; font-size: 23px; line-height: 1; background: var(--bg); }
.grp-form .grp-form-btns { margin-top: 12px; }
/* the emoji picker (app.js emojiPickerHTML): search, the categories row, the list scrolling inside its panel */
.emo-pick { display: flex; flex-direction: column; margin-top: 10px; padding: 8px 6px 0; background: var(--bg); border-radius: 14px; }
.emo-q { flex: none; margin: 0 2px; }
.emo-q input {
  width: 100%; min-width: 0; margin: 0; font: inherit; font-size: 16px; line-height: 1.25; color: var(--ink);
  background: var(--surface); border: 0; border-radius: 999px; padding: 8px 14px 8px 37px; -webkit-appearance: none; appearance: none;
}
.emo-q input::placeholder { color: var(--muted); opacity: 1; }
.emo-q input:focus { outline: 2px solid var(--ink); outline-offset: 2px; }
.emo-q input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.emo-cats { display: flex; justify-content: space-between; gap: 2px; margin-top: 6px; }
.emo-cats[hidden] { display: none; }
.emo-cat { flex: 1 1 0; min-width: 0; height: 32px; padding: 0; border: 0; border-radius: 9px; background: transparent; font-size: 17px; line-height: 1; cursor: pointer; opacity: .42; filter: grayscale(.6); transition: opacity .15s, filter .15s; -webkit-tap-highlight-color: transparent; }
.emo-cat.on { opacity: 1; filter: none; background: color-mix(in srgb, var(--ink) 8%, transparent); }
@media (hover: hover) { .emo-cat:hover { opacity: .85; filter: none; } }
.emo-cat:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.emo-scroll { position: relative; height: 236px; overflow-y: auto; overscroll-behavior: contain; margin-top: 2px; padding-bottom: 6px; scrollbar-width: thin; -webkit-overflow-scrolling: touch; }
.emo-sec { content-visibility: auto; contain-intrinsic-size: auto 400px; }   /* laid out when scrolled to (app.js emojiSection) */
.emo-pick.searching .emo-sec { display: none; }
.emo-h { position: sticky; top: 0; z-index: 1; margin: 0; padding: 8px 6px 4px; font-size: 12px; font-weight: 700; color: var(--muted); background: var(--bg); }
.emo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(38px, 1fr)); gap: 2px; }
.emo-found .emo-grid { padding-top: 8px; }
.emo-sec[data-cat=top] .emo-grid:empty { min-height: 166px; }   /* the most used, until the list is in (4 rows) */
.emo-b { height: 40px; padding: 0; border: 0; border-radius: 10px; background: transparent; color: var(--ink); font: inherit; font-size: 25px; line-height: 1; cursor: pointer; -webkit-tap-highlight-color: transparent; }
@media (hover: hover) { .emo-b:hover { background: color-mix(in srgb, var(--ink) 7%, transparent); } }
.emo-b.on { background: var(--surface); box-shadow: inset 0 0 0 2px var(--ink); }
.emo-b:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.emo-none { margin: 0; padding: 26px 12px; text-align: center; font-size: 13.5px; color: var(--muted); }
.grp-blocked { margin-top: 6px; }

/* people in a group (members, invited, search results, blocked) */
.grp-p { display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 9px 0; }
.grp-p + .grp-p { border-top: 1px solid var(--line-soft); }
.grp-pn { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
a.grp-pn { color: inherit; text-decoration: none; -webkit-tap-highlight-color: transparent; }
a.grp-pn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 6px; }
/* ---------- The Friends tab (#people) ----------
   3 Nov 2026, Timur's Figma "test" (node 96:3931 in J8pe6VVsa9yk1vkgwlcYcu), drawn dark: the title and its note, the
   requests to you, the search, Suggestions, your friends, 22 px apart; rows with 55 px avatars and no lines between
   them. In the light the same look on a white page (--fr-page, also under the tab bar's and status bar's fades). */
:root:has(> body[data-view="people"]) { --bg: var(--fr-page); }
#people-view { gap: 22px; max-width: 560px; width: 100%; }
.fr-head { display: flex; flex-direction: column; gap: 14px; }
.fr-note { margin: 0; font-size: 13.5px; line-height: 20.25px; color: var(--muted); }
/* a friend request: the avatar with a blurred copy of it glowing behind, inside the card */
.fr-reqs { display: flex; flex-direction: column; gap: 12px; }
.fr-reqs[hidden] { display: none; }
.fr-req { position: relative; isolation: isolate; overflow: hidden; display: flex; flex-direction: column; gap: 10px;
  background: var(--fr-card); border-radius: 14px; padding: 12px 14px; animation: here-in .32s cubic-bezier(.3, 1.4, .5, 1); }
.fr-req-top { display: flex; align-items: center; gap: 12px; }
.fr-avw { position: relative; flex: none; display: block; width: 55px; height: 55px; }
.fr-glow { position: absolute; inset: 0; z-index: -1; border-radius: 50%; background: var(--pc); filter: blur(16px); opacity: .5; pointer-events: none; }
.fr-glow.pic { background: none; }
.fr-glow img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.fr-req-q { display: block; font-size: 16px; line-height: 20px; margin: -2px 0; overflow-wrap: anywhere; }
.fr-req-q b { font-weight: 700; }
.fr-req-note { margin: 0; font-size: 13.5px; line-height: 20.25px; color: var(--muted); }
.fr-req-btns { display: flex; align-items: center; justify-content: flex-end; gap: 16px; padding-top: 2px; }
.fr-req-btns .fr-btn { height: 40px; }
.fr-req.declined { flex-direction: row; align-items: center; justify-content: space-between; gap: 12px; animation: none; }
.fr-req.declined .fr-req-q { margin: 0; font-size: 15px; color: var(--muted); }
.fr-req .me-msg:empty { display: none; }
/* the search: a pill, its clear button at the right once something is typed */
.fr-q { position: relative; display: flex; align-items: center; padding-bottom: 2px; }
.fr-q .q-ic { position: absolute; left: 13px; color: var(--muted); pointer-events: none; }
.fr-q input { width: 100%; min-width: 0; height: 36px; box-sizing: border-box; margin: 0; font: inherit; font-size: 16px; line-height: 20px; color: var(--ink);
  background: var(--fr-field); border: 0; border-radius: 999px; padding: 0 40px 0 37px; -webkit-appearance: none; appearance: none; }
.fr-q input::placeholder { color: var(--muted); opacity: 1; }
.fr-q input:focus { outline: none; box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ink) 22%, transparent); }
.fr-q input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.fr-q .q-clear { right: 3px; }
.fr-q .q-clear[hidden] { display: none; }
@media (hover: hover) { .fr-q .q-clear:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); } }
/* the lists */
#people-body { display: flex; flex-direction: column; gap: 12px; }
.fr-sec { display: flex; flex-direction: column; gap: 14px; }
.fr-sec + .fr-friends { padding-top: 16px; }
.fr-h { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 17px; line-height: 21.25px; }
.fr-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.fr-none { margin: 0; font-size: 13.5px; color: var(--muted); }
.fr-row { display: flex; align-items: center; gap: 12px; padding: 10px 0 9px; color: inherit; text-decoration: none; }
/* you or a friend: the whole row opens the week */
a.fr-row { margin: 0 -8px; padding-inline: 8px; border-radius: 14px; -webkit-tap-highlight-color: transparent; transition: background-color .15s; }
a.fr-row:active { background: color-mix(in srgb, var(--ink) 7%, transparent); }
@media (hover: hover) { a.fr-row:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); } }
a.fr-row:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.av.fr-av { width: 55px; height: 55px; font-size: 16.5px; }
.fr-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.fr-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; min-width: 0; }
.fr-name b { font-size: 15px; font-weight: 700; line-height: 1; overflow-wrap: anywhere; }
.fr-name .htag { border: 0; background: color-mix(in srgb, var(--ink) 8%, transparent); padding: 0 7px; }
.fr-txt small { display: block; font-size: 12.5px; line-height: 15px; margin: -1px 0; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fr-txt small.fr-mut { color: var(--fr-dim); }
.fr-act { flex: none; display: flex; }
/* the question before Decline or Block (#confirm-dlg, app.js askConfirm) */
.confirm-dlg h2 { margin: 0; overflow-wrap: anywhere; }
.confirm-dlg .me-note[hidden] { display: none; }
.confirm-dlg .me-btn.danger { align-self: auto; }
/* a friend's ⋮ (Timur's Figma "Frame 7", node 101:4499): 44 px at the row's right, over its link; three 4 px dots 3 px
   apart that stretch into 8 px bars (and lighten towards the ink) while the menu is open */
.fr-has-more { position: relative; }
.fr-has-more > a.fr-row { padding-right: 64px; }   /* (the 8 px the row reaches past the list, the button, 12 px) */
.fr-more { position: absolute; right: 0; top: 50%; width: 44px; height: 44px; margin-top: -22px; padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; color: var(--muted); -webkit-tap-highlight-color: transparent; transition: background-color .15s; }
.fr-more i { display: block; width: 4px; height: 4px; border-radius: 2px; background: currentColor; transition: width .32s cubic-bezier(.34, 1.56, .64, 1), background-color .2s; }
.fr-more[aria-expanded="true"] { color: color-mix(in srgb, var(--muted) 50%, var(--ink)); }
.fr-more[aria-expanded="true"] i { width: 8px; }
.fr-more[aria-expanded="true"] i:nth-child(2) { transition-delay: .03s; }
.fr-more[aria-expanded="true"] i:nth-child(3) { transition-delay: .06s; }
.fr-more:active { background: color-mix(in srgb, var(--ink) 7%, transparent); }
.fr-more:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
/* (10 Nov 2026) ⋮ on someone who isn't your friend: after their Add button, in the row, its dots where a friend's are */
.fr-row > .fr-more { position: static; flex: none; top: auto; margin: 0 0 0 -8px; }
/* its menu: a white popup under the dots, its tail's tip at their middle (app.js placeFrMenu), growing out of the tip */
#people-view { position: relative; }
/* its shadow is the item's box-shadow and the tail's own outline (index.html), no filter: iOS Safari drew the menu's
   drop-shadow as a pale box round it (3 Nov 2026, Timur's screenshot) */
.fr-menu { position: absolute; z-index: 5; color: #fff; transform-origin: calc(100% - 20px) -6px; }
.fr-menu[hidden] { display: none; }
.fr-menu.in { animation: fr-menu-in .26s cubic-bezier(.34, 1.4, .64, 1); }
@keyframes fr-menu-in { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
.fr-menu-tail { position: absolute; z-index: 0; right: 12px; top: -6px; display: block; overflow: visible; }
.fr-menu-edge { stroke: rgba(0, 0, 0, .13); }
.fr-menu.up { transform-origin: calc(100% - 20px) calc(100% + 6px); }
.fr-menu.up .fr-menu-tail { top: auto; bottom: -6px; right: 13px; transform: rotate(180deg); }
.fr-menu-item { position: relative; z-index: 1; display: flex; align-items: center; gap: 5px; margin: 0; padding: 12px; border: 0; border-radius: 8px; background: #fff; color: #f63422; cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .14), 0 0 1px rgba(0, 0, 0, .22);
  font: inherit; font-size: 14px; font-weight: 600; line-height: 12px; white-space: nowrap; -webkit-tap-highlight-color: transparent; }
.fr-menu-item span { display: block; padding-top: 1px; }
/* two items since 5 Nov 2026 (Report under Remove friend; Timur): one white box with a line between, as the class
   menu's (.cls-menu-box), the box carrying the shadow; Report greyed once you have reported them */
.fr-menu-box { position: relative; z-index: 1; display: flex; flex-direction: column; min-width: 170px; border-radius: 10px; background: #fff; overflow: hidden;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .14), 0 0 1px rgba(0, 0, 0, .22); }
.fr-menu-box .fr-menu-item { gap: 7px; padding: 13px 14px; border-radius: 0; background: transparent; box-shadow: none; line-height: 16px; }
.fr-menu-box .fr-menu-item + .fr-menu-item { border-top: 1px solid rgba(0, 0, 0, .08); }
.fr-menu-box .fr-menu-item[hidden] { display: none; }
.fr-menu-box .fr-menu-item[hidden] + .fr-menu-item { border-top: 0; }   /* (Remove friend hidden for someone who isn't your friend) */
.fr-menu-box .fr-menu-item:focus-visible { outline-offset: -2px; }
.fr-menu-box .fr-menu-item[aria-disabled="true"] { color: #8e8e93; cursor: default; }
.fr-menu-box .fr-menu-item[aria-disabled="true"]:active { background: transparent; }
.fr-menu-ic { display: block; flex: none; }
.fr-menu-item:active { background: #f2f2f2; }
.fr-menu-item:focus-visible { outline: 2px solid #f63422; outline-offset: 2px; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .fr-menu-item { box-shadow: none; } :root:not([data-theme="light"]) .fr-menu-edge { stroke: none; } }
:root[data-theme="dark"] .fr-menu-item { box-shadow: none; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .fr-menu-box { box-shadow: none; } }
:root[data-theme="dark"] .fr-menu-box { box-shadow: none; }
:root[data-theme="dark"] .fr-menu-edge { stroke: none; }
@media (prefers-reduced-motion: reduce) { .fr-more i { transition: none; } .fr-menu.in { animation: none; } }
/* Add / Accept: blue; Requested (a tap takes it back), Decline, Undo: an outline */
.fr-btn { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 35px; padding: 0 31px; font: inherit; font-size: 14px; font-weight: 600; line-height: 21px;
  white-space: nowrap; color: #fff; background: var(--fr-blue); border: 1px solid var(--fr-blue); border-radius: 999px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: opacity .15s; }
.fr-btn.out { color: var(--fr-out); background: transparent; border-color: var(--fr-out); font-weight: 700; padding: 0 16px; }
.fr-btn:active { opacity: .7; }
@media (hover: hover) { .fr-btn:hover:not(:disabled) { opacity: .88; } }
.fr-btn:disabled { opacity: .5; cursor: default; }
.fr-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.grp-pl { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.grp-pl b { font-weight: 700; font-size: 15px; }
.grp-pn small { font-size: 12.5px; color: var(--muted); }
.grp-pn .tg { align-self: flex-start; }
.grp-pl .htag { border: 0; background: color-mix(in srgb, var(--ink) 8%, transparent); padding: 0 7px; }
.grp-act { display: flex; gap: 6px; }
.grp-act .me-btn { min-height: 34px; padding: 6px 14px; }

/* a group's page (#group/<id>) */
#group-view { gap: 12px; max-width: 560px; width: 100%; }
#group-view .back { align-self: flex-start; }
.grp-body { display: flex; flex-direction: column; gap: 12px; }
.grp-top { display: flex; align-items: center; gap: 14px; margin: 6px 0 4px; }
.grp-head { min-width: 0; flex: 1 1 auto; }
.grp-head h2 { margin: 0; overflow-wrap: anywhere; }
.grp-head .me-note { margin-top: 2px; }
.grp-q { margin-top: 10px; flex: none; }
.grp-q input {
  width: 100%; min-width: 0; margin: 0; font: inherit; font-size: 16px; line-height: 1.25; color: var(--ink);
  background: var(--bg); border: 0; border-radius: 999px; padding: 8px 14px 8px 37px; -webkit-appearance: none; appearance: none;
}
.grp-q input::placeholder { color: var(--muted); opacity: 1; }
.grp-q input:focus { outline: 2px solid var(--ink); outline-offset: 2px; }
.grp-q input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
#grp-found { max-height: 420px; overflow-y: auto; }
.grp-only { padding: 0 4px; }
.grp-gone { margin: 8px 0; color: var(--muted); }

/* invites, at the top of every page: Join / Decline / Block */
.invites { display: flex; flex-direction: column; gap: 10px; }
.inv { background: var(--surface); border: 1px solid var(--ink); border-radius: 14px; padding: 14px 14px 12px 16px; box-shadow: 0 6px 22px rgba(0, 0, 0, .08); animation: here-in .32s cubic-bezier(.3, 1.4, .5, 1); }
.inv-top { display: flex; align-items: center; gap: 12px; }
.inv-q { margin: 0; font-size: 16px; line-height: 1.35; min-width: 0; }
.inv-q b { font-weight: 700; }
.inv-who { display: block; font-size: 13.5px; color: var(--muted); margin-top: 1px; }
.inv-note { margin: 8px 0 0; font-size: 13.5px; color: var(--muted); }
.inv-btns { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.inv-block { margin-left: auto; font: inherit; font-size: 13px; color: var(--muted); background: none; border: 0; padding: 6px 4px; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.inv-block:hover { color: var(--ink); }
.inv-block:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }
.inv.declined { border-color: var(--line); box-shadow: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; animation: none; }
.inv.declined .inv-q { flex: 1 1 auto; color: var(--muted); font-size: 15px; }
.inv.declined .inv-btns { margin: 0; }
.inv .me-msg { margin-top: 6px; }
/* a friend request: their avatar where an invite has the circle's emoji */
.inv .av.inv-av { width: 40px; height: 40px; font-size: 15px; flex: none; }
.inv-spots { margin-top: 4px; }

/* Everyone: search results outside your groups, and the note when you're in no group */
.brow.outside .bname b { color: var(--muted); }
.out-act { grid-column: 2 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.out-act .me-btn { min-height: 34px; padding: 6px 14px; }
.out-done, .out-make { font-size: 13px; color: var(--muted); }
.out-make { color: var(--ink); text-underline-offset: 3px; }
.balone { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; padding: 16px; border-top: 1px solid var(--line-soft); background: var(--bg); }
.balone p { margin: 0; flex: 1 1 260px; font-size: 14px; color: var(--muted); }
.balone .me-btn { text-decoration: none; display: inline-flex; align-items: center; }
/* a friend's week: the groups you share, then Remove friend */
.rel-groups { flex-basis: 100%; margin: 0; font-size: 13px; color: var(--muted); }
.rel-groups a { color: var(--ink); text-underline-offset: 3px; }
.rel-unfriend { flex-basis: 100%; margin: 4px 0 0; }
/* a circle's own spots, under its name */
.grp-spots { margin: -4px 0 12px; }
@media (max-width: 680px) {
  .out-act { grid-column: 1; padding-left: 48px; }
  .inv { padding: 12px 12px 10px 14px; }
}

/* ---------- Editing a class of yours (#week/edit/…; app.js openEditor, 27 Oct 2026) ----------
   A pencil at the top right of each of your classes in My week opens a page for that class: the course's name as the
   title in its color, the kind under it, then every group of that kind as a row to pick (the one you take first, on the
   course's fill with its radio filled; the others on white), each with its times, lecturer, the friends in it and a
   clash in red; under the one you take, a pill per class to correct it (a dialog like the location one). No outlines
   (27 Oct, user: like Today and My week since that day). Save and Cancel float over the page above the tab bar while
   there is something to save; "Saved" with Undo floats in the same place afterwards. */
.block, .wband { position: relative; }
/* a tap on a class (or a card on Today) opens the map at its time (app.js goToClass): a press shows it */
[data-go] { cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform .12s; }
.block[data-go]:active, .wband[data-go]:active, .ncard[data-go]:active { transform: scale(.98); }
[data-go]:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* the map after a class's tap: the round back button before "Everyone", on its line */
.map-head.with-back { display: flex; align-items: center; gap: 12px; }
.map-back { pointer-events: auto; }
.map-back[hidden] { display: none; }
/* (44 px: the smallest tap Apple allows, 27 Oct, user: "make the edit button tappable area larger"; 36 px before) */
.bedit {
  position: absolute; top: 0; right: 0; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  color: var(--c-text); opacity: .7; border-radius: 8px; -webkit-tap-highlight-color: transparent;
}
.bedit:hover { opacity: 1; }
.bedit:focus-visible { outline: 2px solid var(--ink); outline-offset: -6px; opacity: 1; }
.bedit .pencil { width: 16px; height: 16px; }
.block.editable .bn, .wband.editable > span:first-child { padding-right: 26px; }

#edit-view { gap: 12px; max-width: 560px; width: 100%; padding-bottom: 88px; }
#edit-view .back { align-self: flex-start; }
.edit-head { display: flex; flex-direction: column; gap: 6px; }
/* the course's name with its icon, a size under the pages' titles (27 Oct, user: "make the title slightly smaller and
   add the course icon") */
.edit-h { font-size: 30px; color: var(--c-text); overflow-wrap: anywhere; }
.edit-h .ic { width: .74em; height: .74em; vertical-align: -.04em; margin-right: .2em; }
.edit-sub { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.edit-lede { margin: 0 0 6px; }
.edit-lede[hidden] { display: none; }
.edit-list { display: flex; flex-direction: column; gap: 12px; }
/* just one group of that kind: the illustration (app.js ONE_ILL), "Only one choice here" and a line, on the page */
.eone { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 8px 12px 16px; text-align: center; }
.eone b { font-family: var(--font-display); font-size: 20px; font-weight: 700; line-height: 1.2; }
.eone p { margin: 0; max-width: 32ch; font-size: 14px; color: var(--muted); text-wrap: pretty; }
.one-ill { width: 200px; height: auto; margin-bottom: 10px; color: var(--ink); overflow: visible; }
.one-ill .o-row { fill: var(--c-fill); }
.one-ill .o-ring { fill: none; stroke: var(--c); stroke-width: 4; }
.one-ill .o-dot { fill: var(--c); }
.one-ill .o-line { fill: currentColor; opacity: .16; }
.one-ill .o-ink { fill: currentColor; }
.eopts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.eopt { border-radius: 14px; background: var(--surface); overflow: hidden; transition: background-color .15s; }
.eopt.on { background: var(--c-fill); }
.eopt-pick {
  display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 12px; width: 100%; padding: 14px; margin: 0;
  font: inherit; color: inherit; text-align: start; background: none; border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.eopt-pick:disabled { cursor: default; }
.eopt-pick:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; border-radius: 14px; }
.eradio { width: 20px; height: 20px; margin-top: 1px; border-radius: 50%; border: 2px solid color-mix(in srgb, var(--muted) 70%, transparent); box-sizing: border-box; transition: border-color .15s, box-shadow .15s; }
.eopt.on .eradio { border-color: var(--c); box-shadow: inset 0 0 0 4px var(--c-fill), inset 0 0 0 10px var(--c); }
.eopt.locked .eradio { opacity: .5; }
.eopt-main { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.eopt-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 22px; }
.eopt-top b { font-size: 15px; font-weight: 700; }
.eopt.on .eopt-top b { color: var(--c-text); }
.eopt .grp-avs { padding-left: 6px; }
.eopt .grp-avs .av { width: 22px; height: 22px; font-size: 10px; box-shadow: 0 0 0 2px var(--surface); }
.eopt.on .grp-avs .av { box-shadow: 0 0 0 2px var(--c-fill); }
.emore { margin-left: 4px; font-size: 12px; font-weight: 600; color: var(--muted); align-self: center; }
.emeet { display: flex; flex-wrap: wrap; align-items: center; column-gap: 8px; row-gap: 2px; font-size: 12.5px; color: var(--muted); }
.emeet .mono { color: var(--ink); }
.emeet .htag { color: var(--c-text); border: 0; background: color-mix(in srgb, var(--c) 18%, transparent); padding: 0 7px; }
.ewho { font-size: 12.5px; color: var(--muted); }
.eclash { font-size: 12.5px; font-weight: 600; color: var(--live); }
.efixes { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 14px 14px 46px; }
.efix {
  display: inline-flex; align-items: center; gap: 6px; font: 600 13px/1 var(--font-body); color: var(--ink); background: var(--surface);
  border: 0; border-radius: 999px; padding: 9px 13px; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.efix:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.pencil { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linejoin: round; stroke-linecap: round; }
.eonly { background: var(--surface); border-radius: 14px; padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 6px; }
.eonly .switch span { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.eonly .eye-off { width: 16px; height: 16px; }
.eonly .eye-off path, .bonly path { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.bonly { display: inline-flex; vertical-align: -2px; margin-inline-start: 5px; opacity: .75; }
.bonly svg { width: 13px; height: 13px; }

.edit-bar, .edit-toast {
  position: fixed; z-index: 30; left: 50%; transform: translateX(-50%); bottom: calc(var(--tabbar) + var(--tab-pad) + 10px);
  width: min(560px, calc(100% - 24px)); box-sizing: border-box; display: flex; align-items: center; gap: 8px;
}
.edit-bar { padding: 8px 8px 8px 16px; background: var(--surface); border-radius: 22px; box-shadow: 0 8px 30px rgba(0, 0, 0, .16); }
.edit-msg { flex: 1 1 auto; min-width: 0; margin: 0; font-size: 13.5px; font-weight: 600; color: var(--muted); }
.edit-msg.bad { color: var(--live); }
.edit-bar .me-btn { flex: none; border-color: transparent; }
.edit-bar .me-btn.ghost { background: color-mix(in srgb, var(--ink) 8%, transparent); }   /* (lighter than the black Save in the dark theme too) */
.edit-toast { padding: 8px 8px 8px 18px; color: var(--strong-ink); background: var(--strong); border-radius: 999px; box-shadow: 0 8px 30px rgba(0, 0, 0, .22); font-size: 14px; font-weight: 600; }
.edit-toast span { flex: 1 1 auto; }
.edit-toast button { flex: none; font: 600 14px/1 var(--font-body); color: inherit; background: rgba(255, 255, 255, .16); border: 0; border-radius: 999px; padding: 9px 14px; cursor: pointer; }
/* (the black toast on the dark theme's near-black: a lighter gray, in place of an outline) */
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .edit-toast { background: #333333; box-shadow: 0 8px 30px rgba(0, 0, 0, .5); } }
:root[data-theme="dark"] .edit-toast { background: #333333; box-shadow: 0 8px 30px rgba(0, 0, 0, .5); }

.fix-dlg { border: 0; }
.fix-dlg form { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.leave-dlg { display: none; }
.leave-dlg[open] { display: flex; flex-direction: column; gap: 8px; }
.leave-dlg .geo-btns { margin-top: 10px; }
.fix-dlg .me-btn { border-color: transparent; }
.fix-dlg .me-btn:not(.strong) { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.fix-what { margin: -4px 0 0; font-size: 15px; font-weight: 600; }
.fix-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 4px; }
.fix-day, .fix-b { grid-column: 1 / -1; }
.fix-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.fix-field select, .fix-field input {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 16px; font-weight: 500; color: var(--ink); background: var(--bg);
  border: 0; border-radius: 10px; padding: 9px 12px; min-height: 44px;
}
/* the dropdowns' own arrow, 16 px in from the right (3 Nov 2026, Timur: "fix the drop-down arrow position. It should be
   further from the right": the phone's own arrow sat at the edge); the ink's colour in each theme */
.fix-field select {
  -webkit-appearance: none; appearance: none; padding-right: 42px; text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 8'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%23111111' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 16px center; background-size: 13px 7.5px;
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .fix-field select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 8'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%23e5e5e5' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); } }
:root[data-theme="dark"] .fix-field select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 8'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%23e5e5e5' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
/* focused: a soft ring inside the field (3 Nov 2026, Timur, a screenshot of the Reschedule sheet: "The focus styling has
   visual bug (the border is hidden). Also make the border less contrast": the ring outside was cut off by the
   scrolling panel round it, and white on the dark field) */
.fix-field select:focus-visible, .fix-field input:focus-visible { outline: 1.5px solid color-mix(in srgb, var(--ink) 28%, transparent); outline-offset: -1.5px; }
.fix-note { margin: 2px 0 0; font-size: 13px; color: var(--muted); }
.fix-btns { flex-wrap: wrap; }
.fix-btns #fix-reset { margin-inline-end: auto; }
/* a date of a group on set dates (app.js openDate, 2 Nov 2026): Date in place of Day, Topic beside Room, and Remove
   this date (red, on its own line) over Cancel and Done */
.fix-field[hidden], #fix-del[hidden] { display: none; }
.fix-date { grid-column: 1 / -1; }
.fix-dlg.dated .fix-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.fix-dlg.dated .fix-date, .fix-dlg.dated .fix-b { grid-column: 1 / -1; }
.fix-dlg.dated .fix-from, .fix-dlg.dated .fix-to { grid-column: span 3; }
.fix-dlg.dated .fix-room { grid-column: span 2; }
.fix-dlg.dated .fix-topic { grid-column: span 4; }
.fix-field input[type="date"] { -webkit-appearance: none; appearance: none; text-align: start; }
.fix-field input[type="date"]::-webkit-date-and-time-value { text-align: start; }
.fix-field input::placeholder { color: var(--muted); }
#fix-del { margin-top: 2px; min-height: 44px; }
.fix-wd { font-weight: 500; }

/* A group of yours on set dates (app.js editDated): its dates in one card in the course's colors, each a button to
   correct it (the time under the date, the topic and the room beside them, a pencil), past ones dimmed, Add a date
   at the card's foot. The pencil on a date in My week's Classes on set dates opens it too (.dedit) */
.edates { border-radius: 14px; background: var(--c-fill); overflow: hidden; }
.edates ul { list-style: none; margin: 0; padding: 0; }
.edates li + li .edate { border-top: 1px solid color-mix(in srgb, var(--c) 18%, transparent); }
.edate {
  display: grid; grid-template-columns: 104px minmax(0, 1fr) 16px; gap: 10px; align-items: start; width: 100%; box-sizing: border-box;
  margin: 0; padding: 13px 14px; font: inherit; color: inherit; text-align: start; background: none; border: 0; border-radius: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.edate.past { opacity: .5; }
.edate:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; border-radius: 14px; }
.edate:active { background: color-mix(in srgb, var(--c) 8%, transparent); }
.edate-when { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.edate-when .mono { font-size: 14px; font-weight: 500; color: var(--ink); white-space: nowrap; }
.edate-when .mono + .mono { font-size: 12.5px; font-weight: 400; color: var(--muted); }
.edate-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.edate-topic { font-size: 14.5px; font-weight: 600; line-height: 1.35; color: var(--c-text); overflow-wrap: anywhere; }
.edate-room { font-size: 12.5px; color: var(--muted); }
.edate .pencil { width: 16px; height: 16px; margin-top: 3px; color: var(--c-text); opacity: .75; }
.edates-add { padding: 10px 14px 14px; border-top: 1px solid color-mix(in srgb, var(--c) 18%, transparent); }
.edates-add .efix { min-height: 44px; padding: 0 16px 0 14px; font-size: 14px; }
.efix .plus { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; }
#dated li.pen { position: relative; }
#dated li.pen .what { padding-right: 30px; }
#dated .dedit { top: 2px; right: 2px; }

/* ---------- Adding a course (30 Oct 2026; app.js renderAdd, editAdd) ----------
   The button under your own week, the catalogue's search (#week/add), and the course's page, which is the class
   editor's page (#edit-view) with every kind of group and the colors. */
#week-view .add-course { margin-top: -20px; }
.add-course-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; box-sizing: border-box;
  min-height: 48px; border-radius: 14px; background: var(--surface); text-decoration: none;
}
.add-course-btn:hover { background: color-mix(in srgb, var(--ink) 5%, var(--surface)) !important; }
.add-course-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
@media (min-width: 861px) { .add-course-btn { width: auto; align-self: flex-start; display: inline-flex; padding: 0 22px; } .add-course { display: flex; } }

#add-view { gap: 12px; max-width: 560px; width: 100%; padding-bottom: 24px; }
#add-view .back { align-self: flex-start; }
.add-q { flex: none; margin-top: 4px; }
.add-q input {
  width: 100%; min-width: 0; margin: 0; font: inherit; font-size: 16px; line-height: 1.25; color: var(--ink);
  background: var(--surface); border: 0; border-radius: 999px; padding: 12px 16px 12px 38px; -webkit-appearance: none; appearance: none;
}
.add-q input::placeholder { color: var(--muted); opacity: 1; }
.add-q input:focus { outline: 2px solid var(--ink); outline-offset: 2px; }
.add-q input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.add-hint { margin: -2px 0 0 16px; }
.add-head { margin: 12px 0 0; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.add-head[hidden] { display: none; }
.add-list { list-style: none; margin: 0; padding: 0; background: var(--surface); border-radius: 14px; overflow: hidden; }
.add-list:empty { display: none; }
.add-list li + li { border-top: 1px solid var(--line-soft); }
.add-row {
  display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 12px 14px 12px 12px;
  color: inherit; text-decoration: none; -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .add-row:hover { background: color-mix(in srgb, var(--ink) 3.5%, var(--surface)); } }
.add-row:active { background: color-mix(in srgb, var(--ink) 7%, var(--surface)); }
.add-row:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.add-ic { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; color: var(--ink); background: color-mix(in srgb, var(--ink) 7%, transparent); }
.add-ic .ic { width: 16px; height: 16px; margin: 0; }   /* (no .ic margin: centred in its square) */
.add-row.mine .add-ic { color: var(--muted); }
.add-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.add-name { font-size: 15px; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.add-sub { font-size: 12.5px; color: var(--muted); line-height: 1.35; overflow-wrap: anywhere; }
.add-sub .mono { color: var(--muted); }
.add-tag { align-self: flex-start; margin-top: 3px; font-size: 11.5px; font-weight: 700; color: var(--muted); background: color-mix(in srgb, var(--ink) 7%, transparent); border-radius: 999px; padding: 2px 8px; }
.add-row .grp-avs { display: flex; padding-left: 6px; }
.add-row .grp-avs .av { width: 22px; height: 22px; font-size: 10px; box-shadow: 0 0 0 2px var(--surface); }
.add-none { padding: 18px 16px; font-size: 14px; color: var(--muted); }
.add-more { margin: 2px 0 0 16px; }
.add-more[hidden] { display: none; }

/* Your program's semester and the program picker (8 Nov 2026; app.js renderSem, renderPick) */
.add-find, .add-pick { display: flex; flex-direction: column; gap: 12px; }
.add-find[hidden], .add-pick[hidden], .add-sem[hidden], .add-prog-card[hidden] { display: none; }
.add-find.typing .add-sem, .add-find.typing .add-prog-card, .add-find.typing #add-with-h, .add-find.typing #add-with { display: none; }
.add-sem { display: flex; flex-direction: column; gap: 8px; }
.add-sem-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-top: 12px; }
.add-sem-top .add-head { margin: 0; }
.add-link { font-size: 13.5px; font-weight: 600; color: var(--ink); text-decoration: none; padding: 4px 0; }
.add-link:hover { text-decoration: underline; }
.add-sem-of { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.add-sem-when { margin: -6px 0 2px; }
.add-sem-note { margin: 0; }
.add-sem-note[hidden], .add-all[hidden], .prog-auto[hidden] { display: none; }
.add-all { align-self: stretch; min-height: 46px; margin-top: 2px; }
.add-prog-card {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: 12px; row-gap: 3px; align-items: center;
  margin-top: 12px; padding: 14px 14px 14px 16px; border-radius: 14px; background: var(--surface); color: inherit; text-decoration: none;
}
.add-prog-card b { font-size: 15px; font-weight: 600; }
.add-prog-card span { grid-column: 1; font-size: 13px; color: var(--muted); line-height: 1.35; }
.add-prog-card svg { grid-column: 2; grid-row: 1 / span 2; width: 18px; height: 18px; fill: none; stroke: var(--muted); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
@media (hover: hover) { .add-prog-card:hover { background: color-mix(in srgb, var(--ink) 3.5%, var(--surface)); } }
.prog-lede { margin: 0 0 2px; }
.prog-years { display: flex; flex-wrap: wrap; gap: 8px; }
.prog-year {
  font: inherit; font-size: 14px; font-weight: 600; color: var(--ink); background: var(--surface); border: 0; border-radius: 999px;
  padding: 9px 16px; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.prog-year[aria-pressed="true"] { background: var(--strong); color: var(--strong-ink); }
.prog-list .prog-fac { padding: 14px 16px 6px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.prog-list li.prog-fac + li { border-top: 0; }
.prog-row {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px 14px 12px 16px; font: inherit; color: inherit; text-align: start;
  background: none; border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .prog-row:hover { background: color-mix(in srgb, var(--ink) 3.5%, var(--surface)); } }
.prog-row:active { background: color-mix(in srgb, var(--ink) 7%, var(--surface)); }
.prog-row:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.prog-row .add-main { flex: 1; }
.prog-row .add-tag { margin: 0; flex: none; }
.prog-auto { align-self: flex-start; }
/* a tick on each course of your semester (in or out of Add all; the row itself opens the course) */
.sem-li { position: relative; }
.sem-li .add-row { padding-right: 58px; }
.sem-tick {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; background: none; padding: 0; cursor: pointer; color: var(--strong-ink); -webkit-tap-highlight-color: transparent;
}
.sem-tick svg { width: 24px; height: 24px; box-sizing: border-box; padding: 4px; border-radius: 50%; background: var(--strong); fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.sem-tick[aria-pressed="false"] svg { background: none; stroke: transparent; box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ink) 30%, transparent); }
.sem-tick:focus-visible { outline: 2px solid var(--ink); outline-offset: -4px; border-radius: 50%; }
/* the sign-up form's program suggestions */
.su-prog-list { list-style: none; margin: -6px 0 4px; padding: 0; background: var(--surface); border-radius: 14px; overflow: hidden; box-shadow: 0 0 0 1px var(--line-soft); }
.su-prog-list[hidden] { display: none; }
.su-prog-list li + li { border-top: 1px solid var(--line-soft); }
.su-prog-row { display: flex; align-items: center; width: 100%; padding: 10px 14px; font: inherit; color: inherit; text-align: start; background: none; border: 0; cursor: pointer; }
.su-prog-row:hover, .su-prog-row:focus-visible { background: color-mix(in srgb, var(--ink) 5%, var(--surface)); }

.add-kind { display: flex; flex-direction: column; gap: 8px; }
.add-kind + .add-kind { margin-top: 8px; }
.add-kind h2 { margin: 0 0 0 4px; font-size: 18px; font-weight: 700; line-height: 1.25; }
.add-kind h2 span { margin-left: 4px; font-size: 13px; font-weight: 600; color: var(--muted); }
.add-colors { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 14px; background: var(--surface); border-radius: 14px; }
.add-color {
  width: 34px; height: 34px; border-radius: 50%; border: 0; padding: 0; cursor: pointer; background: var(--c-fill);
  box-shadow: inset 0 0 0 2px var(--c); -webkit-tap-highlight-color: transparent;
}
.add-color[aria-pressed="true"] { box-shadow: inset 0 0 0 2px var(--c), 0 0 0 2px var(--surface), 0 0 0 4px var(--c); }
.add-color:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.eremove { margin-top: 18px; }
p.eremove { margin-left: 4px; }

/* ---------- Rescheduled classes (3 Nov 2026, Timur; app.js blockHTML, movedCard, openMove) ----------
   A class moved away this week: no fill, a gray outline (the one outline in the week), "Rescheduled to …" or
   "Cancelled"; where it moved to: a class as usual with "Rescheduled from …". Today the same as cards. */
.rs-ic { fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
/* a class's ⋮ at its top right (app.js moreBtn; the friend's ⋮ on Friends, .fr-more): three 4 px dots that stretch into
   8 px bars while its menu is open, in the class's colour */
.cls-more { position: absolute; top: 0; right: 0; width: 44px; height: 44px; padding: 0; margin: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; color: var(--c-text); opacity: .75;
  -webkit-tap-highlight-color: transparent; transition: background-color .15s, opacity .15s; }
.cls-more i { display: block; width: 4px; height: 4px; border-radius: 2px; background: currentColor; transition: width .32s cubic-bezier(.34, 1.56, .64, 1); }
.cls-more[aria-expanded="true"] { opacity: 1; }
.cls-more[aria-expanded="true"] i { width: 8px; }
.cls-more[aria-expanded="true"] i:nth-child(2) { transition-delay: .03s; }
.cls-more[aria-expanded="true"] i:nth-child(3) { transition-delay: .06s; }
.cls-more:active { background: color-mix(in srgb, var(--c-text) 12%, transparent); }
.cls-more:hover { opacity: 1; }
.cls-more:focus-visible { outline: 2px solid var(--ink); outline-offset: -6px; opacity: 1; }
.block.short .cls-more { height: 36px; }
.ncard.has-more .nwhen { padding-right: 30px; }
.ncard .cls-more { top: 6px; right: 6px; }
#dated .cls-more { top: 2px; right: 2px; color: var(--ink); }
/* its menu: the friend's white popup (.fr-menu), two items in one box */
.cls-menu { z-index: 25; }
.cls-menu-box { position: relative; z-index: 1; display: flex; flex-direction: column; min-width: 190px; border-radius: 10px; background: #fff; overflow: hidden;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .14), 0 0 1px rgba(0, 0, 0, .22); }
.cls-menu .fr-menu-item { gap: 9px; padding: 13px 14px; border-radius: 0; background: transparent; box-shadow: none; color: #1c1c1e; line-height: 16px; text-decoration: none; }
.cls-menu .fr-menu-item:not([hidden]) ~ .fr-menu-item:not([hidden]) { border-top: 1px solid rgba(0, 0, 0, .08); }
.cls-menu .fr-menu-item[hidden] { display: none; }
.cls-menu .fr-menu-item.cls-del { color: #f63422; }   /* (the friend menu's Remove friend red) */
.cls-menu .fr-menu-item:active { background: #f2f2f2; }
.cls-menu .fr-menu-item:focus-visible { outline: 2px solid #1c1c1e; outline-offset: -2px; }
.cls-menu .fr-menu-ic { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .cls-menu-box { box-shadow: none; } }
:root[data-theme="dark"] .cls-menu-box { box-shadow: none; }
@media (prefers-reduced-motion: reduce) { .cls-more i { transition: none; } }
.block.moved { background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--muted) 55%, transparent); }
.block.moved .bn, .block.moved .bm, .block.moved .bk { color: var(--muted); }
.block.moved .bn .ic { opacity: .55; filter: grayscale(1); }
.bmv { display: flex; align-items: flex-start; gap: 5px; margin-top: 4px; font-size: 11.5px; line-height: 1.25; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.bmv .rs-ic, .block .bd .rs-ic { flex: none; width: 13px; height: 13px; }
.block.rs-new .bd { gap: 5px; }
.block.short .bmv { margin-top: 1px; }
.arow.moved > .t { opacity: .55; }
.ncard { position: relative; }
.ncard.moved { background: transparent; border-color: color-mix(in srgb, var(--muted) 55%, transparent); padding-block: 13px 14px; }
.ncard.moved .st { color: var(--muted); }
.ncard.moved h3 { font-size: 17px; color: var(--muted); }
.ncard.moved h3 .ic { opacity: .55; filter: grayscale(1); }
.ncard.moved .nk { color: var(--muted); }
.block.moved .cls-more, .ncard.moved .cls-more { color: var(--muted); opacity: 1; }
.nmv { display: flex; align-items: flex-start; gap: 7px; margin: 6px 0 0; font-size: 14px; line-height: 1.3; font-weight: 600; color: var(--ink); }
.nmv > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.nmv small { font-size: 14px; font-weight: 400; color: var(--muted); }
.nmv .rs-ic { flex: none; width: 16px; height: 16px; margin-top: 1px; }
.nmv.on { color: var(--c-text); font-size: 13px; margin-top: 2px; padding-right: 0; }
.nmv.on .rs-ic { width: 14px; height: 14px; }
#dated .rs-note { color: var(--ink); font-weight: 600; }
#dated .rs-note .rs-ic { flex: none; width: 13px; height: 13px; }
#dated li.cancelled .wn { color: var(--muted); }
/* Edit rescheduled (showDated): its row lights up for a moment, in the list's own corners at its ends */
#dated li.rs-flash { animation: rs-flash 1.8s ease-out both; }
#dated li.rs-flash:first-child { border-top-left-radius: 14px; border-top-right-radius: 14px; }
#dated li.rs-flash:last-child { border-bottom-left-radius: 14px; border-bottom-right-radius: 14px; }
@keyframes rs-flash { 0%, 35% { background: color-mix(in srgb, var(--ink) 10%, var(--surface)); } 100% { background: var(--surface); } }
@media (prefers-reduced-motion: reduce) { #dated li.rs-flash { background: color-mix(in srgb, var(--ink) 10%, var(--surface)); } }   /* (no fade: lit while the class is on) */
/* the sheet: the correction dialog's look (.fix-dlg). Never taller than the screen (Timur: "The popup should never
   exceed the height of the page ... the groups should have their own scroll"): the list of other groups (and the time
   panel on a very short screen) scrolls inside it, the rest stays put; the page behind doesn't scroll (html.dlg-lock,
   app.js lockPage) */
.rs-dlg { max-height: calc(100dvh - 32px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)); overscroll-behavior: contain; }
.rs-dlg[open] { display: flex; flex-direction: column; overflow: hidden; }
.rs-dlg form { gap: 12px; flex: 1 1 auto; min-height: 0; }
.rs-dlg form > * { flex: none; }
.rs-dlg form > .rs-panel { flex: 0 1 auto; min-height: 0; }
#rs-time { overflow-y: auto; overscroll-behavior: contain; }
#rs-group { overflow: hidden; }
#rs-group .rs-h { flex: none; }
.rs-opts { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; border-radius: 14px; }
html.dlg-lock { overflow: hidden; overscroll-behavior: none; }
html.dlg-lock body { overflow: hidden; }
.rs-dlg .fix-what { display: flex; align-items: center; gap: 6px; color: var(--c-text); }
.rs-dlg .fix-what .ic { flex: none; width: 16px; height: 16px; margin: 0; }
.rs-dlg .me-seg { margin: 2px 0 0; }
.rs-dlg .me-seg span { padding-inline: 4px; }
.rs-dlg .me-seg input:disabled + span { opacity: .4; }
.rs-panel { display: flex; flex-direction: column; gap: 10px; }
.rs-panel[hidden], #rs-reset[hidden], .rs-place[hidden] { display: none; }
/* the date and the time side by side (only a start: the class keeps its usual length, and the sheet doesn't say it) */
.rs-dlg .fix-grid { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); }
.rs-dlg .fix-grid .fix-date { grid-column: auto; }
.rs-where { display: flex; flex-direction: column; gap: 6px; }
.rs-h { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.rs-place { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 10px; margin-top: 4px; }
#rs-which-f[hidden] { display: none; }
.rs-dlg .me-seg[hidden] { display: none; }
.rs-opts .eopt { background: var(--bg); }
.rs-opts .eopt.on { background: var(--c-fill); }
.rs-opts .eopt-pick { padding: 12px 14px; }
.rs-opts .rs-mine .eopt-pick { cursor: default; }
.rs-opts .rs-mine .eopt-top b { color: var(--muted); }
.rs-opts .rs-mine .htag { border: 0; background: color-mix(in srgb, var(--ink) 8%, transparent); padding: 0 7px; }
.rs-opts .grp-avs .av { box-shadow: 0 0 0 2px var(--bg); }
.rs-opts .eopt.on .grp-avs .av { box-shadow: 0 0 0 2px var(--c-fill); }
.rs-none { margin: 0; font-size: 13.5px; color: var(--muted); }
.rs-dlg .fix-btns #rs-reset { margin-inline-end: auto; }

/* ---------- The 10 шек питч card on the map (8 Nov 2026; app.js renderPitch) ---------- */
/* after the ad's five boxes are all open: under the title with the other cards, the Map tab only, in the ad's own look
   (its dark box, Unbounded title with the number in gold, its greens) in both themes */
.pitch { display: flex; align-items: center; gap: 10px; padding: 10px 10px 10px 16px; border: 1.5px solid #3A3A3A; border-radius: 14px; background: #0B0B0B; color: #F2F2F2; box-shadow: 0 2px 10px rgba(0, 0, 0, .14); animation: here-in .32s cubic-bezier(.3, 1.4, .5, 1); }
.pitch[hidden], body:not([data-view="friends"]) .pitch { display: none; }
.pitch-t { flex: 1 1 auto; min-width: 0; margin: 0; font-family: 'Unbounded', system-ui, sans-serif; font-weight: 800; font-size: 15px; line-height: 20px; letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pitch-t .n { color: #E9B949; }
.pitch-go { flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: 38px; padding: 0 16px; border: 0; border-radius: 999px; background: #4E9A58; color: #fff; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pitch-go[aria-pressed="true"] { background: transparent; color: #7DD08A; box-shadow: inset 0 0 0 1.5px #4E9A58; }
.pitch-go:disabled { opacity: .6; cursor: default; }
.pitch-go svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.pitch-x { flex: none; width: 38px; height: 38px; border: 0; border-radius: 50%; background: rgba(255, 255, 255, .08); color: #F2F2F2; display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pitch-x:hover { background: rgba(255, 255, 255, .14); }
.pitch-x svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

/* ---------- A circle's own spots, made by gathering (5 Nov 2026; app.js "A circle's own spots") ---------- */
/* the card on the Map tab only (option B, Seats), under the title with the other cards */
.gather { display: flex; flex-direction: column; gap: 10px; }
.gather[hidden], body:not([data-view="friends"]) .gather, body.gather-open .gather { display: none; }
.g-card { background: var(--surface); border-radius: 14px; padding: 12px 12px 12px 14px; display: flex; flex-direction: column; gap: 10px; box-shadow: 0 2px 10px rgba(0, 0, 0, .08); }   /* no outline (7 Nov 2026, Timur) */
.g-card.asking { box-shadow: 0 6px 22px rgba(0, 0, 0, .12); animation: here-in .32s cubic-bezier(.3, 1.4, .5, 1); }
.g-x { width: 40px; height: 40px; margin: -8px -6px -8px -4px; flex: none; border: 0; border-radius: 50%; background: transparent; color: var(--muted); display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }   /* Not now */
.g-x:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); color: var(--ink); }
.g-top { display: flex; align-items: center; gap: 10px; }
.g-tile { width: 40px; height: 40px; border-radius: 12px; background: var(--bg); color: var(--ink); display: grid; place-items: center; flex: none; }
.g-ok { color: var(--p-green); font-size: 20px; }
.g-who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.g-sub { font-size: 12.5px; color: var(--muted); line-height: 1.35; }
.g-title { font-size: 16.5px; line-height: 1.25; }
.g-left { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.g-seats { display: flex; align-items: center; gap: 5px; }
.g-seats .av.sm, .g-seat.sm { width: 30px; height: 30px; font-size: 11.5px; }
.g-seats .av.me { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--ink); }
.g-seat { border-radius: 50%; border: 1.5px dashed color-mix(in srgb, var(--ink) 30%, transparent); box-sizing: border-box; flex: none; }
.g-count { margin-left: 6px; font-size: 14px; }
.g-names { display: flex; flex-wrap: wrap; gap: 6px; }
.g-name { display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 0 10px; border-radius: 999px; background: var(--bg); font-size: 13.5px; font-weight: 700; }
.g-name.mine { background: var(--ink); color: var(--surface); }
.g-dots { display: inline-flex; gap: 3px; }
.g-dots i { width: 6px; height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--ink) 18%, transparent); box-sizing: border-box; }
.g-dots i.on { background: var(--ink); }
.g-dots i.you { background: transparent; border: 1.6px solid var(--ink); }
.g-name.mine .g-dots i { background: color-mix(in srgb, var(--surface) 35%, transparent); }
.g-name.mine .g-dots i.on { background: var(--surface); }
.g-foot { display: flex; align-items: center; gap: 8px; }
.g-note { margin: 0; flex: 1 1 auto; font-size: 13px; color: var(--muted); line-height: 1.35; }
.g-big { font: inherit; font-size: 15px; font-weight: 700; min-height: 46px; border-radius: 999px; border: 0; cursor: pointer; color: var(--surface); background: var(--ink); }
.g-done .g-title { font-size: 15.5px; }
/* the vote, at the bottom of the Map tab (the half sheet: the map stays visible and framed above it) */
.gsheet {
  position: fixed; z-index: 18; left: 0; right: 0; margin: 0 auto; max-width: 560px; bottom: calc(var(--tabbar) + var(--tab-pad) - 6px);
  max-height: calc(var(--win-h) - var(--title-top) - var(--tabbar) - var(--tab-pad) - 120px); overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); border-radius: 22px 22px 18px 18px; box-shadow: 0 -6px 24px rgba(0, 0, 0, .14);
  padding: 8px 16px 12px; box-sizing: border-box; display: flex; flex-direction: column; gap: 10px;
}
.gsheet[hidden], body:not([data-view="friends"]) .gsheet { display: none; }
body.gather-open .sheet { visibility: hidden; }
.gs-grab { width: 36px; height: 5px; border-radius: 3px; background: var(--line); margin: 0 auto; flex: none; }
.gs-head { display: flex; align-items: center; gap: 8px; }
.gs-ht { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.gs-h { font-family: var(--font-display); font-size: 19px; line-height: 1.2; flex: 1 1 auto; }
.gs-sub, .gs-note, .gs-count { font-size: 12.5px; color: var(--muted); line-height: 1.35; }
.gs-count { white-space: nowrap; }
.gs-note { margin: 0; text-align: center; }
.gs-icon { width: 40px; height: 40px; flex: none; border: 0; border-radius: 50%; background: transparent; color: var(--ink); display: grid; place-items: center; cursor: pointer; margin: 0 -8px; }
.gs-rows { display: flex; flex-direction: column; gap: 6px; }
.gs-row { font: inherit; color: var(--ink); text-align: left; display: flex; align-items: center; gap: 10px; min-height: 50px; padding: 0 12px; border-radius: 14px; border: 1px solid var(--line); background: var(--surface); cursor: pointer; }
.gs-row.on { border: 2px solid var(--ink); padding: 0 11px; }
.gs-row .gs-emo { font-size: 19px; }
.gs-name { flex: 1 1 auto; min-width: 0; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gs-tag { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--surface); background: var(--ink); border-radius: 999px; padding: 2px 7px; white-space: nowrap; }
.gs-voters { display: flex; align-items: center; }
.gs-voters .av.xs { width: 20px; height: 20px; font-size: 8.5px; box-shadow: 0 0 0 1.5px var(--surface); }
.gs-voters .av.xs + .av.xs { margin-left: -5px; }
.gs-voters i { font-style: normal; font-size: 11px; color: var(--muted); margin-left: 3px; }
.gs-n { font-size: 13px; width: 30px; text-align: right; }
.gs-btns { display: flex; gap: 8px; }
.gs-sug { font: inherit; font-size: 14px; font-weight: 700; min-height: 48px; padding: 0 16px; border-radius: 999px; border: 1px dashed color-mix(in srgb, var(--ink) 35%, transparent); background: transparent; color: var(--ink); white-space: nowrap; cursor: pointer; }
.gs-go { flex: 1 1 auto; font: inherit; font-size: 15px; font-weight: 700; min-height: 48px; padding: 0 14px; border-radius: 999px; border: 0; color: var(--surface); background: var(--ink); cursor: pointer; }
.gs-go:disabled { opacity: .45; cursor: default; }
.gs-go.ghost { color: var(--ink); background: transparent; border: 1px solid var(--line); }
.gs-msg { margin: 0; font-size: 13px; color: var(--live); text-align: center; }
.gs-msg:empty { display: none; }
.gs-form { display: flex; flex-direction: column; gap: 10px; }
.gs-field, .spot-field { display: flex; align-items: center; gap: 10px; background: var(--bg); border-radius: 12px; padding: 4px 4px 4px 6px; }
.gs-field:focus-within, .spot-field:focus-within { box-shadow: 0 0 0 2px var(--ink) inset; }
.gs-field .gs-emo, .spot-now { width: 38px; height: 38px; border-radius: 10px; background: var(--surface); display: grid; place-items: center; font-size: 21px; flex: none; }
.gs-field input, .spot-field input { flex: 1 1 auto; min-width: 0; font: inherit; font-size: 16px; font-weight: 600; border: 0; background: transparent; color: var(--ink); padding: 9px 4px; outline: none; }
.spot-emojis { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 4px; }
.spot-emo { font: inherit; aspect-ratio: 1; min-height: 32px; border-radius: 10px; border: 0; background: var(--bg); font-size: 19px; display: grid; place-items: center; padding: 0; cursor: pointer; }
.spot-emo.on { background: var(--surface); box-shadow: 0 0 0 2px var(--ink) inset; }
/* someone at a gathering, on the map: their vote's emoji on their avatar's top right */
.av.voted { overflow: visible; }
.av .vb { position: absolute; z-index: 3; right: -7px; top: -6px; width: 16px; height: 16px; border-radius: 50%; background: var(--surface); display: grid; place-items: center;
  font-style: normal; font-size: 10px; line-height: 1; box-shadow: 0 1px 3px rgba(0, 0, 0, .25); pointer-events: none; }
/* a circle's page: Spots */
.spot-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; }
.spot-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.spot-row + .spot-row { border-top: 1px solid var(--line-soft); }
.spot-tile { width: 40px; height: 40px; border-radius: 12px; background: var(--bg); display: grid; place-items: center; font-size: 21px; flex: none; color: var(--ink); }
.spot-t { flex: 1 1 140px; min-width: 0; display: flex; flex-direction: column; }
.spot-t b { font-size: 15px; }
.spot-act { font: inherit; font-size: 13.5px; font-weight: 600; min-height: 38px; padding: 0 10px; border: 0; border-radius: 999px; background: transparent; color: var(--ink); cursor: pointer; }
.spot-act.icon { width: 40px; padding: 0; display: grid; place-items: center; }
.spot-act.danger { color: var(--live); }
.spot-acts { display: flex; flex-wrap: wrap; gap: 2px; margin: 2px 0 -6px -10px; }   /* Rename · Delete under who started it */
.spot-acts .spot-act { min-height: 36px; }
.spot-row.editing { display: block; }
.spot-form { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.spot-row.editing .spot-form { margin-top: 0; }
.spot-fh { font-size: 15px; }
.spot-make { margin-top: 10px; align-self: stretch; min-height: 46px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; font-size: 15px; }
.spot-how, .spot-why { margin-top: 8px; }
@media (max-width: 380px) { .spot-emojis { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* The bot check (Cloudflare Turnstile, app.js loadTurnstile): shows only when Cloudflare asks for a tap, under the card */
.ts-box { display: flex; justify-content: center; margin-top: 12px; }
.ts-box:empty { display: none; }
