Files
kokkoja-rel/client/kokkoja.css
T
ackandClaude Fable 5.1 87ba7fc776 Tooltips in the Notebooks chooser
From the development repository at e819bc4.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-11 18:05:49 +02:00

585 lines
15 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
:root {
--ink: #1c1c1e;
--muted: #6b6b70;
--line: #d4d4d8;
--panel: #f6f6f7;
--desk: #e4e4e7;
--accent: #1f4fd8;
--text_frame: #e53935; /* A text rectangle's frame: the palette's red. */
font-family: system-ui, sans-serif;
font-size: 15px;
color: var(--ink);
}
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
[hidden] { display: none !important; }
button, input { font: inherit; color: inherit; }
/* A drag across the controls selects nothing: their text is not for
copying (Andy, 2026-10-07). Fields stay selectable. Safari on iOS
and iPadOS knows only the prefixed property (MDN's compatibility
data, 2026-10-10); without it the Pencil's first movement sometimes
selected the save status on Andy's iPad. */
button, select, label, .toolbar, .panel h2, #participants, .chooser header
{ -webkit-user-select: none; user-select: none; }
button {
padding: 0.35rem 0.8rem;
border: 1px solid var(--line);
border-radius: 6px;
background: white;
cursor: pointer;
}
button:hover { border-color: var(--muted); }
button[aria-pressed="true"] {
border-color: var(--accent);
box-shadow: inset 0 0 0 1px var(--accent);
}
input[type="text"], select.notebook_pick {
width: 100%;
padding: 0.4rem 0.5rem;
border: 1px solid var(--line);
border-radius: 6px;
background: white;
font: inherit;
color: inherit;
}
h2 {
margin: 1.4rem 0 0.4rem;
font-size: 0.8rem;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--muted);
}
/* Start screen */
#start {
max-width: 28rem;
margin: 0 auto;
padding: 3rem 1.5rem;
}
#start h1 { margin: 0 0 1.5rem; font-size: 1.6rem; }
#start label { display: block; margin: 1rem 0 0.3rem; }
#start section { margin-top: 1.5rem; }
#start section p { margin: 0 0 0.6rem; color: var(--muted); }
#start section button { margin-top: 0.6rem; }
.message { min-height: 1.4em; margin-top: 1.5rem; color: #b42318; }
.note { margin: 0.3rem 0 0; font-size: 0.85rem; color: var(--muted); overflow-wrap: anywhere; }
.note.problem { color: #b42318; }
.file { margin: 0; overflow-wrap: anywhere; }
/* Session */
#session {
display: flex;
flex-direction: column;
height: 100%;
}
/* One row, holding everything (Andy's teacher, 2026-10-08: the whole
width of the window belongs to the page); it wraps only when the window
is too narrow for it. */
.toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem 0.55rem;
padding: 0.4rem 0.5rem;
border-bottom: 1px solid var(--line);
background: var(--panel);
}
/* Three groups (Andy, 2026-10-11): the drawing tools with their settings
and Undo on the left; the page and the view in the middle, centred
between the other two; the session's buttons flush right. The
drawing group keeps the width of its widest state (main.js sets its
min-width by measuring), so that the middle group stays put when the
tool changes. */
.drawing, .settings { display: flex; align-items: center; gap: 0.5rem 0.55rem; }
/* Twice the gap before Eraser, Hide and Undo, so that with the pen the
widest line and the Eraser read as two groups (Andy, 2026-10-11). */
.drawing .after_settings { margin-left: 0.55rem; }
.toolbar .page_view { margin-left: auto; margin-right: auto; }
/* When the window is too narrow for one row, the tools are centred
instead of standing at the two ends (Andy, 2026-10-09; main.js sets
the class by measuring). */
.toolbar.wrapped { justify-content: center; }
.toolbar.wrapped .page_view { margin-left: 0; margin-right: 0; }
.toolbar.wrapped .toolbar_right { margin-left: 0; justify-content: center; }
/* 9rem wide until 2026-10-11: room for Undo. The buttons' height, else
this select, 36 px tall by its own padding, sets the row's height and
the buttons' trimming gains nothing (measured 2026-10-11). */
.toolbar .notebook_pick, .toolbar #session_notebook_name {
width: 7.2rem;
height: calc(2rem - 2px);
padding-top: 0;
padding-bottom: 0;
box-sizing: border-box;
}
.toolbar .toggle { display: flex; align-items: center; gap: 0.3rem; cursor: pointer; }
.toolbar .toggle input { margin: 0; }
.group { display: flex; align-items: center; gap: 0.35rem; }
.swatch {
width: 1.5rem;
height: 1.5rem;
padding: 3px;
border-radius: 50%;
background: var(--swatch);
background-clip: content-box;
}
/* The same height as the buttons, so the toolbar does not change height;
narrow enough that a host's toolbar fits a 1920-pixel screen in one
row (measured 2026-10-09: about 1750 pixels with these settings).
Since 2026-10-11 two pixels less in height and on each side than
2rem and 0.6rem, for room (Andy, in two steps of a pixel). */
.toolbar button:not(.swatch), #text_size, #text_font {
box-sizing: border-box;
height: calc(2rem - 2px);
padding-top: 0;
padding-bottom: 0;
}
.toolbar button:not(.swatch) { padding-left: calc(0.6rem - 2px); padding-right: calc(0.6rem - 2px); }
#text_size, #text_font {
margin: 0;
padding-left: 0.4rem;
padding-right: 0.4rem;
border: 1px solid var(--line);
border-radius: 6px;
background: white;
font: inherit;
}
#text_size { width: 3.6rem; }
#text_font { padding-right: 0.3rem; }
/* The palette that "+" opens: no system dialog, which crashes Firefox on
Linux (Hollis, 2026-10-04). */
.palette {
position: absolute;
z-index: 5;
display: grid;
grid-template-columns: repeat(8, 1.5rem);
gap: 0.3rem;
padding: 0.5rem;
border: 1px solid var(--line);
border-radius: 8px;
background: white;
box-shadow: 0 4px 16px rgb(0 0 0 / 0.2);
}
.palette .swatch { width: 1.5rem; height: 1.5rem; }
/* A colour already in the toolbar leaves its place in the grid empty. */
.palette .swatch.missing { visibility: hidden; }
.swatch.more {
--swatch: white;
font-size: 1rem;
line-height: 1;
color: var(--muted);
}
.width_choice {
display: flex;
align-items: center;
justify-content: center;
width: 2.4rem;
height: 1.9rem;
padding: 0;
}
.width_choice span {
display: block;
width: 1.4rem;
border-radius: 99px;
background: var(--ink);
}
/* The page, the notebook and the session: flush right, the page number
and what is going on at the very end (Andy, 2026-10-08). */
.toolbar_right {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem 0.55rem;
margin-left: 0; /* auto until 2026-10-11; the middle group's margins push it right now. */
min-width: 0;
}
/* The notice line between the toolbar and the page: nothing, and no
room, while all is well; a problem in red while it lasts; a
confirmation for a few seconds (Andy, 2026-10-10: the toolbar's
"Page 3 Connected Saved at …" was noise, and the room is needed for
one row). */
.notice {
padding: 0.3rem 1rem;
border-bottom: 1px solid var(--line);
background: var(--panel);
text-align: center;
font-size: 0.9rem;
color: var(--muted);
}
.notice.problem { color: #b42318; }
/* The quiet facts in the Session window: the page, the connection, the
last save. */
.session_state span { margin-right: 1rem; white-space: nowrap; }
.session_state .problem { color: #b42318; }
.workspace {
display: flex;
flex: 1;
min-height: 0;
}
.desk {
flex: 1;
min-width: 0;
overflow: auto;
padding: 0.5rem;
background: var(--desk);
}
/* The cue around an image being moved or scaled by hand: green, with a
square at the corner being dragged. */
.image_grip {
position: absolute;
z-index: 3;
box-sizing: border-box;
border: 2px solid #2e7d32;
pointer-events: none;
}
.image_grip.corner::after {
content: "";
position: absolute;
left: var(--corner-x);
top: var(--corner-y);
width: 12px;
height: 12px;
transform: translate(-50%, -50%);
background: #2e7d32;
}
.page {
position: relative;
margin: 0 auto;
background: white;
box-shadow: 0 1px 4px rgb(0 0 0 / 0.25);
touch-action: none;
-webkit-user-select: none; /* Safari on iOS: see the controls rule. */
user-select: none;
-webkit-touch-callout: none; /* No callout from a long press of the Pencil. */
cursor: crosshair;
}
.page canvas, .page_image {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
/* Text being edited */
.text_field {
position: absolute;
z-index: 2;
box-sizing: content-box;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
background: transparent;
resize: none;
overflow: hidden;
outline: none;
}
/* A rectangle being dragged open, for text or for Hide. */
.rect_preview {
position: absolute;
z-index: 3;
box-sizing: border-box;
border: 2px dotted #ababab;
pointer-events: none;
}
/* The field of a text rectangle shows its frame and white ground itself,
since the renderer leaves the block out while it is edited. */
.text_field.rect {
background: white;
outline-style: solid;
outline-color: var(--text_frame);
}
/* Free text's corner mark while it is edited: an L at its top-left corner. */
.text_mark {
position: absolute;
z-index: 3;
box-sizing: border-box;
border-style: solid none none solid;
border-color: var(--text_frame);
pointer-events: none;
}
/* The Session dialog: who is here, and the invitation. */
/* fit-content, not auto: a modal dialog has its top and bottom pinned by
the browser's own style, so an auto height filled the window up to the
maximum (seen 2026-10-10: 1100 px of dialog around 350 px of content). */
.chooser.session { width: min(32rem, 90vw); height: fit-content; max-height: 85vh; }
.session_body h3 { margin: 1rem 0 0.4rem; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.session_body ul { margin: 0; padding: 0; list-style: none; }
.session_body li {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.2rem 0;
}
.session_body li.absent { color: var(--muted); }
.session_body li label { flex: 1; }
.session_body li .role { font-size: 0.8rem; color: var(--muted); }
.session_body li .allow_line { order: 1; display: flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; color: var(--muted); cursor: pointer; }
.session_body li .allow_line input { margin: 0; }
.invitation_line { display: flex; gap: 0.5rem; align-items: center; }
.invitation_line input { flex: 1; min-width: 0; }
/* The invitation as a QR code, for the camera of a phone or a tablet. */
.invitation_code { width: min(13rem, 60vw); margin: 0.75rem auto 0; }
.invitation_code svg { display: block; width: 100%; height: auto; }
/* The log, the latest entry at the bottom and in view, selectable. */
.log_line { display: flex; gap: 0.5rem; align-items: flex-start; }
.event_log {
flex: 1;
min-width: 0;
margin: 0;
max-height: 10rem;
overflow: auto;
padding: 0.3rem 0.4rem;
border: 1px solid var(--line);
border-radius: 6px;
font-size: 0.7rem;
line-height: 1.35;
color: var(--muted);
white-space: pre;
-webkit-user-select: text;
user-select: text;
}
/* The notebook chooser */
.chooser {
width: min(56rem, 90vw);
height: min(36rem, 85vh);
padding: 1rem 1.25rem;
border: 1px solid var(--line);
border-radius: 10px;
box-shadow: 0 8px 30px rgb(0 0 0 / 0.25);
}
.chooser::backdrop { background: rgb(0 0 0 / 0.3); }
.chooser header { display: flex; align-items: center; }
.chooser header h2 { flex: 1; margin: 0; }
.chooser header button { width: 2rem; padding: 0.2rem 0; font-size: 1.1rem; line-height: 1; }
/* The notebook chooser's title takes the width of the notebook column,
so that the Delete button starts where the page cards start, away
from the close mark, which stays at the right (Andy, 2026-10-11).
The button is shaped like the notebook buttons on the left, and the
header is as tall as such a button (its line box, padding and
borders) whether the button is shown or not, so that the body does
not move when it appears. */
#notebook_chooser header { min-height: calc(1lh + 0.7rem + 2px); }
#notebook_chooser header h2 { flex: 0 0 13rem; }
#notebook_chooser header #chooser_close { margin-left: auto; }
.chooser header button.delete {
width: auto;
padding: 0.35rem 0.8rem;
font-size: inherit;
line-height: normal;
color: #b42318;
}
.chooser_body {
display: flex;
gap: 1rem;
height: calc(100% - 4rem);
margin-top: 0.75rem;
}
.chooser_notebooks {
display: flex;
flex-direction: column;
gap: 0.3rem;
width: 12rem;
overflow: auto;
}
.chooser_notebooks button.notebook_pick { flex: 1; min-width: 0; text-align: left; }
/* Rows and cards carry a mark at their left, ×, for deletion (at the
right it would read as "delete" itself, Andy); marked, they dim. */
.notebook_row { display: flex; gap: 0.3rem; align-items: stretch; }
.notebook_row.marked button.notebook_pick, .page_slot.marked .page_card { opacity: 0.45; }
.page_slot { position: relative; display: flex; }
.page_slot .page_card { flex: 1; }
button.mark {
width: 1.6rem;
padding: 0;
font-size: 1.1rem;
line-height: 1;
color: var(--muted);
}
.page_slot button.mark {
position: absolute;
top: 0.3rem;
left: 0.3rem;
height: 1.6rem;
background: white;
/* Above the card even when the card's opacity makes it a stacking
context painted later: without this, the second tap, to unmark,
landed on the dimmed card and loaded the page. */
z-index: 1;
}
button.mark[aria-pressed="true"] { color: #b42318; }
button.mark.unavailable { opacity: 0.4; }
.chooser_pages {
display: grid;
flex: 1;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
gap: 0.75rem;
align-content: start;
overflow: auto;
}
.page_card {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.4rem;
padding: 0.5rem;
}
.page_card img {
width: 100%;
aspect-ratio: 210 / 297;
object-fit: contain;
background: var(--desk);
}
.page_card span { font-size: 0.8rem; }
/* The file chooser */
#file_chooser[open] { display: flex; flex-direction: column; }
.files_place, .files_save {
display: flex;
gap: 0.5rem;
margin-top: 0.75rem;
}
.files_place input, .files_save input { flex: 1; min-width: 0; }
/* Directories down the left, one to a line; the files beside them. Each
scrolls by itself, as in the notebook chooser. */
.files_body {
display: flex;
flex: 1;
gap: 1rem;
min-height: 0;
margin-top: 0.75rem;
}
.files_directories {
display: flex;
flex: none;
flex-direction: column;
gap: 0.3rem;
width: 12rem;
overflow: auto;
}
.files_directories button { text-align: left; overflow-wrap: anywhere; }
.files_entries {
flex: 1;
overflow: auto;
}
.files_existing {
display: flex;
flex-wrap: wrap;
gap: 0.3rem;
}
.files_images {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
gap: 0.75rem;
align-content: start;
}
.file_card {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.4rem;
padding: 0.5rem;
}
.file_card canvas {
width: 100%;
aspect-ratio: 4 / 3;
object-fit: contain;
background: var(--desk);
}
.file_card span { font-size: 0.8rem; overflow-wrap: anywhere; }
.tooltip {
position: fixed;
z-index: 10;
max-width: 20rem;
padding: 0.4rem 0.6rem;
border-radius: 6px;
background: var(--ink);
color: white;
font-size: 0.85rem;
line-height: 1.35;
white-space: pre-line; /* A page card's tooltip has several lines. */
box-shadow: 0 2px 8px rgb(0 0 0 / 0.25);
pointer-events: none;
}
.report {
margin-top: 1.5rem;
font-size: 0.8rem;
color: var(--muted);
font-variant-numeric: tabular-nums;
}