glideshow 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- glideshow/__init__.py +15 -0
- glideshow/__main__.py +3 -0
- glideshow/agent.py +681 -0
- glideshow/build.py +54 -0
- glideshow/cli.py +320 -0
- glideshow/comments.py +35 -0
- glideshow/decks.py +230 -0
- glideshow/docs/agents.md +223 -0
- glideshow/docs/deck-format.md +125 -0
- glideshow/editor/.assetsignore +5 -0
- glideshow/editor/apple-touch-icon.png +0 -0
- glideshow/editor/data/font-metrics.json +1 -0
- glideshow/editor/data/fonts.json +1 -0
- glideshow/editor/data/icons.json +1 -0
- glideshow/editor/data/symbols.js +42 -0
- glideshow/editor/data/themes.js +15 -0
- glideshow/editor/deck/base.css +92 -0
- glideshow/editor/deck/present.js +222 -0
- glideshow/editor/deck/shapes.js +377 -0
- glideshow/editor/deck/template.html +37 -0
- glideshow/editor/editor.css +657 -0
- glideshow/editor/glideshow-1024.png +0 -0
- glideshow/editor/glideshow.svg +10 -0
- glideshow/editor/globals.d.ts +21 -0
- glideshow/editor/home.html +358 -0
- glideshow/editor/index.html +386 -0
- glideshow/editor/js/arrange.js +122 -0
- glideshow/editor/js/boot.js +66 -0
- glideshow/editor/js/boxes.js +25 -0
- glideshow/editor/js/comments.js +85 -0
- glideshow/editor/js/context-menus.js +93 -0
- glideshow/editor/js/dialogs.js +168 -0
- glideshow/editor/js/dock.js +22 -0
- glideshow/editor/js/draw.js +107 -0
- glideshow/editor/js/file.js +318 -0
- glideshow/editor/js/find.js +72 -0
- glideshow/editor/js/format-panel.js +101 -0
- glideshow/editor/js/geometry.js +153 -0
- glideshow/editor/js/guides.js +37 -0
- glideshow/editor/js/insert.js +73 -0
- glideshow/editor/js/keyboard.js +256 -0
- glideshow/editor/js/live.js +48 -0
- glideshow/editor/js/menubar.js +290 -0
- glideshow/editor/js/menus.js +93 -0
- glideshow/editor/js/motion.js +148 -0
- glideshow/editor/js/notes.js +63 -0
- glideshow/editor/js/objects.js +202 -0
- glideshow/editor/js/people.js +73 -0
- glideshow/editor/js/phone-comments.js +43 -0
- glideshow/editor/js/phone-edit.js +253 -0
- glideshow/editor/js/phone-home.js +51 -0
- glideshow/editor/js/phone-mode.js +73 -0
- glideshow/editor/js/phone-sheets.js +153 -0
- glideshow/editor/js/phone-touch.js +145 -0
- glideshow/editor/js/phone-view.js +150 -0
- glideshow/editor/js/pointer.js +407 -0
- glideshow/editor/js/render.js +353 -0
- glideshow/editor/js/shortcuts.js +67 -0
- glideshow/editor/js/slides.js +120 -0
- glideshow/editor/js/spacing.js +23 -0
- glideshow/editor/js/state.js +58 -0
- glideshow/editor/js/storage.js +250 -0
- glideshow/editor/js/text.js +366 -0
- glideshow/editor/js/theme-toggle.js +41 -0
- glideshow/editor/js/theme.js +173 -0
- glideshow/editor/js/toolbar-groups.js +109 -0
- glideshow/editor/js/toolbar.js +372 -0
- glideshow/editor/lib/browser-db.js +47 -0
- glideshow/editor/lib/library.js +612 -0
- glideshow/editor/lib/merge.js +174 -0
- glideshow/editor/lib/move-local.js +51 -0
- glideshow/editor/lib/onefile.js +108 -0
- glideshow/editor/lib/store-browser.js +75 -0
- glideshow/editor/lib/store-folder.js +109 -0
- glideshow/editor/local/sw.js +66 -0
- glideshow/editor/local/tsconfig.json +5 -0
- glideshow/editor/looks/glider.svg +9 -0
- glideshow/editor/looks/thermal-phone.css +144 -0
- glideshow/editor/looks/thermal.css +268 -0
- glideshow/editor/manifest.json +23 -0
- glideshow/editor/phone.css +345 -0
- glideshow/editor/share/share.css +124 -0
- glideshow/editor/share/share.js +256 -0
- glideshow/editor/share/speaker.html +88 -0
- glideshow/editor/tsconfig.json +6 -0
- glideshow/figure.py +33 -0
- glideshow/fonts.py +63 -0
- glideshow/gslides.py +1065 -0
- glideshow/history.py +210 -0
- glideshow/merge.py +210 -0
- glideshow/osutil.py +44 -0
- glideshow/pptx_export.py +207 -0
- glideshow/pptx_import.py +115 -0
- glideshow/publish.py +106 -0
- glideshow/render.py +288 -0
- glideshow/server.py +549 -0
- glideshow/service.py +65 -0
- glideshow/skills/glideshow/SKILL.md +85 -0
- glideshow-0.1.2.dist-info/METADATA +69 -0
- glideshow-0.1.2.dist-info/RECORD +103 -0
- glideshow-0.1.2.dist-info/WHEEL +4 -0
- glideshow-0.1.2.dist-info/entry_points.txt +2 -0
- glideshow-0.1.2.dist-info/licenses/LICENSE +662 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/* The phone's chrome: Google Slides' iPhone app. Every rule is under html.phone
|
|
2
|
+
(editor/js/phone-mode.js), so none of it reaches the desktop editor. Sizes are CSS px = iOS pt. */
|
|
3
|
+
html.phone {
|
|
4
|
+
/* the app in dark mode, measured on the captures */
|
|
5
|
+
--ph-bar: #303134; --ph-canvas: #202123; --ph-page: #202124; --ph-ink: #e8eaed; --ph-muted: #9aa0a6; --ph-rule: #5f6367;
|
|
6
|
+
--ph-accent: #1c419a; --ph-accent-ink: #aec6f6; --ph-select: #3771e0; --ph-halo: #bed1f7; --ph-adjust: #eab63e;
|
|
7
|
+
--ph-bar-h: 62px; --ph-film-h: 96px; --ph-tool-h: 44px; --ph-sheet-row: 60px; --ph-icon-pitch: 48px;
|
|
8
|
+
}
|
|
9
|
+
/* The app is dark (the captures): editor.css's tokens follow, on <body> so they win over body.dark's. */
|
|
10
|
+
html.phone body {
|
|
11
|
+
--font: -apple-system, system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
12
|
+
--ink: var(--ph-ink); --muted: var(--ph-muted); --divider: var(--ph-rule); --icon: var(--ph-ink); --outline: var(--ph-rule);
|
|
13
|
+
--chrome: var(--ph-bar); --surface: var(--ph-bar); --stage: var(--ph-canvas); --toolbar: #2a2b2e; --hover: #3c4043; --selected: var(--ph-accent); --tip: var(--ph-ink);
|
|
14
|
+
--menu-shadow: 0 2px 6px rgba(0, 0, 0, .5), 0 1px 2px rgba(0, 0, 0, .6);
|
|
15
|
+
color-scheme: dark; -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent;
|
|
16
|
+
}
|
|
17
|
+
html.phone .ph-icon-btn { display: grid; place-items: center; width: 48px; height: 48px; padding: 0; border: 0; background: none; color: var(--ph-ink); }
|
|
18
|
+
html.phone .ph-icon-btn .icon, html.phone .ph-sortrow #hm-view { font-size: 24px; }
|
|
19
|
+
html.phone .menu-item { height: 48px; font-size: 16px; }
|
|
20
|
+
|
|
21
|
+
/* ---------- Home (01-home.png) ---------- */
|
|
22
|
+
html.phone body:has(> .hm-bar) { background: var(--ph-page); font-size: 17px; }
|
|
23
|
+
html.phone .hm-bar { position: sticky; top: 0; height: auto; padding: calc(env(safe-area-inset-top) + 7px) 16px 0; gap: 0; background: var(--ph-page); }
|
|
24
|
+
html.phone .hm-bar .brand, html.phone #hm-app-more, html.phone #hm-gh, html.phone .hm-sky, html.phone .hm-actions, html.phone .hm-section, html.phone .hm-group { display: none !important; }
|
|
25
|
+
/* the search bar: 48 tall, radius 8, ≡ | placeholder | folder | account */
|
|
26
|
+
html.phone .ph-search { flex: 1; min-width: 0; display: flex; align-items: center; height: 48px; padding: 0 4px; border-radius: 8px; background: #2a2b2e; box-shadow: 0 1px 3px rgba(0, 0, 0, .4); }
|
|
27
|
+
html.phone .ph-search input { flex: 1; min-width: 0; height: 100%; padding: 0 0 0 8px; border: 0; outline: 0; background: none; color: var(--ph-ink); font: 17px var(--font); }
|
|
28
|
+
html.phone .ph-search input::placeholder { color: var(--ph-muted); }
|
|
29
|
+
html.phone .ph-search .ph-icon-btn { color: var(--ph-muted); }
|
|
30
|
+
html.phone .ph-search .ph-icon-btn:first-child { color: var(--ph-ink); }
|
|
31
|
+
html.phone .ph-avatar { flex: none; display: grid; place-items: center; width: 32px; height: 32px; margin: 0 8px 0 4px; padding: 0; border: 0; border-radius: 50%; overflow: hidden; background: var(--ph-accent); color: var(--ph-ink); font: 500 15px var(--font); }
|
|
32
|
+
html.phone .ph-avatar img { width: 100%; height: 100%; display: block; background: #fff; }
|
|
33
|
+
/* the sort label and the grid/list toggle */
|
|
34
|
+
html.phone .hm-main { padding: 0 11px calc(96px + env(safe-area-inset-bottom)); max-width: none; }
|
|
35
|
+
html.phone .hm-head { min-height: 0; margin: 10px 5px 0; }
|
|
36
|
+
html.phone .hm-head:has(.hm-crumbs > a:only-child) { display: none; } /* at the top level: no path to show */
|
|
37
|
+
html.phone .hm-crumbs { font-size: 17px; margin: 0; }
|
|
38
|
+
html.phone .ph-sortrow { display: flex; align-items: center; justify-content: space-between; height: 42px; margin: 10px 0 16px 5px; }
|
|
39
|
+
html.phone .ph-sort { display: flex; align-items: center; gap: 2px; padding: 0; border: 0; background: none; color: var(--ph-muted); font: 15px var(--font); }
|
|
40
|
+
html.phone .ph-sort .icon { font-size: 18px; }
|
|
41
|
+
html.phone .ph-sortrow #hm-view { width: 48px; height: 48px; margin-right: -8px; border-radius: 0; background: none; color: var(--ph-muted); }
|
|
42
|
+
/* two columns of decks: a 2:1 picture (the slide cropped top and bottom), then the file icon, the title, ⋯ */
|
|
43
|
+
html.phone .hm-folders, html.phone .hm-grid:not(.list) { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 26px; row-gap: 22px; }
|
|
44
|
+
html.phone .hm-folders:not(:empty) { margin-bottom: 22px; }
|
|
45
|
+
html.phone .hm-card, html.phone .hm-card:hover { border: 0; border-radius: 0; background: none; box-shadow: none; overflow: visible; }
|
|
46
|
+
html.phone .hm-grid:not(.list) .hm-card .pic { display: flex; align-items: center; aspect-ratio: 2 / 1; border: 0; border-radius: 6px; }
|
|
47
|
+
html.phone .hm-grid:not(.list) .hm-card .pic .hm-pic { position: relative; inset: auto; flex: none; }
|
|
48
|
+
html.phone .hm-card .meta { gap: 0; padding: 6px 0 0; min-height: 52px; }
|
|
49
|
+
html.phone .hm-card .meta::before { content: "slideshow"; flex: none; width: 32px; font: 24px/1 "Material Symbols Outlined"; font-variation-settings: "FILL" 1; color: #fdd663; font-feature-settings: "liga"; }
|
|
50
|
+
html.phone .hm-card .title { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; text-align: center; font-size: 17px; line-height: 22px; color: var(--ph-ink); }
|
|
51
|
+
html.phone .hm-card .sub { display: none; }
|
|
52
|
+
html.phone .hm-card .more { width: 32px; height: 44px; color: var(--ph-ink); }
|
|
53
|
+
html.phone .hm-card .more .icon { font-size: 24px; width: 24px; height: 24px; }
|
|
54
|
+
html.phone .hm-folder { background: #2a2b2e; }
|
|
55
|
+
/* + : 56 round, bottom right */
|
|
56
|
+
html.phone #hm-new.ph-fab { position: fixed; right: 20px; margin: 0; bottom: max(20px, env(safe-area-inset-bottom)); z-index: 6; display: grid; place-items: center; width: 56px; height: 56px; padding: 0; border: 0; border-radius: 50%;
|
|
57
|
+
background: #353639; color: var(--ph-ink); box-shadow: 0 1px 3px rgba(0, 0, 0, .3), 0 4px 8px 3px rgba(0, 0, 0, .15); }
|
|
58
|
+
html.phone #hm-new.ph-fab .icon { font-size: 32px; width: auto; }
|
|
59
|
+
|
|
60
|
+
/* ---------- the editor page: the desktop chrome gives way (each phone screen brings its own) ---------- */
|
|
61
|
+
html.phone:has(#ph-top), html.phone body:has(#ph-top) { overflow: hidden; height: 100%; }
|
|
62
|
+
html.phone body:has(#ph-top) { background: var(--ph-canvas); font-size: 17px; overscroll-behavior: none; }
|
|
63
|
+
html.phone #ed-bar, html.phone #ed-side, html.phone .ruler, html.phone #ed-dock, html.phone #ed-splitter, html.phone #ed-ai-notes, html.phone #ed-notes { display: none !important; }
|
|
64
|
+
html.phone #ed-stage { padding: 0; touch-action: none; }
|
|
65
|
+
html.phone:not(.ph-view) #ph-view, html.phone:not(.ph-view) .ph-chip, html.phone.ph-view main { display: none; }
|
|
66
|
+
/* the top bar: 62 under the status bar, icons 24 on a 48 pitch, 1 px rule (02-open-view.png, 03-edit.png) */
|
|
67
|
+
html.phone .ph-top { flex: none; position: relative; z-index: 20; padding: env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left); background: var(--ph-bar); border-bottom: 1px solid var(--ph-rule); transition: transform .25s ease; }
|
|
68
|
+
html.phone .ph-bar { display: none; align-items: center; height: var(--ph-bar-h); }
|
|
69
|
+
html.phone.ph-view .ph-bar-view, html.phone.ph-edit .ph-bar-edit { display: flex; }
|
|
70
|
+
html.phone .ph-gap { flex: 1; }
|
|
71
|
+
html.phone .ph-bar .ph-icon-btn .icon { font-variation-settings: "FILL" 0; }
|
|
72
|
+
html.phone .ph-bar .ph-icon-btn:active { opacity: .45; }
|
|
73
|
+
|
|
74
|
+
/* ---------- view mode: the slides as a vertical list (02-open-view.png, r01) ---------- */
|
|
75
|
+
html.phone.ph-view .ph-top { position: fixed; left: 0; right: 0; top: 0; }
|
|
76
|
+
html.phone.ph-view .ph-top.away { transform: translateY(-100%); }
|
|
77
|
+
html.phone #ph-view { position: fixed; inset: 0; z-index: 1; overflow-y: auto; overscroll-behavior: contain; padding: calc(env(safe-area-inset-top) + var(--ph-bar-h) + 1px) 0 env(safe-area-inset-bottom); background: var(--ph-canvas); }
|
|
78
|
+
html.phone .ph-vslide { position: relative; width: 100%; margin-bottom: 4px; overflow: hidden; background: #3c4043; } /* dark until drawn */
|
|
79
|
+
html.phone .ph-vslide.drawn { background: #fff; }
|
|
80
|
+
html.phone .ph-vslide-canvas { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
|
|
81
|
+
html.phone .ph-vslide-canvas > section { display: block !important; position: absolute; inset: 0; }
|
|
82
|
+
html.phone .ph-vslide.cur::after { content: ""; position: absolute; inset: 0; z-index: 5; box-shadow: inset 0 0 0 2px var(--ph-accent-ink); pointer-events: none; }
|
|
83
|
+
/* "Slide N of M" while scrolling: top right, 6 under the bar */
|
|
84
|
+
html.phone .ph-chip { position: fixed; z-index: 21; right: 5px; top: calc(env(safe-area-inset-top) + var(--ph-bar-h) + 7px); padding: 3px 8px; border-radius: 4px; background: #555659; color: #fff; font: 15px var(--font); opacity: 0; transition: opacity .2s; pointer-events: none; }
|
|
85
|
+
html.phone .ph-chip.on { opacity: 1; }
|
|
86
|
+
/* the iOS edit menu: a dark glass pill of labels with thin rules between */
|
|
87
|
+
html.phone .ph-editmenu { position: fixed; z-index: 40; display: flex; align-items: stretch; height: 42px; border-radius: 21px; overflow: hidden; background: rgba(110, 110, 112, .82); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); box-shadow: 0 4px 16px rgba(0, 0, 0, .3); }
|
|
88
|
+
html.phone .ph-editmenu button { height: auto; padding: 0 16px; border: 0; border-radius: 0; background: none; color: #fff; font: 16px var(--font); white-space: nowrap; }
|
|
89
|
+
html.phone .ph-editmenu button + button { border-left: 1px solid rgba(255, 255, 255, .25); }
|
|
90
|
+
html.phone .ph-editmenu button:active { background: rgba(255, 255, 255, .15); }
|
|
91
|
+
/* presenting (13-present.png): ✕ and the title over the black */
|
|
92
|
+
html.phone .ph-show-bar { position: absolute; left: 0; right: 0; top: 0; display: flex; align-items: center; height: calc(env(safe-area-inset-top) + var(--ph-bar-h)); padding-top: env(safe-area-inset-top); background: var(--ph-bar); border-bottom: 1px solid var(--ph-rule); color: var(--ph-ink); }
|
|
93
|
+
html.phone .ph-show-title { font: 17px var(--font); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
94
|
+
|
|
95
|
+
/* ---------- editing (03-edit.png, 04-select-text-box.png) ---------- */
|
|
96
|
+
html.phone body { --slide-shadow: none; }
|
|
97
|
+
html.phone:not(.ph-edit) .ph-film { display: none; }
|
|
98
|
+
/* the top bar: back at the left, the rest on the 48 grid against the right edge; with a selection, ✓ and no share */
|
|
99
|
+
html.phone .ph-bar-edit .ph-done { display: none; color: var(--ph-accent-ink); }
|
|
100
|
+
html.phone .ph-bar-edit.picking .ph-done { display: grid; }
|
|
101
|
+
html.phone .ph-bar-edit.picking > .ph-icon-btn:first-child, html.phone .ph-bar-edit.picking .ph-icon-btn[title=Share] { display: none; }
|
|
102
|
+
html.phone .ph-bar-edit .ph-icon-btn:last-child { margin-right: 0; }
|
|
103
|
+
/* the filmstrip: 1 px rule, cells 98 wide with an 80 × 45 picture 9 in and the number under it; the current cell blue */
|
|
104
|
+
html.phone .ph-film { flex: none; display: flex; height: calc(97px + env(safe-area-inset-bottom)); padding-bottom: env(safe-area-inset-bottom); background: var(--ph-bar); border-top: 1px solid var(--ph-rule); }
|
|
105
|
+
html.phone .ph-film-strip { flex: 1; display: flex; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; padding-top: 5px; }
|
|
106
|
+
html.phone .ph-film-strip::-webkit-scrollbar { display: none; }
|
|
107
|
+
html.phone .ph-film-cells { display: contents; } /* the slides' cells, in the strip (a New slide tile may follow them) */
|
|
108
|
+
html.phone .ph-cell { flex: none; display: flex; flex-direction: column; align-items: flex-start; gap: 7px; width: 98px; height: 87px; padding: 9px 9px 0; border: 0; border-radius: 2px; background: none; color: var(--ph-ink); text-align: left; }
|
|
109
|
+
html.phone .ph-cell.cur { background: var(--ph-accent); }
|
|
110
|
+
html.phone .ph-thumb { position: relative; width: 80px; overflow: hidden; background: #fff; box-shadow: 0 0 0 1px #545759; border-radius: 1px; }
|
|
111
|
+
html.phone .ph-cell.cur .ph-thumb { box-shadow: 0 0 0 1px #9dbdf3; }
|
|
112
|
+
html.phone .ph-thumb > .thumb-view { position: absolute; left: 0; top: 0; transform: scale(calc(80 / 158)); transform-origin: 0 0; border-radius: 0; box-shadow: none; }
|
|
113
|
+
html.phone .ph-num { font: 15px/1 var(--font); }
|
|
114
|
+
html.phone .ph-cell.cur .ph-num { color: #f8e39d; }
|
|
115
|
+
html.phone .ph-film-new { flex: none; width: 44px; height: 100%; border-radius: 0; border-left: 1px solid var(--ph-rule) !important; padding-bottom: 6px; }
|
|
116
|
+
|
|
117
|
+
/* ---------- selection and touch (04-select-text-box.png, 06-select-shape.png, r02) ---------- */
|
|
118
|
+
/* square blue handles with a thin white edge, a blue knob on a stem, a blue frame in a pale halo */
|
|
119
|
+
html.phone .sel-box { box-shadow: 0 0 0 calc(var(--k, 1px) * .75) var(--ph-select), 0 0 0 calc(var(--k, 1px) * 3.25) rgba(190, 209, 247, .85); }
|
|
120
|
+
html.phone .sel-box.thin { box-shadow: 0 0 0 calc(var(--k, 1px) * .75) var(--ph-select); opacity: 1; }
|
|
121
|
+
html.phone .handle:not(.adjust):not(.crop):not(.rotate) { border-radius: 0; background: var(--ph-select); box-shadow: 0 0 0 calc(var(--k, 1px) * 1.3) #fff; }
|
|
122
|
+
html.phone .handle.rotate { background: var(--ph-select); border-radius: 50%; box-shadow: 0 0 0 calc(var(--k, 1px) * 1.5) #fff; }
|
|
123
|
+
html.phone .handle.rotate .icon { display: none; }
|
|
124
|
+
html.phone .rot-stem { background: var(--ph-select); }
|
|
125
|
+
html.phone .handle.adjust { background: var(--ph-adjust); box-shadow: 0 0 0 var(--k) #7a5a00; }
|
|
126
|
+
html.phone .handle::before { inset: -150%; } /* a 30 px touch target around each handle */
|
|
127
|
+
/* while a handle is dragged, only it stays (r02) */
|
|
128
|
+
html.phone #ed-ui.ph-sizing .handle:not(.on), html.phone #ed-ui.ph-sizing .rot-stem { display: none; }
|
|
129
|
+
/* the grey outline that follows the finger */
|
|
130
|
+
html.phone .ph-ghost { position: absolute; box-shadow: 0 0 0 calc(var(--k) * 1.3) #8d8d8d; pointer-events: none; }
|
|
131
|
+
html.phone .guide { background: #f00; }
|
|
132
|
+
html.phone #ed-rules .rule { pointer-events: none; } /* a deck's guides are drawn but not dragged on a phone: a tap goes to the box under it */
|
|
133
|
+
/* the angle while rotating: a dark chip (r02) */
|
|
134
|
+
html.phone .rot-label { scale: 2.2; transform-origin: 100% 0; padding: .25em .6em; border-radius: .3em; background: #2c2c2c; color: #fff; }
|
|
135
|
+
html.phone #ed-stage.zoomed { overflow: hidden; } /* we scroll it ourselves: one finger on nothing, or two */
|
|
136
|
+
|
|
137
|
+
/* ---------- the text and shape toolbars (04-select-text-box.png, 06-select-shape.png, r03) ---------- */
|
|
138
|
+
html.phone .ph-tools { display: none; flex: none; height: calc(var(--ph-tool-h) + env(safe-area-inset-bottom)); align-items: flex-start; background: var(--ph-bar); border-top: 1px solid var(--ph-rule); }
|
|
139
|
+
html.phone.ph-edit.ph-tools-text .ph-tools, html.phone.ph-edit.ph-tools-shape .ph-tools { display: flex; }
|
|
140
|
+
/* the toolbar takes the bottom edge and pushes the filmstrip up over the canvas: the slide doesn't move (r02) */
|
|
141
|
+
html.phone.ph-edit.ph-tools-text .ph-film, html.phone.ph-edit.ph-tools-shape .ph-film { position: relative; z-index: 2; height: 97px; padding-bottom: 0; margin-top: calc(-1 * var(--ph-tool-h)); }
|
|
142
|
+
html.phone .ph-tools > div { display: none; flex: 1; align-items: center; height: var(--ph-tool-h); padding-left: 4px; overflow-x: auto; scrollbar-width: none; } /* scrolls sideways when it doesn't fit */
|
|
143
|
+
html.phone .ph-tools > div::-webkit-scrollbar { display: none; }
|
|
144
|
+
html.phone.ph-tools-text .ph-tools-text, html.phone.ph-tools-shape .ph-tools-shape { display: flex; }
|
|
145
|
+
html.phone .ph-tools-shape { justify-content: center; padding-left: 0 !important; }
|
|
146
|
+
html.phone .ph-tools .ph-icon-btn { position: relative; flex: none; width: 48px; height: var(--ph-tool-h); }
|
|
147
|
+
html.phone .ph-tools .ph-icon-btn.on .icon { width: 32px; height: 36px; line-height: 36px; border-radius: 4px; background: var(--ph-accent); color: var(--ph-accent-ink); text-align: center; }
|
|
148
|
+
html.phone .ph-sep { flex: none; width: 1px; height: 28px; margin: 0 4px; background: var(--ph-rule); }
|
|
149
|
+
html.phone .ph-bar-color { position: absolute; left: 13px; right: 13px; bottom: 6px; height: 3px; border: 1px solid #5f6367; }
|
|
150
|
+
/* typing: the filmstrip goes, the toolbar sits on the keyboard */
|
|
151
|
+
html.phone.ph-edit.ph-typing .ph-film { display: none; }
|
|
152
|
+
html.phone.ph-typing .ph-tools { height: var(--ph-tool-h); }
|
|
153
|
+
html.phone .sel-box.editing { outline: none; box-shadow: 0 0 0 calc(var(--k, 1px) * .75) var(--ph-select), 0 0 0 calc(var(--k, 1px) * 3.25) rgba(190, 209, 247, .85); } /* typing keeps the frame (r03) */
|
|
154
|
+
|
|
155
|
+
/* ---------- bottom sheets (09-insert-menu.png, r04) ---------- */
|
|
156
|
+
html.phone { --ph-safe-top: env(safe-area-inset-top); --ph-sheet-h: min(442px, 58vh); }
|
|
157
|
+
html.phone #ph-top, html.phone main, html.phone #ph-film, html.phone #ph-tools { transition: transform .25s ease; }
|
|
158
|
+
html.phone .ph-sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; height: var(--ph-sheet-h); overflow: hidden; background: var(--ph-bar); color: var(--ph-ink); transform: translateY(100%); transition: transform .25s ease; font: 17px var(--font); }
|
|
159
|
+
html.phone.ph-sheet-open .ph-sheet { transform: none; }
|
|
160
|
+
html.phone .ph-page { position: absolute; inset: 0; display: flex; flex-direction: column; background: var(--ph-bar); transition: transform .25s ease; }
|
|
161
|
+
html.phone .ph-page.in { transform: translateX(100%); } html.phone .ph-page.out { transform: translateX(-30%); }
|
|
162
|
+
html.phone .ph-page-head { position: relative; flex: none; display: flex; align-items: center; justify-content: center; height: 47px; border-bottom: 1px solid var(--ph-rule); }
|
|
163
|
+
html.phone .ph-page-title { font-size: 17px; }
|
|
164
|
+
html.phone .ph-back { position: absolute; left: 0; top: 0; height: 46px; }
|
|
165
|
+
html.phone .ph-page-body { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding-bottom: env(safe-area-inset-bottom); }
|
|
166
|
+
/* rows: 60 tall, icon at 36, label at 72, › at the right, inset rules */
|
|
167
|
+
html.phone .ph-row { position: relative; display: flex; align-items: center; width: 100%; height: 60px; padding: 0 24px 0 24px; border: 0; border-radius: 0; background: none; color: var(--ph-ink); font: 17px var(--font); text-align: left; }
|
|
168
|
+
html.phone .ph-row + .ph-row::before { content: ""; position: absolute; left: 24px; right: 24px; top: 0; border-top: 1px solid var(--ph-rule); }
|
|
169
|
+
html.phone .ph-row > .icon:first-child { width: 24px; margin-right: 24px; font-size: 24px; color: var(--ph-muted); }
|
|
170
|
+
html.phone .ph-row-label { flex: 1; }
|
|
171
|
+
html.phone .ph-row .ph-more { color: var(--ph-muted); font-size: 24px; }
|
|
172
|
+
html.phone .ph-row:active:not(:disabled) { background: #3c4043; }
|
|
173
|
+
html.phone .ph-row:disabled { opacity: .4; }
|
|
174
|
+
/* tabs: equal widths, the chosen one light blue with a 3 px bar under its label */
|
|
175
|
+
html.phone .ph-tabs { display: flex; height: 47px; border-bottom: 1px solid var(--ph-rule); }
|
|
176
|
+
html.phone .ph-tabs button { flex: 1; position: relative; border: 0; border-radius: 0; background: none; color: var(--ph-muted); font: 15px var(--font); }
|
|
177
|
+
html.phone .ph-tabs button.on { color: #a8c7fa; }
|
|
178
|
+
html.phone .ph-tabs button.on::after { content: ""; position: absolute; left: 50%; bottom: 0; width: 50%; height: 3px; translate: -50% 0; border-radius: 3px 3px 0 0; background: #a8c7fa; }
|
|
179
|
+
/* the shape grid: 4 columns, ~52 px pictures, light grey with a grey outline */
|
|
180
|
+
html.phone .ph-shape-grid { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 86px; padding: 4px 0; }
|
|
181
|
+
html.phone .ph-shape-cell { display: grid; place-items: center; border: 0; border-radius: 0; background: none; }
|
|
182
|
+
html.phone .ph-shape-cell:active { background: #3c4043; }
|
|
183
|
+
html.phone .ph-shape-cell svg { width: 52px; height: 52px; }
|
|
184
|
+
html.phone .ph-shape-cell svg * { fill: #f4f4f4; stroke: #949494; stroke-width: 1px; vector-effect: non-scaling-stroke; }
|
|
185
|
+
html.phone .ph-table-pick { padding: 16px; }
|
|
186
|
+
|
|
187
|
+
/* ---------- colour panels (r03, r04) ---------- */
|
|
188
|
+
html.phone .ph-none { height: 50px; }
|
|
189
|
+
html.phone .ph-none .ph-check { display: none; color: var(--ph-muted); font-size: 22px; }
|
|
190
|
+
html.phone .ph-none.on .ph-check { display: inline-block; }
|
|
191
|
+
/* the hue strip: 11 square segments 25 wide, the chosen one in a white frame */
|
|
192
|
+
html.phone .ph-hues { display: flex; justify-content: center; margin: 16px 0 12px; }
|
|
193
|
+
html.phone .ph-hue { width: 25px; height: 30px; padding: 0; border: 0; border-radius: 0; }
|
|
194
|
+
html.phone .ph-hue.on { position: relative; z-index: 1; border-radius: 4px; box-shadow: 0 0 0 4px #fff; scale: 1.15; }
|
|
195
|
+
html.phone .ph-swatches { display: grid; gap: 2px 2.5px; margin: 0 12px; }
|
|
196
|
+
html.phone .ph-swatches.five { grid-template-columns: repeat(5, 1fr); }
|
|
197
|
+
html.phone .ph-swatches.four { grid-template-columns: repeat(4, 1fr); }
|
|
198
|
+
html.phone .ph-swatches.custom { grid-template-columns: repeat(auto-fill, 56px); }
|
|
199
|
+
html.phone .ph-swatch-cell { position: relative; height: 56px; padding: 0; border: 1px solid #54575d; border-radius: 0; }
|
|
200
|
+
html.phone .ph-swatch-cell.on::after { content: "check"; position: absolute; right: 4px; bottom: 4px; width: 15px; height: 15px; border-radius: 50%; background: #d8d8d8; color: #000; font: 13px/15px "Material Symbols Outlined"; font-feature-settings: "liga"; text-align: center; }
|
|
201
|
+
html.phone .ph-add { display: grid; place-items: center; background: none; color: var(--ph-muted); }
|
|
202
|
+
html.phone .ph-label { margin: 16px 12px 10px; font-size: 17px; }
|
|
203
|
+
|
|
204
|
+
/* ---------- slide mode (11-slide-selected.png, r05) ---------- */
|
|
205
|
+
html.phone.ph-edit.ph-slide .ph-bar-edit { display: none; }
|
|
206
|
+
html.phone.ph-edit.ph-slide .ph-bar-slide { display: flex; }
|
|
207
|
+
html.phone .ph-count { min-width: 32px; padding-left: 4px; color: #ccdcfc; font: 17px var(--font); }
|
|
208
|
+
html.phone .ph-bar-slide .ph-act { flex: 0 1 44px; min-width: 34px; } /* 44 apart, a little less on a narrow phone */
|
|
209
|
+
html.phone .ph-cell.picked { background: var(--ph-accent); }
|
|
210
|
+
html.phone .ph-cell.picked .ph-thumb { box-shadow: 0 0 0 1px #9dbdf3; }
|
|
211
|
+
html.phone .ph-cell.picked .ph-num { color: #f8e39d; }
|
|
212
|
+
|
|
213
|
+
/* ---------- Add slide (12-new-slide-layouts.png) ---------- */
|
|
214
|
+
html.phone .ph-addslide { position: fixed; inset: 0; z-index: 40; display: flex; flex-direction: column; background: var(--ph-page); color: var(--ph-ink); }
|
|
215
|
+
html.phone .ph-addslide[hidden] { display: none; }
|
|
216
|
+
html.phone .ph-addslide-head { flex: none; position: relative; display: flex; align-items: center; justify-content: center; height: calc(41px + env(safe-area-inset-top)); padding-top: env(safe-area-inset-top); border-bottom: 1px solid #3c4043; font: 17px var(--font); }
|
|
217
|
+
html.phone .ph-addslide-head .ph-icon-btn { position: absolute; right: 18px; bottom: -4px; }
|
|
218
|
+
html.phone .ph-layouts { flex: 1; overflow-y: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 20px; padding: 20px 20px calc(20px + env(safe-area-inset-bottom)); }
|
|
219
|
+
html.phone .ph-sheet .ph-layouts { overflow: visible; padding: 16px 20px; }
|
|
220
|
+
html.phone .ph-layout { display: flex; flex-direction: column; align-items: stretch; gap: 8px; height: auto; padding: 0 0 12px; border: 0; border-radius: 0; background: none; color: var(--ph-ink); font: 600 15px var(--font); }
|
|
221
|
+
html.phone .ph-layout svg { flex: none; display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; outline: 1px solid var(--ph-rule); }
|
|
222
|
+
html.phone .ph-layout:active svg { outline: 2px solid var(--ph-accent-ink); }
|
|
223
|
+
html.phone .ph-layout svg text { font-weight: 400; }
|
|
224
|
+
|
|
225
|
+
/* ---------- reordering slides (r05) ---------- */
|
|
226
|
+
html.phone .ph-cell { transition: transform .25s ease-out; }
|
|
227
|
+
html.phone .ph-cell.lifting { visibility: hidden; } /* its place closes up as the others make room */
|
|
228
|
+
html.phone .ph-lifted { position: fixed; z-index: 50; width: 97px !important; height: 55px !important; border-radius: 4px; box-shadow: none; pointer-events: none; }
|
|
229
|
+
html.phone .ph-lifted > .thumb-view { transform: scale(calc(97 / 158)); }
|
|
230
|
+
html.phone .ph-film.dragging .ph-film-new { color: #6a6b70; }
|
|
231
|
+
|
|
232
|
+
/* ---------- presenting (13-present.png, r07) ---------- */
|
|
233
|
+
html.phone #ed-show { background: #000; bottom: auto; height: 100dvh; } /* the visible height: iPhone Safari's own bars don't hide the slide's bottom */
|
|
234
|
+
/* a home-screen app (html.ph-app): the editor and presenting keep the app's full height (phone-mode.js), as iOS's
|
|
235
|
+
viewport units and 100% can be off there by about a status bar */
|
|
236
|
+
html.phone.ph-app:has(#ph-top), html.phone.ph-app body:has(#ph-top), html.phone.ph-app #ed-show { height: var(--ph-app-h, 100%); }
|
|
237
|
+
html.phone.ph-app.ph-kb body:has(#ph-top) { position: fixed; left: 0; right: 0; top: var(--ph-vv-top, 0px); } /* the keyboard up: the page is the visible area, wherever iOS has moved it */
|
|
238
|
+
html.phone.ph-app.ph-typing:not(.ph-kb) .ph-tools { height: calc(var(--ph-tool-h) + env(safe-area-inset-bottom)); } /* editing with the keyboard down: clear of the home indicator */
|
|
239
|
+
html.phone .ph-show-count { display: none; }
|
|
240
|
+
html.phone .ph-show-touch { position: absolute; inset: 0; z-index: 1; } /* taps and swipes, over the deck */
|
|
241
|
+
html.phone .ph-show-bar { z-index: 2; transition: transform .38s ease; }
|
|
242
|
+
html.phone .ph-show-bar.away { transform: translateY(-100%); }
|
|
243
|
+
|
|
244
|
+
/* ---------- adding a comment (15-comments.png) ---------- */
|
|
245
|
+
html.phone .ph-cm-cancel, html.phone .ph-cm-hint, html.phone .ph-cm-bar { display: none; }
|
|
246
|
+
html.phone.ph-commenting .ph-top, html.phone.ph-commenting .ph-film, html.phone.ph-commenting .ph-tools { display: none !important; }
|
|
247
|
+
html.phone.ph-commenting main { padding: calc(env(safe-area-inset-top) + 64px) 0 136px; }
|
|
248
|
+
html.phone.ph-commenting .ph-cm-cancel { position: fixed; z-index: 30; left: 50%; top: calc(env(safe-area-inset-top) + 6px); translate: -50% 0; display: flex; align-items: center; gap: 8px; height: 46px; padding: 0 20px 0 8px; border: 0; border-radius: 23px; background: var(--ph-page); color: var(--ph-ink); font: 22px var(--font); box-shadow: 0 1px 4px rgba(0, 0, 0, .4); }
|
|
249
|
+
html.phone .ph-cm-cancel .icon { font-size: 32px; width: auto; }
|
|
250
|
+
html.phone.ph-commenting .ph-cm-hint { position: fixed; z-index: 30; left: 8px; right: 8px; bottom: calc(73px + env(safe-area-inset-bottom)); display: flex; align-items: center; height: 48px; padding: 0 16px; border-radius: 4px; background: #fff; color: #202124; font: 17px var(--font); }
|
|
251
|
+
html.phone.ph-commenting .ph-cm-bar { position: fixed; z-index: 30; left: 0; right: 0; bottom: 0; display: flex; align-items: center; gap: 4px; padding: 8px 8px calc(8px + env(safe-area-inset-bottom)); background: var(--ph-bar); border-top: 1px solid var(--ph-rule); }
|
|
252
|
+
html.phone .ph-cm-at { color: var(--ph-muted); }
|
|
253
|
+
html.phone .ph-cm-field { flex: 1; display: flex; align-items: center; min-height: 48px; padding: 0 4px 0 16px; border-radius: 24px; background: #46474a; }
|
|
254
|
+
html.phone .ph-cm-input { flex: 1; min-width: 0; padding: 12px 0; border: 0; outline: 0; resize: none; background: none; color: var(--ph-ink); font: 17px/22px var(--font); }
|
|
255
|
+
html.phone .ph-cm-input::placeholder { color: var(--ph-muted); }
|
|
256
|
+
html.phone .ph-cm-send { color: var(--ph-accent-ink); }
|
|
257
|
+
html.phone .ph-cm-send:disabled { color: var(--ph-muted); }
|
|
258
|
+
|
|
259
|
+
/* ---------- the comments list and Share, full screen in the app's dark look (14-share.png) ---------- */
|
|
260
|
+
html.phone #ed-comments:not([hidden]) { position: fixed; inset: 0; z-index: 45; width: auto !important; max-width: none; margin: 0; border-radius: 0; padding-top: env(safe-area-inset-top); border: 0; background: var(--ph-page); color: var(--ph-ink); font-size: 15px; }
|
|
261
|
+
html.phone #ed-comments header { height: 56px; font-size: 17px; }
|
|
262
|
+
html.phone .cm-card { border-color: var(--ph-rule); background: var(--ph-bar); font-size: 15px; }
|
|
263
|
+
html.phone #ed-sharedlg { background: var(--ph-page); }
|
|
264
|
+
html.phone #ed-sharedlg .share-dialog { position: fixed; inset: 0; width: auto; max-width: none; max-height: none; margin: 0; padding: calc(env(safe-area-inset-top) + 8px) 16px calc(16px + env(safe-area-inset-bottom)); border-radius: 0; box-shadow: none; background: var(--ph-page); color: var(--ph-ink); font-size: 15px; overflow-y: auto; }
|
|
265
|
+
html.phone #ed-sharedlg header h2 { font-size: 17px; font-weight: 500; }
|
|
266
|
+
html.phone #ed-sharedlg .share-dialog > header { flex-direction: row-reverse; padding: 0 0 8px; border: 0; } /* ✕ at the left, the title in the middle (14-share.png) */
|
|
267
|
+
html.phone #ed-sharedlg .share-dialog > header h2 { margin-right: 40px; text-align: center; }
|
|
268
|
+
html.phone #ed-ui:has(~ #ed-guides .rot-ghost) .handle:not(.rotate) { display: none; } /* turning: only the knob and the frame stay (r02) */
|
|
269
|
+
|
|
270
|
+
/* ---------- glideshow.org on a phone: the browser-only notice under the search, and the empty library ---------- */
|
|
271
|
+
html.phone .hm-move { margin: 12px 0 4px; padding: 12px 12px 12px 16px; gap: 10px 12px; border-radius: 12px; background: #2a2b2e; box-shadow: inset 0 0 0 1px var(--ph-rule); font-size: 15px; line-height: 1.35; }
|
|
272
|
+
html.phone .hm-move span { min-width: 0; color: var(--ph-muted); }
|
|
273
|
+
html.phone .hm-move-go { height: 36px; background: var(--ph-accent-ink); color: #202124; }
|
|
274
|
+
html.phone .hm-empty { margin: 8px 5px; font-size: 15px; color: var(--ph-muted); }
|
|
275
|
+
html.phone .ph-theme { display: none !important; } /* the app's own look is always dark: the switch is Thermal's */
|
|
276
|
+
html.phone .ph-sorttools { display: flex; align-items: center; }
|
|
277
|
+
|
|
278
|
+
/* ---------- layout experiments (?layout=thumb,float,shelf; previews, see phone-mode.js) ---------- */
|
|
279
|
+
/* thumb: the deck's title on top; undo, redo, insert, present and comments in a pill above the filmstrip */
|
|
280
|
+
html.phone .ph-dock, html.phone .ph-doc-title { display: none; }
|
|
281
|
+
html.phone[data-layout~="thumb"] .ph-doc-title { display: block; flex: 1; min-width: 0; padding: 0 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; font: 500 17px var(--font); color: var(--ph-ink); }
|
|
282
|
+
html.phone.ph-edit[data-layout~="thumb"]:not(.ph-typing):not(.ph-slide) .ph-dock { display: flex; flex: none; align-self: center; gap: 2px; margin: 8px 0 10px; padding: 4px; border-radius: 999px;
|
|
283
|
+
background: var(--ph-surface, #303134); box-shadow: 0 0 0 1px var(--ph-rule), 0 6px 18px rgba(0, 0, 0, .12); }
|
|
284
|
+
html.phone[data-layout~="thumb"] .ph-dock .ph-icon-btn { width: 52px; height: 44px; border-radius: 999px; color: var(--icon, var(--ph-ink)); }
|
|
285
|
+
html.phone[data-layout~="thumb"] .ph-dock .ph-icon-btn:active { background: var(--ph-press, #3c4043); }
|
|
286
|
+
html.phone.ph-edit[data-layout~="thumb"].ph-tools-text .ph-film, html.phone.ph-edit[data-layout~="thumb"].ph-tools-shape .ph-film { margin-top: 0; }
|
|
287
|
+
/* float: the format bar floats just above the selection, as a pill; the filmstrip keeps the bottom */
|
|
288
|
+
html.phone.ph-edit[data-layout~="float"]:not(.ph-typing) .ph-tools { position: fixed; z-index: 25; height: 48px; width: max-content; max-width: calc(100vw - 16px); padding: 2px 4px; border: 0; border-radius: 16px;
|
|
289
|
+
background: var(--ph-surface, #303134); box-shadow: 0 0 0 1px var(--ph-rule), 0 8px 24px rgba(0, 0, 0, .14); }
|
|
290
|
+
html.phone.ph-edit[data-layout~="float"]:not(.ph-typing) .ph-tools > div { height: 44px; padding: 0; }
|
|
291
|
+
html.phone.ph-edit[data-layout~="float"]:not(.ph-typing) .ph-tools .ph-icon-btn { width: 44px; }
|
|
292
|
+
html.phone.ph-edit[data-layout~="float"].ph-tools-text:not(.ph-typing) .ph-film, html.phone.ph-edit[data-layout~="float"].ph-tools-shape:not(.ph-typing) .ph-film { margin-top: 0; height: calc(97px + env(safe-area-inset-bottom)); padding-bottom: env(safe-area-inset-bottom); }
|
|
293
|
+
/* shelf: Home as one column; the deck opened last large, the rest as rows with the date and slide count */
|
|
294
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
|
|
295
|
+
html.phone[data-layout~="shelf"] .hm-folders { grid-template-columns: minmax(0, 1fr); row-gap: 10px; } /* folders one to a row too, so a name has room */
|
|
296
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) .hm-card { display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 14px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--ph-rule); }
|
|
297
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) .hm-card .pic { aspect-ratio: 16 / 9; border-radius: 10px; }
|
|
298
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) .hm-card .meta { padding: 0; min-height: 0; align-items: flex-start; }
|
|
299
|
+
html.phone[data-layout~="shelf"] .hm-card .meta::before { content: none; }
|
|
300
|
+
html.phone[data-layout~="shelf"] .hm-card .title { text-align: left; font: 500 16px/21px var(--font); }
|
|
301
|
+
html.phone[data-layout~="shelf"] .hm-card .sub { display: block; margin-top: 6px; font: 400 12px/1.3 var(--mono, ui-monospace, monospace); color: var(--ph-muted); white-space: normal; }
|
|
302
|
+
html.phone[data-layout~="shelf"] .hm-card .more { height: 28px; margin-top: -4px; }
|
|
303
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) > .hm-card:first-child { grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 4px 0 18px; }
|
|
304
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) > .hm-card:first-child .title { font-size: 21px; line-height: 26px; }
|
|
305
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) > .hm-card { grid-row: auto !important; grid-column: auto !important; } /* desktop Thermal's larger first card spans two rows */
|
|
306
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) > .hm-card:first-child { display: grid !important; }
|
|
307
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) > .hm-card:not(:first-child) .pic { width: 128px; }
|
|
308
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) > .hm-card:first-child .sub { margin-top: 4px; }
|
|
309
|
+
html.phone[data-layout~="shelf"] .hm-grid:not(.list) > .hm-card { border-radius: 0 !important; }
|
|
310
|
+
|
|
311
|
+
/* Long-press on the app's own controls (bars, the pill, the filmstrip, sheets, cards) doesn't select their text or icon
|
|
312
|
+
glyphs, nor open iOS's callout ("Copy | Search with Google"); text being edited, and fields, still select as usual. */
|
|
313
|
+
html.phone body, html.phone body * { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
|
|
314
|
+
html.phone :is([contenteditable="true"], [contenteditable="true"] *, input, textarea) { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
|
|
315
|
+
|
|
316
|
+
/* thumb, in landscape (html.ph-rails, phone-edit.js): side rails. No top bar, so the slide gets all of the height; the
|
|
317
|
+
filmstrip runs down the left; the pill stands on the right as a column (back or ✓, undo, redo, insert, present,
|
|
318
|
+
comments, ⋯). A text box or shape selected turns the column into its format controls: ✓ on top, the three align
|
|
319
|
+
buttons as one, and Cut, Copy, Paste, Delete in a ⋯ at the foot. Slide mode brings its bar back over the slide. */
|
|
320
|
+
html.phone .ph-rail-only, html.phone.ph-rails .ph-dock .ph-done, html.phone.ph-rails.ph-picking .ph-dock .ph-rail-back { display: none !important; }
|
|
321
|
+
html.phone.ph-edit.ph-rails .ph-rail-only:not(.ph-done, .ph-rail-back), html.phone.ph-edit.ph-rails #ph-tools .ph-done,
|
|
322
|
+
html.phone.ph-edit.ph-rails:not(.ph-picking) .ph-dock .ph-rail-back, html.phone.ph-edit.ph-rails.ph-picking .ph-dock .ph-done { display: grid !important; }
|
|
323
|
+
html.phone.ph-edit.ph-rails { --ph-rail-l: calc(112px + env(safe-area-inset-left)); --ph-rail-r: calc(68px + env(safe-area-inset-right)); }
|
|
324
|
+
html.phone.ph-edit.ph-rails:not(.ph-slide) #ph-top { display: none; }
|
|
325
|
+
html.phone.ph-edit.ph-rails main { position: fixed; left: var(--ph-rail-l); right: var(--ph-rail-r); top: 0; bottom: 0; height: auto; margin: 0; }
|
|
326
|
+
html.phone.ph-edit.ph-rails.ph-slide #ph-top { position: fixed; left: var(--ph-rail-l); right: 0; top: 0; padding-right: env(safe-area-inset-right); }
|
|
327
|
+
html.phone.ph-edit.ph-rails.ph-slide main { top: var(--ph-bar-h); right: 0; }
|
|
328
|
+
html.phone.ph-edit.ph-rails:is(.ph-typing, .ph-commenting) main { left: env(safe-area-inset-left); }
|
|
329
|
+
html.phone.ph-edit.ph-rails.ph-commenting main { right: 0; }
|
|
330
|
+
html.phone.ph-edit.ph-rails.ph-commenting .ph-dock { display: none; }
|
|
331
|
+
/* the filmstrip, down the left */
|
|
332
|
+
html.phone.ph-edit.ph-rails #ph-film { position: fixed; z-index: 2; left: 0; top: 0; bottom: 0; width: var(--ph-rail-l); height: auto; margin: 0; padding: 0 0 0 env(safe-area-inset-left); flex-direction: column; border-top: 0; border-right: 1px solid var(--ph-rule); }
|
|
333
|
+
html.phone.ph-edit.ph-rails #ph-film .ph-film-strip { position: relative; flex-direction: column; align-items: center; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; padding: 8px 0 calc(8px + env(safe-area-inset-bottom)); }
|
|
334
|
+
html.phone.ph-edit.ph-rails #ph-film > .ph-film-new { width: 100%; height: calc(44px + env(safe-area-inset-bottom)); padding: 0 0 env(safe-area-inset-bottom); border-left: 0 !important; border-top: 1px solid var(--ph-rule); }
|
|
335
|
+
/* the pill, and the format controls in its place, as a column on the right */
|
|
336
|
+
html.phone.ph-edit.ph-rails[data-layout~="thumb"]:not(.ph-typing):not(.ph-slide) .ph-dock, html.phone.ph-edit.ph-rails #ph-tools {
|
|
337
|
+
position: fixed; z-index: 25; left: auto; right: calc(8px + env(safe-area-inset-right)); top: 50%; bottom: auto; translate: 0 -50%; flex-direction: column; align-items: center;
|
|
338
|
+
width: 52px; height: auto; max-height: calc(100% - 16px); margin: 0; padding: 4px 0; overflow-x: hidden; overflow-y: auto; scrollbar-width: none; border: 0; border-radius: 26px;
|
|
339
|
+
background: var(--ph-surface, #303134); box-shadow: 0 0 0 1px var(--ph-rule), 0 6px 18px rgba(0, 0, 0, .12); }
|
|
340
|
+
html.phone.ph-edit.ph-rails[data-layout~="thumb"]:is(.ph-tools-text, .ph-tools-shape) .ph-dock { display: none; }
|
|
341
|
+
html.phone.ph-edit.ph-rails .ph-dock .ph-icon-btn, html.phone.ph-edit.ph-rails #ph-tools .ph-icon-btn { flex: none; width: 52px; height: 42px; }
|
|
342
|
+
html.phone.ph-edit.ph-rails #ph-tools > div { flex: none; flex-direction: column; align-items: center; height: auto; padding: 0; overflow: visible; }
|
|
343
|
+
html.phone.ph-edit.ph-rails #ph-tools [data-align] { display: none; }
|
|
344
|
+
html.phone.ph-edit.ph-rails #ph-tools .ph-sep { width: 28px; height: 1px; margin: 4px 0; }
|
|
345
|
+
html.phone.ph-edit.ph-rails .ph-done { color: var(--ph-accent-ink); }
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* The comments panel on a shared deck (share.js), in Glideshow's Thermal look (editor/looks/thermal.css): cool paper by
|
|
2
|
+
day and graphite at dusk (the viewer's system setting), the mascot's canopy blue for what's chosen, Hanken Grotesk
|
|
3
|
+
with IBM Plex Mono for counts and times, hairlines rather than shadows. Kept apart from the deck's own styles by the
|
|
4
|
+
gs- prefix. */
|
|
5
|
+
@import url("https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap");
|
|
6
|
+
:root { --gs-page: #eef2f6; --gs-bg: #fff; --gs-ink: #14204a; --gs-muted: #5c6b87; --gs-line: #dbe2ea; --gs-field: #eaf0f6; --gs-hover: #e6ecf5;
|
|
7
|
+
--gs-accent: #2f6bff; --gs-on: #fff; --gs-tint: #d9e4ff; --gs-shadow: rgba(20, 32, 74, .10);
|
|
8
|
+
--gs-font: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif; --gs-mono: "IBM Plex Mono", ui-monospace, Menlo, monospace; }
|
|
9
|
+
@media (prefers-color-scheme: dark) { :root { --gs-page: #17181d; --gs-bg: #1d1e25; --gs-ink: #ececee; --gs-muted: #a1a3aa; --gs-line: #2e2f33; --gs-field: #232427; --gs-hover: #2a2b2f;
|
|
10
|
+
--gs-accent: #8aaeff; --gs-on: #121314; --gs-tint: #2b3447; --gs-shadow: rgba(0, 0, 0, .4); } }
|
|
11
|
+
.gs-panel[hidden], .gs-hint[hidden] { display: none !important; } /* their display: flex would otherwise show them closed */
|
|
12
|
+
.gs-toggle, .gs-panel, .gs-hint { font: 14px/1.45 var(--gs-font); color: var(--gs-ink); -webkit-font-smoothing: antialiased; }
|
|
13
|
+
.gs-panel button, .gs-panel input, .gs-panel textarea { font-family: var(--gs-font); }
|
|
14
|
+
|
|
15
|
+
/* the pill that opens the panel: frosted paper with a hairline, the open comments' count in canopy blue */
|
|
16
|
+
.gs-toggle { position: fixed; top: 14px; right: 14px; z-index: 40; display: flex; align-items: center; gap: 8px; height: 38px; padding: 0 12px 0 14px; border: 0; border-radius: 999px;
|
|
17
|
+
background: color-mix(in srgb, var(--gs-bg) 82%, transparent); box-shadow: 0 0 0 1px var(--gs-line), 0 6px 18px var(--gs-shadow);
|
|
18
|
+
-webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); cursor: pointer; font-weight: 500; }
|
|
19
|
+
.gs-toggle:hover { background: var(--gs-bg); }
|
|
20
|
+
.gs-toggle svg { color: var(--gs-accent); }
|
|
21
|
+
.gs-n { min-width: 20px; height: 20px; padding: 0 6px; box-sizing: border-box; border-radius: 10px; background: var(--gs-accent); color: var(--gs-on); font: 500 12px/20px var(--gs-mono); text-align: center; }
|
|
22
|
+
.gs-n:empty { display: none; }
|
|
23
|
+
body.gs-open .gs-toggle { display: none; } /* the panel has its own × */
|
|
24
|
+
/* Edit (for whoever may edit): a canopy-blue pill left of Comments */
|
|
25
|
+
.gs-edit { position: fixed; top: 14px; right: 142px; z-index: 40; display: flex; align-items: center; gap: 6px; height: 38px; padding: 0 14px 0 12px; border-radius: 999px;
|
|
26
|
+
background: var(--gs-accent); color: var(--gs-on); font: 500 14px/1 var(--gs-font); text-decoration: none; box-shadow: 0 6px 18px var(--gs-shadow); }
|
|
27
|
+
.gs-edit:hover { filter: brightness(1.06); }
|
|
28
|
+
body.gs-open .gs-edit { right: 374px; }
|
|
29
|
+
body.gs-open .reveal:not(.gs-pic-reveal) { width: calc(100% - 360px) !important; }
|
|
30
|
+
body.gs-strip-on .reveal:not(.gs-pic-reveal) { margin-left: 176px; width: calc(100% - 176px) !important; }
|
|
31
|
+
body.gs-strip-on.gs-open .reveal:not(.gs-pic-reveal) { width: calc(100% - 176px - 360px) !important; }
|
|
32
|
+
body.gs-strip-on .sl-bar { left: 196px !important; } /* the slideshow's ◀ n ▶ clear of the filmstrip */
|
|
33
|
+
|
|
34
|
+
/* the filmstrip (share.js): paper with a hairline at its edge; pictures with a hairline, the current one ringed in canopy
|
|
35
|
+
blue, its number in mono, open comments counted in a canopy-blue dot */
|
|
36
|
+
.gs-strip { position: fixed; left: 0; top: 0; bottom: 0; z-index: 38; width: 176px; box-sizing: border-box; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;
|
|
37
|
+
padding: 62px 8px 16px 4px; background: var(--gs-page); border-right: 1px solid var(--gs-line); display: flex; flex-direction: column; gap: 2px; font: 14px/1.4 var(--gs-font); }
|
|
38
|
+
body:not(.gs-strip-on) .gs-strip { display: none; }
|
|
39
|
+
.gs-cell { position: relative; flex: none; display: grid; grid-template-columns: 22px auto; align-items: start; gap: 6px; padding: 6px 6px 6px 2px; border: 0; border-radius: 12px; background: none; cursor: pointer; text-align: right; }
|
|
40
|
+
.gs-cell:hover { background: var(--gs-hover); }
|
|
41
|
+
.gs-num { padding-top: 1px; color: var(--gs-muted); font: 400 11px/1.4 var(--gs-mono); }
|
|
42
|
+
.gs-cell.cur .gs-num { color: var(--gs-accent); font-weight: 500; }
|
|
43
|
+
.gs-pic { position: relative; width: 120px; height: var(--gs-pic-h, 68px); overflow: hidden; border-radius: 6px; box-shadow: 0 0 0 1px var(--gs-line); background: #fff; }
|
|
44
|
+
.gs-cell.cur .gs-pic { box-shadow: 0 0 0 2px var(--gs-accent); }
|
|
45
|
+
.gs-pic-reveal { position: absolute !important; left: 0; top: 0; transform-origin: 0 0; overflow: hidden; pointer-events: none; }
|
|
46
|
+
.gs-pic-reveal .slides { position: absolute !important; }
|
|
47
|
+
.gs-still { display: block; width: 100%; height: 100%; object-fit: contain; background: #000; }
|
|
48
|
+
.gs-cn { position: absolute; right: 10px; bottom: 10px; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: 9px; background: var(--gs-accent); color: var(--gs-on); font: 500 11px/18px var(--gs-mono); text-align: center; }
|
|
49
|
+
.gs-cn:empty { display: none; }
|
|
50
|
+
|
|
51
|
+
/* the panel: paper, a hairline at its edge; a header with the count and × */
|
|
52
|
+
.gs-panel { position: fixed; top: 0; right: 0; bottom: 0; z-index: 39; width: 360px; overflow-y: auto; padding: 0 16px 20px; box-sizing: border-box; background: var(--gs-page);
|
|
53
|
+
border-left: 1px solid var(--gs-line); display: flex; flex-direction: column; gap: 10px; }
|
|
54
|
+
.gs-panel header { position: sticky; top: 0; z-index: 1; display: flex; align-items: center; gap: 8px; margin: 0 -16px; padding: 14px 10px 10px 16px; background: var(--gs-page); }
|
|
55
|
+
.gs-panel h2 { margin: 0; font-size: 18px; font-weight: 500; letter-spacing: -.01em; }
|
|
56
|
+
.gs-panel header .gs-n { background: var(--gs-tint); color: var(--gs-accent); }
|
|
57
|
+
.gs-x { display: grid; place-items: center; width: 36px; height: 36px; margin-left: auto; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--gs-muted); cursor: pointer; }
|
|
58
|
+
.gs-x:hover { background: var(--gs-hover); color: var(--gs-ink); }
|
|
59
|
+
.gs-tools { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
|
60
|
+
.gs-primary { height: 36px; border: 0; border-radius: 999px; padding: 0 16px; background: var(--gs-accent); color: var(--gs-on); font-size: 14px; font-weight: 500; cursor: pointer; }
|
|
61
|
+
.gs-primary:hover { filter: brightness(1.06); }
|
|
62
|
+
.gs-link { border: 0; border-radius: 8px; background: none; color: var(--gs-accent); font-size: 13px; font-weight: 500; cursor: pointer; padding: 6px 8px; }
|
|
63
|
+
.gs-link:hover { background: var(--gs-hover); }
|
|
64
|
+
.gs-check { display: flex; align-items: center; gap: 6px; color: var(--gs-muted); font-size: 13px; cursor: pointer; }
|
|
65
|
+
.gs-check input { accent-color: var(--gs-accent); margin: 0; }
|
|
66
|
+
|
|
67
|
+
/* a comment: a card on a hairline; the current slide's ringed in canopy blue */
|
|
68
|
+
.gs-card { background: var(--gs-bg); border-radius: 14px; padding: 12px 12px 8px 14px; display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; gap: 6px; box-shadow: 0 0 0 1px var(--gs-line); cursor: pointer; transition: box-shadow .2s; }
|
|
69
|
+
.gs-card:hover { box-shadow: 0 0 0 1px var(--gs-line), 0 6px 18px var(--gs-shadow); }
|
|
70
|
+
.gs-card.here { box-shadow: 0 0 0 2px var(--gs-accent); } .gs-card.flash { box-shadow: 0 0 0 3px var(--gs-accent), 0 6px 18px var(--gs-shadow); } .gs-card.done { opacity: .6; }
|
|
71
|
+
.gs-new { cursor: default; box-shadow: 0 0 0 2px var(--gs-accent); }
|
|
72
|
+
.gs-top { display: flex; justify-content: space-between; align-items: baseline; color: var(--gs-muted); font: 400 11px/1.4 var(--gs-mono); letter-spacing: .02em; }
|
|
73
|
+
.gs-chip { font-weight: 500; color: var(--gs-accent); } .gs-by { font-weight: 600; }
|
|
74
|
+
.gs-quote { border-left: 2px solid var(--gs-accent); padding-left: 8px; color: var(--gs-muted); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
75
|
+
.gs-text { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
76
|
+
.gs-reply { padding-top: 6px; border-top: 1px solid var(--gs-line); overflow-wrap: anywhere; } .gs-reply.event { color: var(--gs-muted); font-size: 12px; }
|
|
77
|
+
.gs-acts { display: flex; align-items: center; gap: 2px; margin-top: 2px; }
|
|
78
|
+
.gs-in { flex: 1; min-width: 0; font-size: 14px; color: inherit; background: var(--gs-field); border: 1px solid transparent; border-radius: 10px; padding: 7px 10px; resize: vertical; outline: 0; }
|
|
79
|
+
.gs-in:focus { border-color: var(--gs-accent); background: var(--gs-bg); }
|
|
80
|
+
.gs-in::placeholder { color: var(--gs-muted); }
|
|
81
|
+
textarea.gs-in { width: 100%; box-sizing: border-box; }
|
|
82
|
+
.gs-empty { color: var(--gs-muted); margin: 6px 2px; } .gs-empty a { color: var(--gs-accent); font-weight: 500; }
|
|
83
|
+
.gs-foot { margin: auto 2px 0; padding-top: 18px; font: 400 11px/1.4 var(--gs-mono); } .gs-foot a { color: var(--gs-muted); }
|
|
84
|
+
|
|
85
|
+
/* a comment's place on the slide: a canopy-blue pin with its number, grey once resolved */
|
|
86
|
+
.gs-marker { position: absolute; z-index: 30; width: 60px; height: 60px; margin: -60px 0 0 0; border: 0; border-radius: 30px 30px 30px 6px; background: #2f6bff; color: #fff;
|
|
87
|
+
font: 500 28px/60px "IBM Plex Mono", ui-monospace, monospace; text-align: center; box-shadow: 0 0 0 3px #fff, 0 4px 12px rgba(20, 32, 74, .25); cursor: pointer; padding: 0; }
|
|
88
|
+
.gs-marker.done { background: #a1a3aa; }
|
|
89
|
+
.gs-hint { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 41; padding: 10px 18px; border-radius: 999px; color: var(--gs-ink);
|
|
90
|
+
background: color-mix(in srgb, var(--gs-bg) 88%, transparent); box-shadow: 0 0 0 1px var(--gs-line), 0 8px 24px var(--gs-shadow); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
|
|
91
|
+
body.gs-placing .reveal { cursor: crosshair; }
|
|
92
|
+
/* the deck's sticky notes (Notes for AI, .box.note), which a slideshow hides: on a shared link they show as in the editor,
|
|
93
|
+
a little see-through, so whoever reads the deck sees what's still being worked on; in the filmstrip too */
|
|
94
|
+
.reveal .slides .box.note { display: flex !important; background: #fff3a8; box-shadow: 0 2px 6px rgba(60, 64, 67, .3); opacity: .85; }
|
|
95
|
+
.reveal .slides .box.note > .content { font-size: 32px; color: #3c4043; }
|
|
96
|
+
body.gs-notes-off .reveal .slides .box.note { display: none !important; }
|
|
97
|
+
/* its button, beside the filmstrip's */
|
|
98
|
+
.gs-strip-toggle, .gs-notes-toggle { position: fixed; top: 14px; left: 14px; z-index: 40; display: grid; place-items: center; width: 38px; height: 38px; padding: 0; border: 0; border-radius: 50%; color: var(--gs-muted);
|
|
99
|
+
background: color-mix(in srgb, var(--gs-bg) 82%, transparent); box-shadow: 0 0 0 1px var(--gs-line), 0 6px 18px var(--gs-shadow); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); cursor: pointer; }
|
|
100
|
+
.gs-notes-toggle { left: 60px; }
|
|
101
|
+
.gs-notes-toggle[hidden] { display: none; }
|
|
102
|
+
.gs-strip-toggle:hover, .gs-notes-toggle:hover { color: var(--gs-ink); background: var(--gs-bg); }
|
|
103
|
+
.gs-strip-toggle.on, .gs-notes-toggle.on { color: var(--gs-accent); box-shadow: 0 0 0 1px var(--gs-line); }
|
|
104
|
+
|
|
105
|
+
@media (max-width: 700px) { /* a phone: the panel is a sheet over the lower part, the filmstrip a row along the bottom */
|
|
106
|
+
body.gs-open .reveal:not(.gs-pic-reveal) { width: 100% !important; height: 45vh !important; margin-left: 0; }
|
|
107
|
+
body.gs-strip-on .reveal:not(.gs-pic-reveal) { margin-left: 0; width: 100% !important; height: calc(100% - 92px) !important; }
|
|
108
|
+
body.gs-strip-on .sl-bar { left: 20px !important; bottom: 112px !important; }
|
|
109
|
+
.gs-strip { top: auto; right: 0; width: auto; height: 92px; flex-direction: row; overflow-x: auto; overflow-y: hidden; padding: 8px 8px 8px 4px; border-right: 0; border-top: 1px solid var(--gs-line); }
|
|
110
|
+
.gs-cell { grid-template-columns: auto; padding: 4px; } .gs-num { display: none; }
|
|
111
|
+
body.gs-open .gs-strip { display: none; }
|
|
112
|
+
.gs-panel { top: auto; left: 0; width: auto; height: 55vh; border-left: 0; border-top: 1px solid var(--gs-line); border-radius: 18px 18px 0 0; }
|
|
113
|
+
.gs-panel header { border-radius: 18px 18px 0 0; }
|
|
114
|
+
}
|
|
115
|
+
@media print { .gs-toggle, .gs-panel, .gs-hint, .gs-marker, .gs-strip, .gs-strip-toggle, .gs-notes-toggle, .gs-edit { display: none !important; } body .reveal:not(.gs-pic-reveal) { margin-left: 0 !important; width: 100% !important; } }
|
|
116
|
+
/* Presenting from a shared link: the buttons over the slide (filmstrip, notes, Edit, Comments) fade with the slideshow's
|
|
117
|
+
own toolbar (present.js .sl-bar.idle: 3 s without the mouse moving) and are gone in full screen; moving the mouse
|
|
118
|
+
brings them back. Not while the comments panel is open. */
|
|
119
|
+
.gs-toggle, .gs-edit, .gs-strip-toggle, .gs-notes-toggle { transition: opacity .3s; }
|
|
120
|
+
body:not(.gs-open):has(.sl-bar.idle) :is(.gs-toggle, .gs-edit, .gs-strip-toggle, .gs-notes-toggle) { opacity: 0; pointer-events: none; }
|
|
121
|
+
:root:fullscreen body:not(.gs-open) :is(.gs-toggle, .gs-edit, .gs-strip-toggle, .gs-notes-toggle) { display: none; }
|
|
122
|
+
/* A picture in the speaker view (share/speaker.html): the deck alone, none of this viewer's buttons or the slideshow's toolbar */
|
|
123
|
+
.gs-preview :is(.gs-toggle, .gs-edit, .gs-strip, .gs-strip-toggle, .gs-notes-toggle, .gs-panel, .gs-hint, .sl-bar) { display: none !important; }
|
|
124
|
+
.gs-preview body { cursor: default; }
|