Kokkoja as of 2026-10-10: the teacher's requests, the Session window, notices, the QR code, the license

This commit is contained in:
ack committed 2026-10-10 19:01:20 +02:00
1 parent 95c80d04c9
commit 1d087af633
32 files changed
+4917 -890

No files matched your search

+135 -70
View File
@@ -5,8 +5,7 @@
--panel: #f6f6f7;
--desk: #e4e4e7;
--accent: #1f4fd8;
--text_edge: #ababab; /* The top edge of a text block being edited: 67% grey. */
--text_handle: #ababab; /* Its squares: the same. */
--text_frame: #e53935; /* A text rectangle's frame: the palette's red. */
font-family: system-ui, sans-serif;
font-size: 15px;
color: var(--ink);
@@ -20,6 +19,14 @@ html, body { height: 100%; margin: 0; }
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);
@@ -35,12 +42,14 @@ button[aria-pressed="true"] {
box-shadow: inset 0 0 0 1px var(--accent);
}
input[type="text"] {
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 {
@@ -80,15 +89,29 @@ h2 {
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: 1.25rem;
padding: 0.5rem 0.75rem;
gap: 0.5rem 0.55rem;
padding: 0.4rem 0.5rem;
border-bottom: 1px solid var(--line);
background: var(--panel);
}
/* 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 .toolbar_right { margin-left: 0; justify-content: center; }
.toolbar .notebook_pick { width: 9rem; }
.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 {
@@ -100,13 +123,16 @@ h2 {
background-clip: content-box;
}
/* The same height as the buttons, so the toolbar does not change height. */
/* 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). */
.toolbar button:not(.swatch), #text_size, #text_font {
box-sizing: border-box;
height: 2rem;
padding-top: 0;
padding-bottom: 0;
}
.toolbar button:not(.swatch) { padding-left: 0.6rem; padding-right: 0.6rem; }
#text_size, #text_font {
margin: 0;
@@ -137,6 +163,8 @@ h2 {
}
.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;
@@ -161,24 +189,36 @@ h2 {
background: var(--ink);
}
#zoom_in, #zoom_out {
width: 2.2rem;
padding: 0.1rem 0;
font-size: 1.35rem;
line-height: 1;
}
/* What concerns the page and the view, not the tool: it never moves. */
/* 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: 1.25rem;
gap: 0.5rem 0.55rem;
margin-left: auto;
min-width: 0;
}
.page_number { color: var(--muted); }
.status { min-width: 6.5rem; text-align: right; color: var(--muted); }
.status.problem { color: #b42318; }
/* 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;
@@ -190,17 +230,40 @@ h2 {
flex: 1;
min-width: 0;
overflow: auto;
padding: 1.25rem;
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;
}
@@ -228,75 +291,78 @@ h2 {
outline: none;
}
.text_handle {
/* A rectangle being dragged open, for text or for Hide. */
.rect_preview {
position: absolute;
z-index: 3;
width: 10px;
height: 10px;
margin: -5px 0 0 -5px;
border: 1px solid white;
border-radius: 2px;
background: var(--text_handle);
cursor: move;
box-sizing: border-box;
border: 2px dotted #ababab;
pointer-events: none;
}
.text_handle.end { cursor: ew-resize; }
/* 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);
}
.text_edge {
/* Free text's corner mark while it is edited: an L at its top-left corner. */
.text_mark {
position: absolute;
z-index: 3;
height: 0;
margin-top: -1px;
border-top: 2px solid var(--text_edge);
cursor: move;
}
.text_edge::before, .text_edge::after {
content: "";
position: absolute;
top: 0;
width: 0;
height: 8px;
border-left: 2px solid var(--text_edge);
}
.text_edge::before { left: 0; }
.text_edge::after { right: 0; }
/* The top edge of a new block, while it is being dragged out. */
.text_preview {
position: absolute;
z-index: 3;
height: 0;
margin-top: -1px;
border-top: 2px solid var(--text_edge);
box-sizing: border-box;
border-style: solid none none solid;
border-color: var(--text_frame);
pointer-events: none;
}
.panel {
width: 16rem;
padding: 0 1rem 1rem;
overflow: auto;
border-left: 1px solid var(--line);
background: var(--panel);
}
/* The Session dialog: who is here, and the invitation. */
.panel ul { margin: 0; padding: 0; list-style: none; }
/* 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; }
.panel li {
.session_body li {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.2rem 0;
}
.panel li.absent { color: var(--muted); }
.panel li label { flex: 1; }
.panel li .role { font-size: 0.8rem; color: var(--muted); }
.panel li .allow { order: 1; padding: 0.1rem 0.4rem; font-size: 0.75rem; }
.panel button { margin-top: 0.4rem; }
.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 */
@@ -396,7 +462,6 @@ h2 {
overflow: auto;
}
.files_shrink { display: block; margin-top: 0.75rem; font-size: 0.9rem; }
.files_existing {
display: flex;