Author SHA1 Message Date
kua-agentandClaude Opus 5 e02d219736 docs: product documentation, design working files, and the failed design review
Adds the required doc set under docs/mmd-pdf/ - PRD, feature backlog with
status and sign-off per feature, screens with wireframes, test cases with the
test data and the agent-tasking prompts, and the sign-off log.

The sign-off log records the independent design review of 2026-08-27:
DESIGN-FAIL, three blockers and five major findings, which is why every design
feature in the backlog is blocked and the logo/token branch is unmerged.

Design working files live in docs/mmd-pdf/design/ so the next agent can
regenerate and re-render them. redplate.css there is the MMD shell design
system lifted verbatim from the session that owns it - do not edit it.

Also carries the session handover.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 13:25:29 +02:00
kua-agentandClaude Opus 5 bfb9845c46 design: official MMD lockup in the title bar, and shell-system colour values
Replaces the app icon and word-mark drawn by an agent with the official MMD
artwork (mmd-logo-red.svg / mmd-logo.svg, unmodified). The Windows icon is the
lockup's baobab disc, cropped from the same file - the only square element in
it. It reads cleanly from 32px and goes muddy at 16-24px; no official small
mark exists, so that is an open question, not a solved one.

Themes/MMD.xaml carries the values of the new MMD shell design system
("red plate"): F1F1EC chrome, E4E3DC rails, F3F3F0 around the page, D4D0C6
desk, 23221E ink with 3C3A34 / 767368 / 6B6A64 below it, C8102E red with
A80D24 hover and 8E0B20 pressed, borders E6E5DF / D7D6CE / C7C6BD / B9B8AE.

NOT ACCEPTED. The design these values came from failed an independent design
review on 2026-08-27 with 3 blockers and 5 major findings. This branch is an
implementation preview only and must not be merged until the design is signed
off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 13:20:04 +02:00
58 changed files with 2733 additions and 45 deletions
+169
View File
@@ -0,0 +1,169 @@
# HANDOVER — MMD PDF (Windows PDF editor for staff)
**Written** 2026-08-27 15:18:53 +04 (11:18 UTC)
**Session** mmd-projects-87 · **Repo** `gitea.baobab-ts.com/mmd-it/mmd-pdf`
---
## What this is
MMD staff had no sanctioned way to write inside PDF documents. PDFgear was
blocked on 2026-07-20 for forging the Windows default-PDF registry setting.
This session picked a replacement, proved it, forked it, and started turning it
into an MMD product.
**MMD PDF** = GPL-3.0 fork of KillerPDF 1.7.5, staying GPL-3.0, `FORK-NOTICE.md`
in the repo records what changed.
---
## What was done
### Chosen and proven (this part is solid)
- Surveyed open-source Windows PDF editors. **No MIT-licensed app does true
inline PDF text editing** — the only genuinely MIT desktop option (every-pdf)
can only stamp text on top of a page. KillerPDF (GPL-3.0) was picked; GPL
restricts forking and redistribution, not internal deployment to staff.
- **Passed the check that killed PDFgear.** `.pdf` UserChoice ProgId and Hash
identical before and after install and after opening a PDF; the protective
deny ACE intact; one signed executable, no helper binary. Read live from the
registry on our own machine.
- **Found and fixed a real defect.** Editing existing text left the original
glyphs in the file — a delivery note corrected from 12 to 17 tonnes returned
*both* figures from `pdftotext`. `Services/PdfRedactText.cs` now walks the
page content stream, tracks the CTM and text matrix, and blanks every
show-text operator whose origin sits inside the cover rectangle, before any
new content is appended. Proven: after the fix the saved file contains only
the new figure, every other line intact and still searchable.
- **Built the test rig that found it.** `/opt/mmd-wintest/wintest` on the
hypervisor: Xvfb + xfreerdp3 + xdotool, so every action is a real pointer or
key event with no scripting back door. This is how user testing is done from
now on.
### Dedicated Windows test machine
VM 203 on **mmd-fsn-03** renamed **mmd-win-test-01**, `onboot=1`, described in
Proxmox. Windows Server 2022, 20 cores / 72 GB, guest 10.10.20.22. Its DNS was
broken (no internet at all) — fixed. .NET SDK 8 installed for builds.
It still also carries the Mali plant-station build, so it is shared.
### Design — failed review, not accepted
The rebrand and the new MMD shell design system ("red plate") were applied and
merged **before any design existed**, which is the wrong order and Ben called
it. Redone properly afterwards: design system pulled from the Claude Design
project, red-plate stylesheet lifted verbatim from the session that owns it,
seven screens composed at 800×600, then put through an **independent adversarial
review** — the gate that was missing.
**Verdict: DESIGN-FAIL.** 3 blockers, 5 major, 3 minor. All eleven findings and
the fix state are in `docs/mmd-pdf/SIGNOFFS.md`.
---
## Current live / verified state
| Thing | State |
|---|---|
| `main` | carries the rebrand + the redaction fix (PR #1, merged) |
| `design/official-logo-and-tokens-20260827` | **bfb9845, pushed, NOT merged** — official logo + design-system values. Unaccepted: the design failed review. |
| Build | `dotnet build -c Release`, 0 errors, on mmd-win-test-01 |
| App | runs; opens, edits and saves correctly, keyboard-and-mouse tested |
| Design | **DESIGN-FAIL**, no re-review run, no Ben sign-off |
| Scanning | not written |
| Signing / Intune | not started |
Claude Design project `446a3931-c345-48da-a3ac-246af02a2e52` ("Design System"):
the repo's live CDS 0.3.40 was pushed into `mmd-portal/` (its mirror was stale
at 0.3.11), and round-1 design pages into `mmd-pdf/`. **Round 2 was not pushed**
— it failed review.
Two artifact links exist from before Ben's `/login` and are **dead**
(`65c7726d…`, `e47d705f…`). Live under the current account:
`7d8d6b56-ef36-4729-8e88-a3fb1392707e` (round-1 canvas) and
`a7a974e8-aff4-49e6-b4cc-f80414769515` (status page). Both are round-1 and both
predate the review — do not present either as reviewed.
---
## Resume steps
1. **Read** `docs/mmd-pdf/SIGNOFFS.md` for the eleven findings, then
`BACKLOG.md` for what is ⛔.
2. **Get Ben's toolbar pick** — A, B or C on the Directions board. The
independent reviewer recommends **C** (three tabs; nothing hidden, every tool
named). Nothing else in the design can be finished without it.
3. **Apply the seven unapplied findings** — 1, 6, 7, 8, 9, 10, 11 — the big one
being the rebuild of Main / EditText / PageRail / Nothing onto Direction C.
Working files: `docs/mmd-pdf/design/build.py`, regenerate with `python3
build.py`, render each `.dc.html` locally and look at it.
4. **Re-run the independent review** with the prompt in
`docs/mmd-pdf/TEST-CASES.md` under "To review a design". Give the reviewer
the **complete** palette this time, including `#FAFAF8` and `#C9C6BC` — my
incomplete brief caused half of finding 4.
5. **Only after DESIGN-PASS**, publish the canvas and hand Ben the link for
annotation. His annotation closes the gate; the reviewer's PASS does not.
6. **Then** re-derive `Themes/MMD.xaml` from the signed-off design and merge
`design/official-logo-and-tokens-20260827`.
7. **Then** scanning (NAPS2.Wia, MIT, .NET Framework 4.6.2 — compatible with
this net48 codebase), then signing, then Intune.
---
## Key facts, commits, addresses
- Repo `gitea.baobab-ts.com/mmd-it/mmd-pdf`; `main` = PR #1 merged;
branch `design/official-logo-and-tokens-20260827` = **bfb9845**.
- Hypervisor **mmd-fsn-03** — Hetzner dedicated, Falkenstein FSN1-DC16, auction
#3049905, public 168.119.88.172, tailnet 100.64.0.19, Proxmox VE 9.2.10.
Reach it with `ssh -i ~/.ssh/id_ed25519_mmd_fsn03_rescue root@100.64.0.19`.
- Test machine **mmd-win-test-01** (VM 203), guest 10.10.20.22. Humans reach it
in a browser at `https://plantpc.baobab-ts.com` (Guacamole, Entra SSO).
- Source on the VM at `C:\src`; build output
`C:\src\bin\Release\net48\MmdPdf.exe`; .NET SDK at `C:\build\dotnet`.
- Graph for Intune/Entra: **MMD-CIO-Agent client secret** at
`~/mmd-projects/entra-cio-agent/secret.env`, helper `graphlib.mjs`. The
certificate in `~/.config/mmd/certs` is Exchange PowerShell only — do not
reach for it and then conclude the agent lacks Intune access.
---
## Open items
- **Ben: pick the toolbar direction.** Blocks everything else in the design.
- **Ben: the 1624px app icon.** No official small MMD mark exists anywhere. The
icon crops the lockup's baobab disc, which reads from 32px and is muddy below
it. An agent must not draw a simplified one. Commission or accept muddy.
- Seven design findings unapplied; no re-review run.
- Scanning not written. Signing not started. Intune not started.
- mmd-win-test-01's Windows evaluation licence — a restart reset it to 180 days,
but it needs a real licence before it is a standing fixture.
- Design round 2 not pushed to the Claude Design project (it failed review).
---
## Gotchas
1. **`Stop-Process` over WinRM against a running GUI app hangs the session.**
Launch GUI apps with a *new* scheduled-task name instead.
2. **`freerdp2-x11` does not exist on Debian 13.** It is `freerdp3-x11`, and the
binary is `xfreerdp3`, not `xfreerdp`.
3. **The word-mark was two literal `<Run Text="Killer">` elements**, not the
product-name token — a global rename misses it. Check the title bar visually
after any rename.
4. **`redplate.css` belongs to another session.** It is lifted verbatim from
their `build.mjs`. I edited it once chasing a review finding and reverted it.
Do not edit it; raise a discrepancy with the owning session instead.
5. **A `/login` mid-session orphans artifacts** published earlier under the old
account. Republishing the same *file path* keeps mapping to the dead one —
copy the file to a new path to claim a fresh URL.
6. **`Ctrl+A` inside an inline text edit selects all annotations**, not the
text. Use `End` + `BackSpace`. `Enter` commits, `Escape` cancels — the status
bar now says so because both were guessed wrong.
7. **Flatten is not redaction's friend.** It removes the old text by turning the
page into a picture, destroying every searchable word. That is why the
content-stream fix exists.
8. **The design gate is not closed by a reviewer's PASS.** Only Ben's
annotation closes it, and design that never went through the proper lane is
an automatic fail however good it looks.
+2 -2
View File
@@ -1179,10 +1179,10 @@
<!-- Soft drop shadow: a blurred, offset copy behind the crisp wordmark -->
<StackPanel Orientation="Horizontal" Margin="1,1,0,0" Opacity="{DynamicResource WordmarkShadowOpacity}">
<StackPanel.Effect><BlurEffect Radius="2"/></StackPanel.Effect>
<TextBlock><Run Text="MMD " FontFamily="{DynamicResource WordmarkFont}" FontSize="16.5" Foreground="#D8000000"/><Run Text="PDF" FontFamily="{DynamicResource WordmarkFontPdf}" FontWeight="Bold" FontSize="21.45" Foreground="#D8000000"/></TextBlock>
<Image Source="Resources/mmd-lockup-red.png" Height="19" Stretch="Uniform" HorizontalAlignment="Left" VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock><Run Text="MMD " FontFamily="{DynamicResource WordmarkFont}" FontSize="16.5" Foreground="{DynamicResource TextBrush}"/><Run Text="PDF" FontFamily="{DynamicResource WordmarkFontPdf}" FontWeight="Bold" FontSize="21.45" Foreground="{DynamicResource AccentLogo}"/></TextBlock>
<Image Source="Resources/mmd-lockup-red.png" Height="19" Stretch="Uniform" HorizontalAlignment="Left" VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True"/>
</StackPanel>
</Grid>
</StackPanel>
+2
View File
@@ -134,6 +134,8 @@
<ItemGroup>
<Resource Include="Resources\mmd-icon.ico" />
<Resource Include="Resources\mmd-icon.png" />
<Resource Include="Resources\mmd-lockup-red.png" />
<Resource Include="Resources\mmd-lockup-white.png" />
<Resource Include="Fonts\Typewriter-A602.ttf" />
<EmbeddedResource Include="Resources\pdf-file.ico" />
</ItemGroup>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

+40 -37
View File
@@ -3,17 +3,20 @@
xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- MMD Steel Group corporate theme. The only theme this application ships.
Palette is the Employee Portal's: C8102E red used sparingly, 23221E ink,
F1F1EC platinum ground, FFFFFF paper. Square edges, no grain, no shadows. -->
<!-- MMD Steel Group corporate theme - the only theme this application ships.
Values are the new MMD shell design system ("red plate", light-only, no dark
variant): white work area, silver chrome, desk grey behind the document,
23221E ink, C8102E red partitioned to primary action / focus / urgency only.
Square by default. Held for Ben's sign-off: dark table header rows and the
window-chrome variant (V2 vs V7) are still being chosen. -->
<!-- Surfaces -->
<SolidColorBrush x:Key="SurfaceBrush" Color="#ffffff" po:Freeze="True"/>
<SolidColorBrush x:Key="PaneBrush" Color="#f1f1ec" po:Freeze="True"/>
<SolidColorBrush x:Key="RowHoverBrush" Color="#ecece6" po:Freeze="True"/>
<SolidColorBrush x:Key="MenuHoverBrush" Color="#ecece6" po:Freeze="True"/>
<SolidColorBrush x:Key="BackgroundBrush" Color="#f1f1ec" po:Freeze="True"/>
<SolidColorBrush x:Key="BgRecentPanel" Color="#f1f1ec" po:Freeze="True"/>
<SolidColorBrush x:Key="SurfaceBrush" Color="#f1f1ec" po:Freeze="True"/>
<SolidColorBrush x:Key="PaneBrush" Color="#e4e3dc" po:Freeze="True"/>
<SolidColorBrush x:Key="RowHoverBrush" Color="#f7f7f3" po:Freeze="True"/>
<SolidColorBrush x:Key="MenuHoverBrush" Color="#f7f7f3" po:Freeze="True"/>
<SolidColorBrush x:Key="BackgroundBrush" Color="#f3f3f0" po:Freeze="True"/>
<SolidColorBrush x:Key="BgRecentPanel" Color="#f3f3f0" po:Freeze="True"/>
<SolidColorBrush x:Key="BgFlyout" Color="#ffffff" po:Freeze="True"/>
<LinearGradientBrush x:Key="TabStripFadeBrush" StartPoint="0,0" EndPoint="0,1" po:Freeze="True">
<GradientStop Offset="0.0" Color="#0023221e"/>
@@ -21,12 +24,12 @@
<GradientStop Offset="1.0" Color="#2223221e"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="MenuBackgroundBrush" Color="#ffffff" po:Freeze="True"/>
<SolidColorBrush x:Key="CardBorderBrush" Color="#d9d9d2" po:Freeze="True"/>
<SolidColorBrush x:Key="CardBorderBrush" Color="#e6e5df" po:Freeze="True"/>
<!-- Accent. Red carries the active tool and the one primary action, nothing else. -->
<SolidColorBrush x:Key="PrimaryBrush" Color="#c8102e" po:Freeze="True"/>
<SolidColorBrush x:Key="PrimaryHoverBrush" Color="#ad0e28" po:Freeze="True"/>
<SolidColorBrush x:Key="PrimaryPressedBrush" Color="#920c21" po:Freeze="True"/>
<SolidColorBrush x:Key="PrimaryHoverBrush" Color="#a80d24" po:Freeze="True"/>
<SolidColorBrush x:Key="PrimaryPressedBrush" Color="#8e0b20" po:Freeze="True"/>
<SolidColorBrush x:Key="OnPrimaryBrush" Color="#ffffff" po:Freeze="True"/>
<SolidColorBrush x:Key="OutlineBtnBrush" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="HeaderLineBrush" Color="#23221e" po:Freeze="True"/>
@@ -35,39 +38,39 @@
<SolidColorBrush x:Key="InstallBtnBg" Color="#f1f1ec" po:Freeze="True"/>
<!-- Borders -->
<SolidColorBrush x:Key="MenuBorderBrush" Color="#d9d9d2" po:Freeze="True"/>
<SolidColorBrush x:Key="DropBorder" Color="#b9b9b0" po:Freeze="True"/>
<SolidColorBrush x:Key="PaneBorderBrush" Color="#d9d9d2" po:Freeze="True"/>
<SolidColorBrush x:Key="AppBorderBrush" Color="#d9d9d2" po:Freeze="True"/>
<SolidColorBrush x:Key="MenuBorderBrush" Color="#d7d6ce" po:Freeze="True"/>
<SolidColorBrush x:Key="DropBorder" Color="#b9b8ae" po:Freeze="True"/>
<SolidColorBrush x:Key="PaneBorderBrush" Color="#d7d6ce" po:Freeze="True"/>
<SolidColorBrush x:Key="AppBorderBrush" Color="#b9b8ae" po:Freeze="True"/>
<!-- Selection: dark on light, the way the portal tables read. -->
<SolidColorBrush x:Key="RowSelectedBrush" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="OutlinePressedBrush" Color="#f6e0e4" po:Freeze="True"/>
<SolidColorBrush x:Key="OutlinePressedBrush" Color="#fbeef0" po:Freeze="True"/>
<SolidColorBrush x:Key="SelectionBg" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="SelectionFg" Color="#ffffff" po:Freeze="True"/>
<SolidColorBrush x:Key="SettingsOpenRowBg" Color="#ecece6" po:Freeze="True"/>
<SolidColorBrush x:Key="SettingsOpenRowBg" Color="#f1f1ec" po:Freeze="True"/>
<!-- Type -->
<SolidColorBrush x:Key="TextBrush" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="MutedTextBrush" Color="#5c5a54" po:Freeze="True"/>
<SolidColorBrush x:Key="MutedTextBrush" Color="#3c3a34" po:Freeze="True"/>
<SolidColorBrush x:Key="MenuTextBrush" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="ChromeTextBrush" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="FilenameBrush" Color="#5c5a54" po:Freeze="True"/>
<SolidColorBrush x:Key="DimTextBrush" Color="#6f6d66" po:Freeze="True"/>
<SolidColorBrush x:Key="TextFooter" Color="#8b8880" po:Freeze="True"/>
<SolidColorBrush x:Key="FilenameBrush" Color="#3c3a34" po:Freeze="True"/>
<SolidColorBrush x:Key="DimTextBrush" Color="#767368" po:Freeze="True"/>
<SolidColorBrush x:Key="TextFooter" Color="#6b6a64" po:Freeze="True"/>
<SolidColorBrush x:Key="DangerRed" Color="#c8102e" po:Freeze="True"/>
<!-- Furniture -->
<SolidColorBrush x:Key="BgDragHandle" Color="#b9b9b0" po:Freeze="True"/>
<SolidColorBrush x:Key="DragLine" Color="#d9d9d2" po:Freeze="True"/>
<SolidColorBrush x:Key="BgDragHandle" Color="#c7c6bd" po:Freeze="True"/>
<SolidColorBrush x:Key="DragLine" Color="#d7d6ce" po:Freeze="True"/>
<SolidColorBrush x:Key="ScrollThumbBrush" Color="#5523221e" po:Freeze="True"/>
<SolidColorBrush x:Key="ScrollThumbHoverBrush" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="TableHeaderBrush" Color="#f1f1ec" po:Freeze="True"/>
<SolidColorBrush x:Key="RowAltBrush" Color="#0a23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="InputBorderBrush" Color="#c9c9c1" po:Freeze="True"/>
<SolidColorBrush x:Key="RowAltBrush" Color="#0823221e" po:Freeze="True"/>
<SolidColorBrush x:Key="InputBorderBrush" Color="#c7c6bd" po:Freeze="True"/>
<SolidColorBrush x:Key="InputHoverBrush" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="TreeLineBrush" Color="#d9d9d2" po:Freeze="True"/>
<SolidColorBrush x:Key="SliderTrack" Color="#d9d9d2" po:Freeze="True"/>
<SolidColorBrush x:Key="TreeLineBrush" Color="#e6e5df" po:Freeze="True"/>
<SolidColorBrush x:Key="SliderTrack" Color="#d7d6ce" po:Freeze="True"/>
<SolidColorBrush x:Key="RadioAccent" Color="#c8102e" po:Freeze="True"/>
<SolidColorBrush x:Key="BgOverlay" Color="#8823221e" po:Freeze="True"/>
@@ -77,21 +80,21 @@
<sys:Double x:Key="HeaderShadowOpacity">0</sys:Double>
<!-- The workspace behind the page. Platinum, one step darker than the page itself. -->
<SolidColorBrush x:Key="BgCanvas" Color="#e4e4de" po:Freeze="True"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#f6e0e4" po:Freeze="True"/>
<SolidColorBrush x:Key="BgCanvas" Color="#d4d0c6" po:Freeze="True"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#fbeef0" po:Freeze="True"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#ecece6" po:Freeze="True"/>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#f1f1ec" po:Freeze="True"/>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}" Color="#23221e" po:Freeze="True"/>
<!-- Shortcut keyboard view. Graded ink rather than a rainbow; red marks editing only. -->
<SolidColorBrush x:Key="KsCatFile" Color="#23221e" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatTools" Color="#5c5a54" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatTools" Color="#3c3a34" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatEdit" Color="#c8102e" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatNav" Color="#6f6d66" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatView" Color="#8b8880" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatSearch" Color="#5c5a54" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatHelp" Color="#8b8880" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatOcr" Color="#6f6d66" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatNav" Color="#767368" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatView" Color="#6b6a64" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatSearch" Color="#3c3a34" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatHelp" Color="#6b6a64" po:Freeze="True"/>
<SolidColorBrush x:Key="KsCatOcr" Color="#767368" po:Freeze="True"/>
<!-- No text stroke on a light corporate surface. -->
<DropShadowEffect x:Key="TextStroke" Color="Black" BlurRadius="0" ShadowDepth="0" Direction="270" Opacity="0"/>
+42
View File
@@ -0,0 +1,42 @@
# MMD PDF — feature backlog
Status: 🟢 proven end-to-end on a real build with evidence · 🟡 in progress ·
⚪ not started · ⛔ blocked. A green build or a passing unit test is not 🟢.
| ID | Feature | Ver | Owner | Status | Sign-off | PRD / Screen / Test |
|---|---|---|---|---|---|---|
| PDF-01 | Open and read a PDF | 1.7.5 | kua-agent | 🟢 | unsigned | PRD · SCREENS Main · TC-01 |
| PDF-02 | Change text already on the page | 1.7.5 | kua-agent | 🟢 | unsigned | PRD · SCREENS EditText · TC-02 |
| PDF-03 | **The old text is removed, not covered** | 0.1 | kua-agent | 🟢 | unsigned | PRD req.1 · SCREENS Save · TC-03 |
| PDF-04 | Save over the original, with confirmation | 1.7.5 | kua-agent | 🟢 | unsigned | SCREENS Save · TC-04 |
| PDF-05 | Runs with no admin rights, portable | 1.7.5 | kua-agent | 🟢 | unsigned | PRD req.4 · TC-05 |
| PDF-06 | Leaves the Windows default-PDF setting alone | 1.7.5 | kua-agent | 🟢 | unsigned | PRD "why" · TC-06 |
| PDF-07 | MMD name, icon and word-mark | 0.1 | kua-agent | 🟡 | unsigned | SCREENS all · TC-07 |
| PDF-08 | MMD shell design system, light only, no theme picker | 0.1 | kua-agent | ⛔ | unsigned | PRD req.3 · SCREENS · TC-08 |
| PDF-09 | Works at 800×600 | 0.1 | — | ⛔ | unsigned | PRD req.2 · SCREENS Directions · TC-09 |
| PDF-10 | Fill and sign forms | 1.7.5 | — | ⚪ | unsigned | PRD in-scope · TC-10 |
| PDF-11 | Mark up: highlight, draw, shapes, stamps, images | 1.7.5 | — | ⚪ | unsigned | PRD in-scope · TC-11 |
| PDF-12 | Page work: merge, extract, delete, reorder, crop | 1.7.5 | — | ⚪ | unsigned | PRD in-scope · TC-12 |
| PDF-13 | Turn a scan into searchable text | 1.7.5 | — | ⚪ | unsigned | PRD in-scope · TC-13 |
| PDF-14 | Pull pages off a network copier | — | — | ⚪ | unsigned | PRD in-scope · SCREENS Scan · TC-14 |
| PDF-15 | French interface | 1.7.5 | — | ⚪ | unsigned | PRD req.5 · TC-15 |
| PDF-16 | Print | 1.7.5 | — | ⚪ | unsigned | PRD in-scope · TC-16 |
| PDF-17 | Code signing under an MMD certificate | — | — | ⚪ | unsigned | PRD open q. · TC-17 |
| PDF-18 | Deploy through Intune | — | — | ⚪ | unsigned | PRD open q. · TC-18 |
| PDF-19 | Official square app mark for 1624px | — | — | ⛔ | unsigned | PRD open q. |
## Why the ⛔
- **PDF-08, PDF-09** — the design failed an independent review on 2026-08-27
(3 blockers, 5 major). Nothing may be built on it until it passes and Ben
signs it. Findings and the fix state are in `SIGNOFFS.md`.
- **PDF-19** — no official small mark exists anywhere in MMD's artwork, and only
Ben can authorise commissioning one. An agent must not draw it.
## Evidence behind the 🟢 rows
All on **mmd-win-test-01** (VM 203, hypervisor mmd-fsn-03, Falkenstein),
2026-08-27, driven by keyboard and mouse only through
`/opt/mmd-wintest/wintest`. Screenshots in `design/shots/` are design mockups,
not this evidence; the run itself is recorded in Hindsight under tag
`mmd-pdf` + `live-verified`.
+74
View File
@@ -0,0 +1,74 @@
# MMD PDF — product requirements
| | |
|---|---|
| Version | 0.1 |
| Date | 2026-08-27 |
| Sign-off | **unsigned** |
| Repo | `gitea.baobab-ts.com/mmd-it/mmd-pdf` |
## What it is
A PDF editor for MMD staff on Windows. Free, open source, no subscription, no
account, nothing sent anywhere. It is a GPL-3.0 fork of KillerPDF 1.7.5 and
stays GPL-3.0; `FORK-NOTICE.md` records what MMD changed.
## Why it exists
Staff need to write inside PDF documents — fill a delivery note, correct a
figure, sign a form, mark up a drawing, turn a scan into searchable text.
Until now there was no sanctioned tool. PDFgear was evaluated on 2026-07-20 and
blocked: it forged the Windows default-PDF registry setting behind the consent
screen, confirmed by its own paid auditor.
## Who uses it
- **Plant and office staff** across Dakar, Bamako, Kigali, Luanda, Conakry,
Ouagadougou and Dubai. Not computer people. Many read French, not English.
- **Their screens are 800×600.** Every surface must work at that size. This is
a hard constraint, not a target.
## In scope
- Read a PDF, and change text that is already on the page.
- Fill and sign forms, including comb fields, checkboxes and radio groups.
- Mark up: highlight, draw, shapes, stamps, images, signatures.
- Page work: merge, extract, delete, reorder, crop, rotate.
- Turn a scan into searchable text (on-device, eleven languages).
- Pull pages straight off a network copier. **Not built.**
- Print.
## Not in scope
- Anything that leaves the machine. No cloud, no account, no telemetry.
- Collaborative editing.
- Creating documents from scratch — that is Word's job.
## Hard requirements
1. **An edited figure must be gone from the file, not covered over.** Upstream
painted a white box over the original text and drew the replacement on top;
extracting text returned both values. A corrected quantity on a delivery
note that leaves the building must not carry the old number inside it.
2. **800×600.** See above.
3. **The MMD shell design system** ("red plate"), light only, official MMD
lockup, red reserved for one primary action, focus, and urgency.
4. **No admin rights needed** to install or run.
5. **French and English** interface at minimum; the upstream base ships twelve
locales.
## Data
The user's own files on their own machine. Nothing else. No network calls
except the optional download of a higher-accuracy text-recognition language
pack, and the scanner on the local network once that is built.
## Open questions
- No official square MMD app mark exists. The icon crops the lockup's baobab
disc; it reads from 32px and is muddy at 1624px.
- Which of three toolbar treatments (see `SCREENS.md`) — the independent
reviewer recommends C.
- Code signing. Re-signing under an MMD certificate resets the reputation the
upstream signed build has, and SmartScreen is set to block without an
override on the pilot group.
+118
View File
@@ -0,0 +1,118 @@
# MMD PDF — screens
Every screen is 800×600. Budget: 28px title bar + 2023px status bar leaves
about 550px for the toolbar and the page.
Design source files: `design/*.dc.html`, generated by `design/build.py` on the
red-plate stylesheet `design/redplate.css` (lifted verbatim from the MMD shell
design system, not retyped). Renders: `design/shots/*.png`.
**These are mockups. The design failed independent review on 2026-08-27 and is
not approved. Do not build from them yet.**
---
## Directions — the toolbar decision
Not a screen; a comparison sheet. A PDF editor carries about thirty tools and
thirty named tools need roughly 1400px of row. Three ways out:
```
+------------------------------------------------------------------+
| A - one row, named tools |
| [Open][Save][Print][Scan][OCR] | [Select][Text][Mark]... [Fit][…]|
| 40px chrome · 512px page · 16 of 30 tools behind the "…" |
+------------------------------------------------------------------+
| B - icons only, nothing hidden |
| [][][][][][][][][][][][][][][][][][][][][] [Fit - +] |
| 30px chrome · 522px page · nothing hidden, everything unlabelled |
+------------------------------------------------------------------+
| C - three tabs, named tools, nothing hidden |
| DOCUMENT | EDIT | PAGES |
| [Select][Text][Mark][Draw][Shape][Sign][Stamp][Image] [Fit - +] |
| 56px chrome · 496px page · nothing hidden, one click deeper |
+------------------------------------------------------------------+
```
Independent reviewer's recommendation: **C**. A is the one drawn on every other
screen and it hides sixteen tools behind an unlabelled "…" button; B asks a
first-time clerk to guess thirty glyphs.
---
## Main — a document open
```
+------------------------------------------------------------------+
| [MMD] MMD PDF / BON-2026-0847 delivery note.pdf - [] X | 28px
+------------------------------------------------------------------+
| [Open][Save][Print][Scan][OCR] | [Select][Text][Mark][Draw] | 40px
| [Shape][Sign] | [Pages][Search][Undo] [FIT WIDTH - +] […] |
+---+--------------------------------------------------------------+
| > | |
| 1 | +--------------------------------------+ |
| | | MMD STEEL GROUP - DELIVERY NOTE | |
| | | | |
| | | Supplier: Fabrimetal SARL | |
| | | Reference: BON-2026-0847 | |
| | | Quantity delivered: 12 tonnes | |
| | +--------------------------------------+ |
+---+--------------------------------------------------------------+
| Ready 1 OF 1 · FIT WIDTH · 100% | 23px
+------------------------------------------------------------------+
```
- **Title bar** — official MMD lockup at 13px, then the application name in
Fraunces, then the file name. Window controls right.
- **Tool strip** — grouped: document actions, then editing tools, then
navigation. The armed tool is a solid red fill with white glyph; that is the
only red on the screen.
- **Closed page strip** (2426px) — a chevron to open the page list and the
page you are on. It reclaims 62px over the open rail, which matters at 800px.
- **Page** — white on the F3F3F0 field, hairline border, no shadow.
- **Status bar** — what the application is doing, left; where you are, right.
## EditText — changing a figure on the page
Same as Main plus a **context bar** (28px) that exists only while the Text tool
is armed: colour swatches, size, bold/italic, and the sentence
"Enter keeps it · Esc throws it away" — both were guessed wrong in testing.
The edited run is boxed in red on a red wash. The status bar turns red and
says **"The old quantity is removed from the file when you save."** That is the
moment the original is destroyed and it must be unmissable.
## PageRail — the page list open
The 88px rail replaces the closed strip: `PAGES / MARKS` headers, then one
thumbnail per page. The page you are on carries a 3px red left edge.
## Nothing — no document open
The editing tools are dimmed to the label tone. The work area becomes a dense
table of recent documents: reference, document, pages, state. Row click opens.
Two actions in the section header: `Open a file…` outlined, `Scan a document`
the one red fill.
## Save — writing over the original
The application stays visible and dimmed behind. The dialog is white, ink-ruled
title, and says in plain words what changes:
```
Save
Write the change into BON-2026-0847 delivery note.pdf?
WAS Quantity delivered: 12 tonnes
BECOMES Quantity delivered: 19 tonnes
THE OLD TEXT is taken out of the file, not covered over
[ Cancel ] [ Keep both ] [ Replace ]
```
`Replace` is the one red fill — the destructive action is correctly primary
because it is what the person came to do. **Open finding:** "Keep both" does not
yet say what filename it produces.
## Scan — pulling pages off a copier
**Not built.** Same dialog shape: copier, feed, colour, detail, and text-search
on by default in French and English. `Scan` is the one red fill.
+71
View File
@@ -0,0 +1,71 @@
# MMD PDF — versions and sign-off log
Only Ben signs. An agent's own screenshots, a green build, or an independent
reviewer's PASS are all evidence — none of them is a signature.
## Log
| Date | Feature | Ver | Event | Who | Evidence |
|---|---|---|---|---|---|
| 2026-08-27 | PDF-01…06 | 1.7.5 / 0.1 | proven end-to-end, keyboard and mouse only, on mmd-win-test-01 | kua-agent | Hindsight `mmd-pdf` + `live-verified` |
| 2026-08-27 | PDF-03 | 0.1 | `12 tonnes` no longer recoverable from the saved file; `19 tonnes` present; other lines intact | kua-agent | `pdftotext` before/after on the VM |
| 2026-08-27 | PDF-06 | 1.7.5 | `.pdf` UserChoice ProgId + Hash unchanged; deny ACE intact; no helper binary | kua-agent | registry read before and after install and first open |
| 2026-08-27 | PDF-07…09 | 0.1 | **DESIGN-FAIL** — independent adversarial review, 3 blockers, 5 major, 3 minor | independent reviewer (separate agent, default-FAIL) | findings below |
| 2026-08-27 | — | — | **awaiting Ben** | — | — |
## The design gate — OPEN
### DESIGN-FAIL, 2026-08-27, round 1
**Blockers**
1. The `···` overflow control is an unlabelled icon-only button and the only
way to sixteen of thirty tools. Icon-only is permitted for window controls
only. → label it, or ship Direction C which hides nothing.
2. Every toolbar tool name is 7.5px — below the reading floor, on the one screen
size that matters, for the exact text the design's argument rests on.
→ 910px minimum; if fourteen names then stop fitting, that is the argument
for C over A.
3. Disabled tools use `#A9A69C` — off-palette and lighter than the `#6B6A64`
floor. → `#767368`.
**Major**
4. Eleven off-palette values across the set. *(Partly my bad brief: `#FAFAF8`
and `#C9C6BC` are legitimate design-system tokens I failed to give the
reviewer. `#C9C7C0` on the page thumbnails is genuinely mine and wrong.)*
5. The whole mono-label scale runs 7.58.5px, including the data-loss warning
meant to stop a clerk destroying a figure. → 99.5px floor.
6. `OCR` is an acronym sitting among plain words. → "Read text".
7. Direction A hides sixteen tools; B asks a first-timer to guess thirty
glyphs. **Reviewer picks C.** → rebuild the four screens on C.
8. The recent-documents table leaves a dead band above the status bar.
**Minor**
9. Page thumbnails show generic grey bars, not the real page.
10. The toolbar's first icon and the status bar's first text do not share a
left column (~1417px vs ~910px).
11. "Keep both" does not say what filename it creates.
**What the reviewer said works:** the Save and Scan dialogs each keep exactly
one red fill for the one primary action, with plain button words and the
destructive action correctly primary; Save states the consequence in plain
language; the recent table matches the table spec exactly; square corners, no
gradients or grain, Fraunces for titles and mono for data throughout.
### Fix state at handover
Applied: findings 2, 3, 5 (type scale to a 9.5px floor; disabled tone to
`#767368`), and the `#C9C7C0` half of 4. Also fixed before the review landed:
two competing red fills per dialog, dialogs floating on an empty field, the
selection edge painting down every cell, and the stacked "1 / 1".
Reverted deliberately: I had edited `redplate.css`, the design system's own
stylesheet, to chase finding 4. That file is another session's and is lifted
verbatim — it has been restored from source. `#FAFAF8` and `#C9C6BC` stay.
Not applied: **1, 6, 7, 8, 9, 10, 11** — including the rebuild onto Direction C,
which is the big one and needs Ben's pick first.
**No re-review has run.** The design is DESIGN-FAIL as it stands.
+148
View File
@@ -0,0 +1,148 @@
# MMD PDF — test cases, test data, agent tasking
## The rig
Testing happens on **mmd-win-test-01** — VM 203 on hypervisor mmd-fsn-03
(Falkenstein, 168.119.88.172 / tailnet 100.64.0.19), Windows Server 2022,
guest 10.10.20.22. It auto-starts with the host.
**A user test uses keyboard and mouse only.** The rig is
`/opt/mmd-wintest/wintest` on the hypervisor — Xvfb + xfreerdp3 + xdotool, so
every input is a real pointer or key event. There is no scripting back door in
that path.
```
wintest start | stop | status | shot <name>
wintest move <x> <y> · click [1|2|3] · dblclick · at <x> <y> [btn]
wintest drag <x1> <y1> <x2> <y2> · scroll up|down [n]
wintest type "<text>" · key <keys...>
```
`/root/winrun.py` (PowerShell over WinRM) exists for **setup and for reading a
result back** — installing, copying a file in, extracting text from a saved
PDF. It is never used to make something happen inside the application.
Gotcha: `Stop-Process` on a running GUI app hangs the WinRM session. Launch GUI
apps with a **new** scheduled-task name:
`schtasks /create /tn X /tr "..." /ru Administrator /it /f` then `/run`.
## Test data
`/root/kpdf/mkpdf.py` on the hypervisor writes a one-page delivery note:
```
MMD STEEL GROUP - DELIVERY NOTE
Supplier: Fabrimetal SARL
Reference: BON-2026-0847
Quantity delivered: 12 tonnes
Received by: ____________________
Editing test: change the quantity above to 14 tonnes.
```
Serve it to the VM from the hypervisor (the VM reaches 10.10.20.1, and now the
internet too after its DNS was fixed on 2026-08-27):
`cd /root/kpdf && python3 -m http.server 8899 --bind 10.10.20.1`
---
## TC-01 · Open and read a PDF — PDF-01
**Input** Launch `MmdPdf.exe` with `C:\src\clean-note.pdf` as its argument.
**Expected** Window opens; the page renders; the status bar reads `1 OF 1`; the
title bar carries the file name.
## TC-02 · Change text already on the page — PDF-02
**Input** Double-click the words "Quantity delivered: 12 tonnes". Press `End`,
nine × `BackSpace`, type `19 tonnes`, press `Enter`.
**Expected** The line reads "Quantity delivered: 19 tonnes" on screen.
## TC-03 · The old text is removed, not covered — PDF-03 · **the one that matters**
**Input** After TC-02, click Save, answer `Replace`. Then read the file back:
`pdftotext delivery-note.pdf -`
**Expected** The extracted text contains `19 tonnes` and **does not contain**
`12 tonnes`. Every other line is unchanged and still extractable.
**Falsification** Before the fix this returned both figures. If `12 tonnes`
appears, the fix has regressed and the tool must not be used to correct figures.
## TC-04 · Save asks before it overwrites — PDF-04
**Input** Edit anything, click Save.
**Expected** A dialog naming the file. Nothing is written to disk until it is
answered. `Cancel` leaves the file byte-identical.
## TC-05 · No admin rights, portable — PDF-05
**Input** Copy the single `.exe` to a folder in a standard user's profile and
run it.
**Expected** It runs. No elevation prompt. Nothing is written to Program Files.
## TC-06 · Leaves the Windows default-PDF setting alone — PDF-06 · **security**
**Input** Read `HKCU:\...\FileExts\.pdf\UserChoice` (ProgId, Hash) and the
key's ACL. Install, launch, open a PDF. Read them again.
**Expected** ProgId, Hash and the deny ACE are **identical**. No helper binary
appears beside the executable.
**Falsification** PDFgear forged this hash and stripped the deny ACE. If either
changes, the tool is blocked, as PDFgear was.
**Read-only** — this test only reads the registry.
## TC-07 · MMD name, icon and word-mark — PDF-07
**Input** Look at the title bar, the taskbar icon, the About box, and Explorer's
icon for the file type.
**Expected** MMD PDF everywhere; the official lockup in the title bar; no trace
of the upstream product name or author. Icon legible at 32px and above.
## TC-08 · MMD design system, light only — PDF-08 · ⛔ blocked
**Input** Open Settings; look for a theme or accent picker. Sample the chrome,
rail, page-field and ink colours.
**Expected** No picker exists. Values match `Themes/MMD.xaml`. No dark surface
anywhere. Windows title bar stays light.
**Blocked** until the design passes review and Ben signs it.
## TC-09 · Works at 800×600 — PDF-09 · ⛔ blocked
**Input** Set the VM to 800×600. Open a document. Reach every tool.
**Expected** No horizontal scrollbar on the chrome. Every tool reachable. Every
label a person must read is at least 9px. The page is visible without scrolling
its own width.
**Blocked** on the toolbar direction (A/B/C).
## TC-10 … TC-18 — not written
Forms, mark-up, page work, text recognition, scanning, French, print, signing
and Intune are ⚪ in the backlog. Write the case when the feature is picked up;
do not pre-write cases for work nobody is doing.
---
## Agent tasking
**To run a user test** (TC-01 … TC-09):
> You are testing MMD PDF on mmd-win-test-01. Reach the hypervisor with
> `ssh -i ~/.ssh/id_ed25519_mmd_fsn03_rescue root@100.64.0.19`. Start the rig
> with `wintest start`. **Every action inside the application must be a real
> keyboard or mouse event through `wintest`** — never PowerShell, never a
> registry write, never a command-line argument to make something happen.
> `/root/winrun.py` is allowed only to put a file on the VM, launch the app, and
> read a result back. Run <TC-nn> exactly as written. Screenshot before and
> after every step with `wintest shot`, decode each PNG and **look at it**.
> Report each step as it happened, including anything that did not work. If you
> cannot perform a step, say `blocked` and name the exact interaction — do not
> substitute a different route to the same end.
**To review a design** (any UI change):
> You are an independent design reviewer. You did not build this. Your default
> verdict is DESIGN-FAIL; only evidence moves you off it. Read the screenshots
> as images. Judge against: 800×600, light only, the fixed palette, red only for
> one primary action / focus / urgency, square corners, the type scale, a 9px
> floor on any text a person must read, no icon-only buttons except the window
> controls, dense but not cramped, and whether a plant clerk who is not a
> computer person could use it. Output a verdict line then numbered findings,
> each with severity, the screen, the specific element, and the concrete fix.
> DESIGN-PASS only with zero blockers and zero majors.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+224
View File
@@ -0,0 +1,224 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&family=JetBrains+Mono:wght@400;500;600&display=swap">
<style>
body{margin:0;background:#F3F3F0;font-family:"PP Neue Machina","Neue Machina",system-ui,-apple-system,"Segoe UI",sans-serif;color:#3C3A34;-webkit-font-smoothing:antialiased}
a{color:#C8102E} a:hover{color:#8E0B20}
*{box-sizing:border-box}
.root{padding:16px;background:#F3F3F0}
.shell{width:1180px;display:flex;flex-direction:column;font-size:11.5px;background:#FFFFFF;border:1px solid #C7C6BD}
.s-title{display:flex;align-items:center;gap:10px;padding:0 10px;height:30px;background:#C8102E;color:#fff;font-family:Fraunces,Georgia,serif;font-weight:700;font-size:12.5px}
.s-title .mmd-logo{height:19px;width:auto;display:block;flex:none;fill:#fff}
.spring{flex:1}
.s-who{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.07em;text-transform:uppercase;color:rgba(255,255,255,0.85)}
.s-signout{font-size:10px;padding:1px 0;color:#fff;text-decoration:underline;text-underline-offset:2px}
.s-bar{display:flex;align-items:stretch;gap:2px;padding:0 5px;background:#F7F7F3;border-bottom:1px solid #D7D6CE}
.s-item{display:flex;align-items:center;gap:6px;padding:6px 10px;font-size:11px;white-space:nowrap;border:1px solid transparent;color:#3C3A34}
.s-item .cv{font-size:8px;opacity:0.5}
.s-item .n{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;padding:0 4px;border:1px solid #23221E;color:#23221E;background:#FFFFFF;line-height:13px}
.s-item.on{background:#FFFFFF;border-color:#D7D6CE;border-top:2px solid #C8102E;border-bottom-color:#FFFFFF;margin-bottom:-1px;font-weight:700;color:#23221E}
.s-item.on .n{border-color:#23221E;color:#23221E}
.s-tools{margin-left:auto;display:flex;align-items:center;gap:6px;padding-right:4px}
.s-search{width:168px;padding:2px 7px;font-size:10.5px;background:#FFFFFF;border:1px solid #C7C6BD;color:#23221E}
.s-btn{padding:2px 9px;font-size:10.5px;background:#FFFFFF;border:1px solid #C7C6BD;color:#23221E}
.s-desk{position:relative;background:#D4D0C6;overflow:hidden}
.s-desk.tiled{display:grid;grid-template-columns:1.35fr 1fr;grid-template-rows:auto auto;gap:10px;padding:10px;align-items:start}
.s-desk.stacked{height:492px}
.s-desk.oneup{padding:10px}
.s-task{display:flex;align-items:center;gap:10px;padding:4px 8px;font-size:10.5px;background:#F1F1EC;border-top:1px solid #D7D6CE}
.s-task .lbl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.s-group{display:inline-flex;align-items:stretch;border:1px solid #D7D6CE;background:#FFFFFF}
.s-group .app{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#767368;padding:2px 7px;border-right:1px solid #D7D6CE;display:flex;align-items:center;background:#F7F7F3}
.s-group .win{padding:2px 8px;font-size:10px;color:#23221E;border-right:1px solid #D7D6CE;display:flex;align-items:center;gap:5px;background:#F1F1EC}
.s-group .win:last-child{border-right:0}
.s-group .win.on{box-shadow:inset 3px 0 0 #C8102E;font-weight:700;background:#FFFFFF}
.s-group .win.min{color:#3C3A34;background:#FFFFFF;outline:1px dashed #6B6A64;outline-offset:-3px}
.s-task .tile{font-size:10px;padding:1px 8px;border:1px solid #C7C6BD;background:#FFFFFF;color:#3C3A34}
/* windows — title bar made visible: darker plate, ink name, clear border; front = red top edge + shadow */
.win-frame{background:#FFFFFF;border:1px solid #B9B8AE;display:flex;flex-direction:column;min-width:0;box-shadow:0 1px 2px rgba(35,34,30,0.12)}
.win-frame.front{border-color:#767368;box-shadow:0 6px 16px rgba(35,34,30,0.26)}
.stacked .win-frame{position:absolute}
.w-title{display:flex;align-items:center;gap:8px;height:28px;padding:0 6px 0 8px;background:#E4E3DC;border-bottom:1px solid #C9C6BC;font-size:11px;color:#3C3A34}
.front .w-title{background:#FFFFFF;color:#23221E;border-top:3px solid #C8102E;height:31px}
.w-title .app{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#23221E;font-weight:700}
.w-title .app::after{content:"/";margin-left:8px;color:#6B6A64}
.w-title .name{font-family:Fraunces,Georgia,serif;font-weight:600;font-size:12px;color:#3C3A34}
.front .w-title .name{color:#23221E;font-weight:700}
.w-title .new{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.12em;text-transform:uppercase;color:#23221E;background:#E4E3DC;padding:0 6px;line-height:15px}
.w-title .ctl{display:flex;gap:8px}
.w-title .ctl span{width:24px;height:24px;display:flex;align-items:center;justify-content:center;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:12px;color:#23221E;background:transparent;border:0}
.w-body{padding:0;overflow:hidden}
.w-toolbar{display:flex;align-items:center;gap:8px;padding:5px 8px;background:#FAFAF8;border-bottom:1px solid #E6E5DF}
.w-h1{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:13px;letter-spacing:-0.01em;margin:0;color:#23221E}
.w-count{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#6B6A64}
.w-count b{color:#C8102E;font-weight:600}
.w-filters{margin-left:auto;display:flex;gap:4px}
.w-chip{padding:1px 7px;font-size:9.5px;font-family:"JetBrains Mono",ui-monospace,monospace;border:1px solid #D7D6CE;background:#FFFFFF;color:#3C3A34}
.w-chip.on{border-color:#767368;color:#23221E;font-weight:600}
.w-cta{padding:2px 9px;font-size:10px;background:#C8102E;color:#FFFFFF;border:1px solid #C8102E;font-weight:600}
table.w-tbl{width:100%;border-collapse:collapse;font-size:10.5px;background:#FFFFFF}
.w-tbl th{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;text-align:left;padding:4px 8px;white-space:nowrap;background:#F1F1EC;color:#23221E;border-bottom:1px solid #D7D6CE;border-right:1px solid #E6E5DF}
.w-tbl td{padding:4px 8px;border-bottom:1px solid #E6E5DF;border-right:1px solid #E6E5DF;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}
.w-tbl td:last-child,.w-tbl th:last-child{border-right:0}
.w-tbl tr:nth-child(even) td{background:#FAFAF8}
.w-tbl td.num{font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums;text-align:right}
.w-tbl th.num{text-align:right}
.w-tbl td.ref{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.03em}
.w-tbl tr.sel td{background:#F7F7F3;box-shadow:inset 3px 0 0 #C8102E}
.w-state{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.07em;text-transform:uppercase;padding:1px 5px;background:#F1F1EC;color:#23221E}
.rec{display:grid;grid-template-columns:repeat(2, minmax(0, 1fr));gap:0}
.rec .col{padding:6px 10px 8px;border-right:1px solid #E6E5DF}
.rec .col:last-child{border-right:0}
.rec h4{margin:4px 0 4px;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.12em;text-transform:uppercase;color:#767368;font-weight:600;border-bottom:1px solid #E6E5DF;padding-bottom:3px}
.kv{display:grid;grid-template-columns:96px 1fr;gap:2px 8px;font-size:10.5px;margin:0}
.kv dt{color:#767368}
.kv dd{margin:0;color:#23221E}
.kv dd.mono{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:10px;font-variant-numeric:tabular-nums}
.rec-actions{display:flex;gap:6px;padding:6px 10px;border-top:1px solid #E6E5DF;background:#FAFAF8}
.rec-actions span{padding:2px 9px;font-size:10px;border:1px solid #C7C6BD;background:#FFFFFF;color:#23221E}
.rec-actions span.primary{color:#FFFFFF;background:#C8102E;border:1px solid #C8102E;font-weight:600}
.steps{display:flex;gap:0;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.06em;text-transform:uppercase;border-bottom:1px solid #E6E5DF}
.steps span{padding:3px 8px;border-right:1px solid #E6E5DF;color:#6B6A64}
.steps span.done{color:#767368}
.steps span.now{color:#C8102E;font-weight:700;box-shadow:inset 0 -2px 0 #C8102E}
.rep{padding:6px 10px}
.rep .row{display:grid;grid-template-columns:150px 1fr;gap:10px;padding:4px 0;border-bottom:1px solid #E6E5DF;font-size:10.5px}
.rep .row:last-child{border-bottom:0}
.rep .name{color:#23221E;font-weight:600}
.rep .name small{display:block;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.08em;text-transform:uppercase;color:#6B6A64;font-weight:400}
.rep .hl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#3C3A34;font-variant-numeric:tabular-nums}
/* title-bar option closeups */
.opt{width:600px;padding:16px;background:#D4D0C6}
.opt .cap{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.12em;text-transform:uppercase;color:#767368;margin:0 0 8px}
.opt .win-frame{margin-bottom:14px}
.opt .win-frame:last-child{margin-bottom:0}
/* Option B: ink strip */
.optB .front .w-title{background:#3C3A34;color:#fff;border-top:0;height:28px;border-bottom:1px solid #23221E}
.optB .front .w-title .name{color:#fff}
.optB .front .w-title .app{color:#fff}
.optB .front .w-title .app::after{color:rgba(255,255,255,0.35)}
.optB .front .w-title .ctl span{color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,0.6)}
.optB .front .w-title .new{color:#fff;border-color:rgba(255,255,255,0.7)}
/* Option C: ruled */
.optC .w-title{background:#FFFFFF;border-bottom:2px solid #23221E;height:28px}
.optC .front .w-title{background:#FFFFFF;border-top:3px solid #C8102E;height:31px;border-bottom:2px solid #23221E}
.optC .win-frame{border-color:#23221E}
/* ---- MMD PDF: the parts the shell system has no component for yet ------
Named for adoption into the design system, not invented per screen.
Every colour below is a red-plate value; nothing new is introduced. */
.pdf{width:800px;height:600px;display:flex;flex-direction:column;background:#FFFFFF;border:1px solid #767368;box-shadow:0 6px 16px rgba(35,34,30,0.26);overflow:hidden}
/* tool strip */
.pdf-tools{display:flex;align-items:stretch;background:#F1F1EC;border-bottom:1px solid #D7D6CE}
.pdf-t{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;width:44px;color:#23221E;flex:none}
.pdf-t .lb{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:7.5px;letter-spacing:0.02em;text-transform:uppercase;line-height:1;white-space:nowrap}
.pdf-t.on{background:#C8102E;color:#FFFFFF}
.pdf-t.dim{color:#A9A69C}
.pdf-rule{width:1px;background:#D7D6CE;margin:6px 3px;flex:none}
.pdf-end{margin-left:auto;display:flex;align-items:center;gap:5px;padding:0 6px;flex:none}
.pdf-zoom{display:flex;align-items:center;border:1px solid #C7C6BD;background:#FFFFFF}
.pdf-zoom b{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;font-weight:500;color:#23221E;padding:0 7px;line-height:19px}
.pdf-zoom i{width:19px;line-height:19px;text-align:center;font-style:normal;font-size:11px;color:#23221E;border-left:1px solid #C7C6BD}
.pdf-over{width:26px;display:flex;align-items:center;justify-content:center;color:#23221E;border-left:1px solid #D7D6CE;flex:none}
/* icon-only strip (direction B) */
.pdf-tools--icons .pdf-t{width:28px}
.pdf-tools--icons .pdf-t .lb{display:none}
/* tab strip (direction C) */
.pdf-tabs{display:flex;align-items:stretch;background:#E4E3DC;border-bottom:1px solid #D7D6CE;padding:0 4px}
.pdf-tab{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;letter-spacing:0.1em;text-transform:uppercase;color:#767368;padding:0 11px;line-height:21px}
.pdf-tab.on{background:#FFFFFF;color:#23221E;font-weight:600;border-top:2px solid #C8102E;line-height:19px}
/* context bar — only present while a tool is armed */
.pdf-ctx{display:flex;align-items:center;gap:9px;height:26px;padding:0 9px;background:#FAFAF8;border-bottom:1px solid #E6E5DF;font-size:10px;color:#3C3A34}
.pdf-ctx .lbl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.pdf-sw{display:flex;gap:3px}
.pdf-sw i{width:12px;height:12px;display:block;border:1px solid #C7C6BD}
.pdf-sw i.on{outline:1px solid #23221E;outline-offset:1px}
.pdf-pick{border:1px solid #C7C6BD;background:#FFFFFF;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#23221E;padding:1px 6px}
/* work area */
.pdf-work{flex:1;display:flex;min-height:0}
.pdf-strip{width:26px;flex:none;background:#E4E3DC;border-right:1px solid #D7D6CE;display:flex;flex-direction:column;align-items:center;gap:7px;padding-top:7px}
.pdf-strip .pn{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;color:#23221E;line-height:1.25;text-align:center}
.pdf-rail{width:88px;flex:none;background:#E4E3DC;border-right:1px solid #D7D6CE;overflow:hidden}
.pdf-rail-h{display:flex;gap:7px;padding:5px 7px 3px;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.pdf-rail-h .on{color:#23221E;font-weight:700}
.pdf-pg{margin:0 7px 5px;background:#FFFFFF;border:1px solid #C7C6BD}
.pdf-pg.here{box-shadow:inset 3px 0 0 #C8102E}
.pdf-pg .mini{height:64px;padding:5px 6px;overflow:hidden}
.pdf-pg .mini i{display:block;background:#C9C7C0;height:2px;margin-bottom:3px}
.pdf-pg .mini i.t{background:#23221E;height:3px;width:74%;margin-bottom:5px}
.pdf-pg .mini i.s{width:52%}
.pdf-pg .n{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8px;text-align:center;color:#3C3A34;line-height:14px;border-top:1px solid #E6E5DF}
.pdf-canvas{flex:1;background:#F3F3F0;display:flex;justify-content:center;overflow:hidden;padding:9px 0 0}
.pdf-page{width:100%;max-width:560px;background:#FFFFFF;border:1px solid #C7C6BD;padding:28px 34px}
/* status */
.pdf-status{display:flex;align-items:center;gap:12px;height:20px;padding:0 8px;background:#F1F1EC;border-top:1px solid #D7D6CE;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;color:#3C3A34;flex:none}
.pdf-status .sep{width:1px;height:11px;background:#C7C6BD}
.pdf-status .r{margin-left:auto;color:#6B6A64}
.pdf-status .warn{color:#C8102E}
/* document body */
.pdf-h{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:14px;color:#23221E;margin:0 0 13px}
.pdf-p{font-size:10.5px;color:#3C3A34;line-height:1.9;margin:0}
.pdf-live{display:inline-block;padding:0 4px;border:1px solid #C8102E;background:#FBEEF0;color:#23221E}
/* dialog */
.pdf-behind{position:absolute;inset:0}
.pdf-behind::after{content:"";position:absolute;inset:0;background:rgba(35,34,30,0.28)}
.pdf-over-scrim{position:relative;width:800px;height:600px;display:flex;align-items:center;justify-content:center;overflow:hidden}
.pdf-over-scrim .pdf-dlg{position:relative;z-index:2}
.pdf-dlg{width:404px;background:#FFFFFF;border:1px solid #767368;box-shadow:0 6px 16px rgba(35,34,30,0.26)}
.pdf-dlg-t{display:flex;align-items:center;height:26px;padding:0 10px;background:#FFFFFF;color:#23221E;border-bottom:2px solid #23221E;font-family:Fraunces,Georgia,serif;font-weight:700;font-size:11.5px}
.pdf-dlg-b{padding:13px 15px;display:flex;flex-direction:column;gap:10px;font-size:10.5px;color:#3C3A34}
.pdf-dlg-a{display:flex;justify-content:flex-end;gap:6px;padding:0 15px 13px}
.pdf-kv{display:grid;grid-template-columns:82px 1fr;gap:4px 10px;align-items:baseline}
.pdf-kv .k{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.09em;text-transform:uppercase;color:#767368}
.pdf-in{border:1px solid #C7C6BD;background:#FFFFFF;padding:3px 7px;font-size:10.5px;color:#23221E;display:flex;align-items:center}
.pdf-in .cv{margin-left:auto;font-size:8px;color:#767368}
/* direction board */
.board{width:800px;background:#F3F3F0;padding:11px;display:flex;flex-direction:column;gap:11px}
.board h3{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:12.5px;color:#23221E;margin:0}
.board .why{font-size:10px;color:#3C3A34;margin:0}
.board .cost{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.06em;text-transform:uppercase;color:#767368;margin:0}
.board .card{background:#FFFFFF;border:1px solid #C7C6BD;padding:9px 10px;display:flex;flex-direction:column;gap:6px}
.board .strip{border:1px solid #D7D6CE}
</style>
</helmet>
<div class="board">
<div class="card">
<h3>A &mdash; one row, named tools</h3>
<div class="strip"><div class="pdf-tools" style="height:40px"><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M2 6h6l2 2h8v9H2z"/></svg><span class="lb">Open</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 3h11l3 3v11H3z"/><path d="M6 3v5h7V3"/><path d="M6 17v-5h8v5"/></svg><span class="lb">Save</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 8V3h8v5"/><path d="M3 8h14v6h-3v4H6v-4H3z"/></svg><span class="lb">Print</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 5V3h4"/><path d="M17 5V3h-4"/><path d="M3 15v2h4"/><path d="M17 15v2h-4"/><path d="M2 10h16"/></svg><span class="lb">Scan</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 6V3h3"/><path d="M17 6V3h-3"/><path d="M3 14v3h3"/><path d="M17 14v3h-3"/><path d="M6 9h8"/><path d="M6 12h5"/></svg><span class="lb">OCR</span></div><span class="pdf-rule"></span><div class="pdf-t on"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#FFFFFF" stroke-width="1.35" stroke-linecap="square"><path d="M5 3l11 8-5 1 3 5-2 1-3-5-4 3z"/></svg><span class="lb">Select</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 5h12"/><path d="M10 5v11"/></svg><span class="lb">Text</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 15l3-9h2l3 9"/><path d="M6 12h5"/><path d="M14 15h3"/></svg><span class="lb">Mark</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 17l3-1 9-9-2-2-9 9z"/></svg><span class="lb">Draw</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 8h8v8H3z"/><path d="M11 4h6v6h-6z"/></svg><span class="lb">Shape</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 14c3-6 5 3 7-2s4 2 7-3"/><path d="M3 17h14"/></svg><span class="lb">Sign</span></div><span class="pdf-rule"></span><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 3h8v14H4z"/><path d="M12 6h4v11H8"/></svg><span class="lb">Pages</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M13 13l4 4"/><path d="M4 9a5 5 0 1010 0 5 5 0 10-10 0"/></svg><span class="lb">Search</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M7 6L3 10l4 4"/><path d="M3 10h9a4 4 0 010 8"/></svg><span class="lb">Undo</span></div><div class="pdf-end"><span class="pdf-zoom"><b>FIT WIDTH</b><i>&minus;</i><i>+</i></span></div><div class="pdf-over"><svg width="14" height="14" viewBox="0 0 14 14" fill="#23221E"><circle cx="3" cy="7" r="1.2"/><circle cx="7" cy="7" r="1.2"/><circle cx="11" cy="7" r="1.2"/></svg></div></div></div>
<p class="why">Fourteen tools carry their name. Everything else &mdash; stamp, image, crop, merge, flatten, redo &mdash; lives behind the three dots on the right.</p>
<p class="cost">40px of chrome &middot; 512px left for the page &middot; 16 of 30 tools hidden</p>
</div>
<div class="card">
<h3>B &mdash; icons only, nothing hidden</h3>
<div class="strip"><div class="pdf-tools pdf-tools--icons" style="height:30px"><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M2 6h6l2 2h8v9H2z"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 3h11l3 3v11H3z"/><path d="M6 3v5h7V3"/><path d="M6 17v-5h8v5"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 8V3h8v5"/><path d="M3 8h14v6h-3v4H6v-4H3z"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 5V3h4"/><path d="M17 5V3h-4"/><path d="M3 15v2h4"/><path d="M17 15v2h-4"/><path d="M2 10h16"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 6V3h3"/><path d="M17 6V3h-3"/><path d="M3 14v3h3"/><path d="M17 14v3h-3"/><path d="M6 9h8"/><path d="M6 12h5"/></svg></div><div class="pdf-t on"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#FFFFFF" stroke-width="1.35" stroke-linecap="square"><path d="M5 3l11 8-5 1 3 5-2 1-3-5-4 3z"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 5h12"/><path d="M10 5v11"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 15l3-9h2l3 9"/><path d="M6 12h5"/><path d="M14 15h3"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 17l3-1 9-9-2-2-9 9z"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 8h8v8H3z"/><path d="M11 4h6v6h-6z"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 14c3-6 5 3 7-2s4 2 7-3"/><path d="M3 17h14"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 16h8"/><path d="M7 13h6l-1-5a2 2 0 10-4 0z"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 4h14v12H3z"/><path d="M3 13l4-4 3 3 3-3 4 4"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 2v12h12"/><path d="M2 6h12v12"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 5h6v4H3z"/><path d="M11 11h6v4h-6z"/><path d="M6 9v3h5"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 3h8v7H6z"/><path d="M3 13h14"/><path d="M3 16h14"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 3h8v14H4z"/><path d="M12 6h4v11H8"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M13 13l4 4"/><path d="M4 9a5 5 0 1010 0 5 5 0 10-10 0"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M7 6L3 10l4 4"/><path d="M3 10h9a4 4 0 010 8"/></svg></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M13 6l4 4-4 4"/><path d="M17 10H8a4 4 0 000 8"/></svg></div><div class="pdf-end"><span class="pdf-zoom"><b>FIT WIDTH</b><i>&minus;</i><i>+</i></span></div></div></div>
<p class="why">All thirty fit, name on hover. Fastest once someone knows the icons; a plant clerk opening it for the first time has to guess.</p>
<p class="cost">30px of chrome &middot; 522px left for the page &middot; nothing hidden</p>
</div>
<div class="card">
<h3>C &mdash; three tabs, named tools, nothing hidden</h3>
<div class="strip"><div class="pdf-tabs"><span class="pdf-tab">Document</span><span class="pdf-tab on">Edit</span><span class="pdf-tab">Pages</span></div><div class="pdf-tools" style="height:34px"><div class="pdf-t on"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#FFFFFF" stroke-width="1.35" stroke-linecap="square"><path d="M5 3l11 8-5 1 3 5-2 1-3-5-4 3z"/></svg><span class="lb">Select</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 5h12"/><path d="M10 5v11"/></svg><span class="lb">Text</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 15l3-9h2l3 9"/><path d="M6 12h5"/><path d="M14 15h3"/></svg><span class="lb">Mark</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 17l3-1 9-9-2-2-9 9z"/></svg><span class="lb">Draw</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 8h8v8H3z"/><path d="M11 4h6v6h-6z"/></svg><span class="lb">Shape</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 14c3-6 5 3 7-2s4 2 7-3"/><path d="M3 17h14"/></svg><span class="lb">Sign</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 16h8"/><path d="M7 13h6l-1-5a2 2 0 10-4 0z"/></svg><span class="lb">Stamp</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 4h14v12H3z"/><path d="M3 13l4-4 3 3 3-3 4 4"/></svg><span class="lb">Image</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 2v12h12"/><path d="M2 6h12v12"/></svg><span class="lb">Crop</span></div><div class="pdf-end"><span class="pdf-zoom"><b>FIT WIDTH</b><i>&minus;</i><i>+</i></span></div></div></div>
<p class="why">Document, Edit, Pages. Every tool keeps its name and every tool is reachable, at the price of one click to change tab and a second bar of chrome.</p>
<p class="cost">56px of chrome &middot; 496px left for the page &middot; nothing hidden, one click deeper</p>
</div>
</div></x-dc>
</body>
</html>
File diff suppressed because one or more lines are too long
+205
View File
@@ -0,0 +1,205 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&family=JetBrains+Mono:wght@400;500;600&display=swap">
<style>
body{margin:0;background:#F3F3F0;font-family:"PP Neue Machina","Neue Machina",system-ui,-apple-system,"Segoe UI",sans-serif;color:#3C3A34;-webkit-font-smoothing:antialiased}
a{color:#C8102E} a:hover{color:#8E0B20}
*{box-sizing:border-box}
.root{padding:16px;background:#F3F3F0}
.shell{width:1180px;display:flex;flex-direction:column;font-size:11.5px;background:#FFFFFF;border:1px solid #C7C6BD}
.s-title{display:flex;align-items:center;gap:10px;padding:0 10px;height:30px;background:#C8102E;color:#fff;font-family:Fraunces,Georgia,serif;font-weight:700;font-size:12.5px}
.s-title .mmd-logo{height:19px;width:auto;display:block;flex:none;fill:#fff}
.spring{flex:1}
.s-who{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.07em;text-transform:uppercase;color:rgba(255,255,255,0.85)}
.s-signout{font-size:10px;padding:1px 0;color:#fff;text-decoration:underline;text-underline-offset:2px}
.s-bar{display:flex;align-items:stretch;gap:2px;padding:0 5px;background:#F7F7F3;border-bottom:1px solid #D7D6CE}
.s-item{display:flex;align-items:center;gap:6px;padding:6px 10px;font-size:11px;white-space:nowrap;border:1px solid transparent;color:#3C3A34}
.s-item .cv{font-size:8px;opacity:0.5}
.s-item .n{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;padding:0 4px;border:1px solid #23221E;color:#23221E;background:#FFFFFF;line-height:13px}
.s-item.on{background:#FFFFFF;border-color:#D7D6CE;border-top:2px solid #C8102E;border-bottom-color:#FFFFFF;margin-bottom:-1px;font-weight:700;color:#23221E}
.s-item.on .n{border-color:#23221E;color:#23221E}
.s-tools{margin-left:auto;display:flex;align-items:center;gap:6px;padding-right:4px}
.s-search{width:168px;padding:2px 7px;font-size:10.5px;background:#FFFFFF;border:1px solid #C7C6BD;color:#23221E}
.s-btn{padding:2px 9px;font-size:10.5px;background:#FFFFFF;border:1px solid #C7C6BD;color:#23221E}
.s-desk{position:relative;background:#D4D0C6;overflow:hidden}
.s-desk.tiled{display:grid;grid-template-columns:1.35fr 1fr;grid-template-rows:auto auto;gap:10px;padding:10px;align-items:start}
.s-desk.stacked{height:492px}
.s-desk.oneup{padding:10px}
.s-task{display:flex;align-items:center;gap:10px;padding:4px 8px;font-size:10.5px;background:#F1F1EC;border-top:1px solid #D7D6CE}
.s-task .lbl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.s-group{display:inline-flex;align-items:stretch;border:1px solid #D7D6CE;background:#FFFFFF}
.s-group .app{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#767368;padding:2px 7px;border-right:1px solid #D7D6CE;display:flex;align-items:center;background:#F7F7F3}
.s-group .win{padding:2px 8px;font-size:10px;color:#23221E;border-right:1px solid #D7D6CE;display:flex;align-items:center;gap:5px;background:#F1F1EC}
.s-group .win:last-child{border-right:0}
.s-group .win.on{box-shadow:inset 3px 0 0 #C8102E;font-weight:700;background:#FFFFFF}
.s-group .win.min{color:#3C3A34;background:#FFFFFF;outline:1px dashed #6B6A64;outline-offset:-3px}
.s-task .tile{font-size:10px;padding:1px 8px;border:1px solid #C7C6BD;background:#FFFFFF;color:#3C3A34}
/* windows — title bar made visible: darker plate, ink name, clear border; front = red top edge + shadow */
.win-frame{background:#FFFFFF;border:1px solid #B9B8AE;display:flex;flex-direction:column;min-width:0;box-shadow:0 1px 2px rgba(35,34,30,0.12)}
.win-frame.front{border-color:#767368;box-shadow:0 6px 16px rgba(35,34,30,0.26)}
.stacked .win-frame{position:absolute}
.w-title{display:flex;align-items:center;gap:8px;height:28px;padding:0 6px 0 8px;background:#E4E3DC;border-bottom:1px solid #C9C6BC;font-size:11px;color:#3C3A34}
.front .w-title{background:#FFFFFF;color:#23221E;border-top:3px solid #C8102E;height:31px}
.w-title .app{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#23221E;font-weight:700}
.w-title .app::after{content:"/";margin-left:8px;color:#6B6A64}
.w-title .name{font-family:Fraunces,Georgia,serif;font-weight:600;font-size:12px;color:#3C3A34}
.front .w-title .name{color:#23221E;font-weight:700}
.w-title .new{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.12em;text-transform:uppercase;color:#23221E;background:#E4E3DC;padding:0 6px;line-height:15px}
.w-title .ctl{display:flex;gap:8px}
.w-title .ctl span{width:24px;height:24px;display:flex;align-items:center;justify-content:center;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:12px;color:#23221E;background:transparent;border:0}
.w-body{padding:0;overflow:hidden}
.w-toolbar{display:flex;align-items:center;gap:8px;padding:5px 8px;background:#FAFAF8;border-bottom:1px solid #E6E5DF}
.w-h1{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:13px;letter-spacing:-0.01em;margin:0;color:#23221E}
.w-count{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#6B6A64}
.w-count b{color:#C8102E;font-weight:600}
.w-filters{margin-left:auto;display:flex;gap:4px}
.w-chip{padding:1px 7px;font-size:9.5px;font-family:"JetBrains Mono",ui-monospace,monospace;border:1px solid #D7D6CE;background:#FFFFFF;color:#3C3A34}
.w-chip.on{border-color:#767368;color:#23221E;font-weight:600}
.w-cta{padding:2px 9px;font-size:10px;background:#C8102E;color:#FFFFFF;border:1px solid #C8102E;font-weight:600}
table.w-tbl{width:100%;border-collapse:collapse;font-size:10.5px;background:#FFFFFF}
.w-tbl th{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;text-align:left;padding:4px 8px;white-space:nowrap;background:#F1F1EC;color:#23221E;border-bottom:1px solid #D7D6CE;border-right:1px solid #E6E5DF}
.w-tbl td{padding:4px 8px;border-bottom:1px solid #E6E5DF;border-right:1px solid #E6E5DF;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}
.w-tbl td:last-child,.w-tbl th:last-child{border-right:0}
.w-tbl tr:nth-child(even) td{background:#FAFAF8}
.w-tbl td.num{font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums;text-align:right}
.w-tbl th.num{text-align:right}
.w-tbl td.ref{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.03em}
.w-tbl tr.sel td{background:#F7F7F3;box-shadow:inset 3px 0 0 #C8102E}
.w-state{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.07em;text-transform:uppercase;padding:1px 5px;background:#F1F1EC;color:#23221E}
.rec{display:grid;grid-template-columns:repeat(2, minmax(0, 1fr));gap:0}
.rec .col{padding:6px 10px 8px;border-right:1px solid #E6E5DF}
.rec .col:last-child{border-right:0}
.rec h4{margin:4px 0 4px;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.12em;text-transform:uppercase;color:#767368;font-weight:600;border-bottom:1px solid #E6E5DF;padding-bottom:3px}
.kv{display:grid;grid-template-columns:96px 1fr;gap:2px 8px;font-size:10.5px;margin:0}
.kv dt{color:#767368}
.kv dd{margin:0;color:#23221E}
.kv dd.mono{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:10px;font-variant-numeric:tabular-nums}
.rec-actions{display:flex;gap:6px;padding:6px 10px;border-top:1px solid #E6E5DF;background:#FAFAF8}
.rec-actions span{padding:2px 9px;font-size:10px;border:1px solid #C7C6BD;background:#FFFFFF;color:#23221E}
.rec-actions span.primary{color:#FFFFFF;background:#C8102E;border:1px solid #C8102E;font-weight:600}
.steps{display:flex;gap:0;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.06em;text-transform:uppercase;border-bottom:1px solid #E6E5DF}
.steps span{padding:3px 8px;border-right:1px solid #E6E5DF;color:#6B6A64}
.steps span.done{color:#767368}
.steps span.now{color:#C8102E;font-weight:700;box-shadow:inset 0 -2px 0 #C8102E}
.rep{padding:6px 10px}
.rep .row{display:grid;grid-template-columns:150px 1fr;gap:10px;padding:4px 0;border-bottom:1px solid #E6E5DF;font-size:10.5px}
.rep .row:last-child{border-bottom:0}
.rep .name{color:#23221E;font-weight:600}
.rep .name small{display:block;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.08em;text-transform:uppercase;color:#6B6A64;font-weight:400}
.rep .hl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#3C3A34;font-variant-numeric:tabular-nums}
/* title-bar option closeups */
.opt{width:600px;padding:16px;background:#D4D0C6}
.opt .cap{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.12em;text-transform:uppercase;color:#767368;margin:0 0 8px}
.opt .win-frame{margin-bottom:14px}
.opt .win-frame:last-child{margin-bottom:0}
/* Option B: ink strip */
.optB .front .w-title{background:#3C3A34;color:#fff;border-top:0;height:28px;border-bottom:1px solid #23221E}
.optB .front .w-title .name{color:#fff}
.optB .front .w-title .app{color:#fff}
.optB .front .w-title .app::after{color:rgba(255,255,255,0.35)}
.optB .front .w-title .ctl span{color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,0.6)}
.optB .front .w-title .new{color:#fff;border-color:rgba(255,255,255,0.7)}
/* Option C: ruled */
.optC .w-title{background:#FFFFFF;border-bottom:2px solid #23221E;height:28px}
.optC .front .w-title{background:#FFFFFF;border-top:3px solid #C8102E;height:31px;border-bottom:2px solid #23221E}
.optC .win-frame{border-color:#23221E}
/* ---- MMD PDF: the parts the shell system has no component for yet ------
Named for adoption into the design system, not invented per screen.
Every colour below is a red-plate value; nothing new is introduced. */
.pdf{width:800px;height:600px;display:flex;flex-direction:column;background:#FFFFFF;border:1px solid #767368;box-shadow:0 6px 16px rgba(35,34,30,0.26);overflow:hidden}
/* tool strip */
.pdf-tools{display:flex;align-items:stretch;background:#F1F1EC;border-bottom:1px solid #D7D6CE}
.pdf-t{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;width:44px;color:#23221E;flex:none}
.pdf-t .lb{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:7.5px;letter-spacing:0.02em;text-transform:uppercase;line-height:1;white-space:nowrap}
.pdf-t.on{background:#C8102E;color:#FFFFFF}
.pdf-t.dim{color:#A9A69C}
.pdf-rule{width:1px;background:#D7D6CE;margin:6px 3px;flex:none}
.pdf-end{margin-left:auto;display:flex;align-items:center;gap:5px;padding:0 6px;flex:none}
.pdf-zoom{display:flex;align-items:center;border:1px solid #C7C6BD;background:#FFFFFF}
.pdf-zoom b{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;font-weight:500;color:#23221E;padding:0 7px;line-height:19px}
.pdf-zoom i{width:19px;line-height:19px;text-align:center;font-style:normal;font-size:11px;color:#23221E;border-left:1px solid #C7C6BD}
.pdf-over{width:26px;display:flex;align-items:center;justify-content:center;color:#23221E;border-left:1px solid #D7D6CE;flex:none}
/* icon-only strip (direction B) */
.pdf-tools--icons .pdf-t{width:28px}
.pdf-tools--icons .pdf-t .lb{display:none}
/* tab strip (direction C) */
.pdf-tabs{display:flex;align-items:stretch;background:#E4E3DC;border-bottom:1px solid #D7D6CE;padding:0 4px}
.pdf-tab{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;letter-spacing:0.1em;text-transform:uppercase;color:#767368;padding:0 11px;line-height:21px}
.pdf-tab.on{background:#FFFFFF;color:#23221E;font-weight:600;border-top:2px solid #C8102E;line-height:19px}
/* context bar — only present while a tool is armed */
.pdf-ctx{display:flex;align-items:center;gap:9px;height:26px;padding:0 9px;background:#FAFAF8;border-bottom:1px solid #E6E5DF;font-size:10px;color:#3C3A34}
.pdf-ctx .lbl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.pdf-sw{display:flex;gap:3px}
.pdf-sw i{width:12px;height:12px;display:block;border:1px solid #C7C6BD}
.pdf-sw i.on{outline:1px solid #23221E;outline-offset:1px}
.pdf-pick{border:1px solid #C7C6BD;background:#FFFFFF;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#23221E;padding:1px 6px}
/* work area */
.pdf-work{flex:1;display:flex;min-height:0}
.pdf-strip{width:26px;flex:none;background:#E4E3DC;border-right:1px solid #D7D6CE;display:flex;flex-direction:column;align-items:center;gap:7px;padding-top:7px}
.pdf-strip .pn{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;color:#23221E;line-height:1.25;text-align:center}
.pdf-rail{width:88px;flex:none;background:#E4E3DC;border-right:1px solid #D7D6CE;overflow:hidden}
.pdf-rail-h{display:flex;gap:7px;padding:5px 7px 3px;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.pdf-rail-h .on{color:#23221E;font-weight:700}
.pdf-pg{margin:0 7px 5px;background:#FFFFFF;border:1px solid #C7C6BD}
.pdf-pg.here{box-shadow:inset 3px 0 0 #C8102E}
.pdf-pg .mini{height:64px;padding:5px 6px;overflow:hidden}
.pdf-pg .mini i{display:block;background:#C9C7C0;height:2px;margin-bottom:3px}
.pdf-pg .mini i.t{background:#23221E;height:3px;width:74%;margin-bottom:5px}
.pdf-pg .mini i.s{width:52%}
.pdf-pg .n{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8px;text-align:center;color:#3C3A34;line-height:14px;border-top:1px solid #E6E5DF}
.pdf-canvas{flex:1;background:#F3F3F0;display:flex;justify-content:center;overflow:hidden;padding:9px 0 0}
.pdf-page{width:100%;max-width:560px;background:#FFFFFF;border:1px solid #C7C6BD;padding:28px 34px}
/* status */
.pdf-status{display:flex;align-items:center;gap:12px;height:20px;padding:0 8px;background:#F1F1EC;border-top:1px solid #D7D6CE;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;color:#3C3A34;flex:none}
.pdf-status .sep{width:1px;height:11px;background:#C7C6BD}
.pdf-status .r{margin-left:auto;color:#6B6A64}
.pdf-status .warn{color:#C8102E}
/* document body */
.pdf-h{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:14px;color:#23221E;margin:0 0 13px}
.pdf-p{font-size:10.5px;color:#3C3A34;line-height:1.9;margin:0}
.pdf-live{display:inline-block;padding:0 4px;border:1px solid #C8102E;background:#FBEEF0;color:#23221E}
/* dialog */
.pdf-behind{position:absolute;inset:0}
.pdf-behind::after{content:"";position:absolute;inset:0;background:rgba(35,34,30,0.28)}
.pdf-over-scrim{position:relative;width:800px;height:600px;display:flex;align-items:center;justify-content:center;overflow:hidden}
.pdf-over-scrim .pdf-dlg{position:relative;z-index:2}
.pdf-dlg{width:404px;background:#FFFFFF;border:1px solid #767368;box-shadow:0 6px 16px rgba(35,34,30,0.26)}
.pdf-dlg-t{display:flex;align-items:center;height:26px;padding:0 10px;background:#FFFFFF;color:#23221E;border-bottom:2px solid #23221E;font-family:Fraunces,Georgia,serif;font-weight:700;font-size:11.5px}
.pdf-dlg-b{padding:13px 15px;display:flex;flex-direction:column;gap:10px;font-size:10.5px;color:#3C3A34}
.pdf-dlg-a{display:flex;justify-content:flex-end;gap:6px;padding:0 15px 13px}
.pdf-kv{display:grid;grid-template-columns:82px 1fr;gap:4px 10px;align-items:baseline}
.pdf-kv .k{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.09em;text-transform:uppercase;color:#767368}
.pdf-in{border:1px solid #C7C6BD;background:#FFFFFF;padding:3px 7px;font-size:10.5px;color:#23221E;display:flex;align-items:center}
.pdf-in .cv{margin-left:auto;font-size:8px;color:#767368}
/* direction board */
.board{width:800px;background:#F3F3F0;padding:11px;display:flex;flex-direction:column;gap:11px}
.board h3{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:12.5px;color:#23221E;margin:0}
.board .why{font-size:10px;color:#3C3A34;margin:0}
.board .cost{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.06em;text-transform:uppercase;color:#767368;margin:0}
.board .card{background:#FFFFFF;border:1px solid #C7C6BD;padding:9px 10px;display:flex;flex-direction:column;gap:6px}
.board .strip{border:1px solid #D7D6CE}
</style>
</helmet>
<div class="pdf"><div class="w-title"><img class="mmd-logo" src="mmd-logo-red.svg" alt="MMD" style="height:13px"><span class="app">MMD PDF</span><span class="name">BON-2026-0847 delivery note.pdf</span><span class="spring"></span><span class="ctl"><span>&minus;</span><span>&#9723;</span><span>&times;</span></span></div><div class="pdf-tools" style="height:40px"><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M2 6h6l2 2h8v9H2z"/></svg><span class="lb">Open</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 3h11l3 3v11H3z"/><path d="M6 3v5h7V3"/><path d="M6 17v-5h8v5"/></svg><span class="lb">Save</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M6 8V3h8v5"/><path d="M3 8h14v6h-3v4H6v-4H3z"/></svg><span class="lb">Print</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 5V3h4"/><path d="M17 5V3h-4"/><path d="M3 15v2h4"/><path d="M17 15v2h-4"/><path d="M2 10h16"/></svg><span class="lb">Scan</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 6V3h3"/><path d="M17 6V3h-3"/><path d="M3 14v3h3"/><path d="M17 14v3h-3"/><path d="M6 9h8"/><path d="M6 12h5"/></svg><span class="lb">OCR</span></div><span class="pdf-rule"></span><div class="pdf-t on"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#FFFFFF" stroke-width="1.35" stroke-linecap="square"><path d="M5 3l11 8-5 1 3 5-2 1-3-5-4 3z"/></svg><span class="lb">Select</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 5h12"/><path d="M10 5v11"/></svg><span class="lb">Text</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 15l3-9h2l3 9"/><path d="M6 12h5"/><path d="M14 15h3"/></svg><span class="lb">Mark</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 17l3-1 9-9-2-2-9 9z"/></svg><span class="lb">Draw</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 8h8v8H3z"/><path d="M11 4h6v6h-6z"/></svg><span class="lb">Shape</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M3 14c3-6 5 3 7-2s4 2 7-3"/><path d="M3 17h14"/></svg><span class="lb">Sign</span></div><span class="pdf-rule"></span><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M4 3h8v14H4z"/><path d="M12 6h4v11H8"/></svg><span class="lb">Pages</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M13 13l4 4"/><path d="M4 9a5 5 0 1010 0 5 5 0 10-10 0"/></svg><span class="lb">Search</span></div><div class="pdf-t"><svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="#23221E" stroke-width="1.35" stroke-linecap="square"><path d="M7 6L3 10l4 4"/><path d="M3 10h9a4 4 0 010 8"/></svg><span class="lb">Undo</span></div><div class="pdf-end"><span class="pdf-zoom"><b>FIT WIDTH</b><i>&minus;</i><i>+</i></span></div><div class="pdf-over"><svg width="14" height="14" viewBox="0 0 14 14" fill="#23221E"><circle cx="3" cy="7" r="1.2"/><circle cx="7" cy="7" r="1.2"/><circle cx="11" cy="7" r="1.2"/></svg></div></div><div class="pdf-work"><div class="pdf-strip"><svg width="11" height="11" viewBox="0 0 12 12" fill="none" stroke="#23221E" stroke-width="1.3"><path d="M4 2l4 4-4 4"/></svg><span class="pn">1</span></div><div class="pdf-canvas"><div class="pdf-page"><h1 class="pdf-h">MMD STEEL GROUP &mdash; DELIVERY NOTE</h1><p class="pdf-p">Supplier: Fabrimetal SARL<br>Reference: BON-2026-0847<br>Quantity delivered: 12 tonnes<br>Vehicle: DK-4471-AB &middot; Driver: M. Sow<br><br>Received by: ______________________<br><br>Dakar plant &middot; corridor freight &middot; weighbridge ticket WB-4471</p></div></div></div><div class="pdf-status"><span class="">Ready</span><span class="r">1 OF 1 &middot; FIT WIDTH &middot; 100%</span></div></div></x-dc>
</body>
</html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+413
View File
@@ -0,0 +1,413 @@
#!/usr/bin/env python3
"""MMD PDF — design pages for the desktop editor at 800x600.
Stylesheet: the red-plate MMD shell design system, lifted verbatim from its
own source (portal-redesign session, canvas/build.mjs). Not retyped.
The screen budget at 800x600 drives every decision here:
600 - 28 title bar - 20 status bar = 552px for toolbar + document.
800 - page rail = document width.
A PDF editor carries about thirty tools. Thirty labelled tools need ~1400px.
Three directions resolve that differently; A/B/C are real alternatives, not
cosmetic variants of one answer.
"""
import json, os
OUT = os.path.dirname(os.path.abspath(__file__))
RP = open(os.path.join(OUT, "redplate.css")).read()
W, H = 800, 600
EXT = """
/* ---- MMD PDF: the parts the shell system has no component for yet ------
Named for adoption into the design system, not invented per screen.
Every colour below is a red-plate value; nothing new is introduced. */
.pdf{width:800px;height:600px;display:flex;flex-direction:column;background:#FFFFFF;border:1px solid #767368;box-shadow:0 6px 16px rgba(35,34,30,0.26);overflow:hidden}
/* tool strip */
.pdf-tools{display:flex;align-items:stretch;background:#F1F1EC;border-bottom:1px solid #D7D6CE}
.pdf-t{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;width:44px;color:#23221E;flex:none}
.pdf-t .lb{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.01em;text-transform:uppercase;line-height:1;white-space:nowrap}
.pdf-t.on{background:#C8102E;color:#FFFFFF}
.pdf-t.dim{color:#767368}
.pdf-rule{width:1px;background:#D7D6CE;margin:6px 3px;flex:none}
.pdf-end{margin-left:auto;display:flex;align-items:center;gap:5px;padding:0 6px;flex:none}
.pdf-zoom{display:flex;align-items:center;border:1px solid #C7C6BD;background:#FFFFFF}
.pdf-zoom b{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;font-weight:500;color:#23221E;padding:0 7px;line-height:19px}
.pdf-zoom i{width:19px;line-height:19px;text-align:center;font-style:normal;font-size:11px;color:#23221E;border-left:1px solid #C7C6BD}
.pdf-over{width:26px;display:flex;align-items:center;justify-content:center;color:#23221E;border-left:1px solid #D7D6CE;flex:none}
/* icon-only strip (direction B) */
.pdf-tools--icons .pdf-t{width:28px}
.pdf-tools--icons .pdf-t .lb{display:none}
/* tab strip (direction C) */
.pdf-tabs{display:flex;align-items:stretch;background:#E4E3DC;border-bottom:1px solid #D7D6CE;padding:0 4px}
.pdf-tab{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:10px;letter-spacing:0.1em;text-transform:uppercase;color:#767368;padding:0 11px;line-height:21px}
.pdf-tab.on{background:#FFFFFF;color:#23221E;font-weight:600;border-top:2px solid #C8102E;line-height:19px}
/* context bar — only present while a tool is armed */
.pdf-ctx{display:flex;align-items:center;gap:9px;height:28px;padding:0 9px;background:#FAFAF8;border-bottom:1px solid #E6E5DF;font-size:10px;color:#3C3A34}
.pdf-ctx .lbl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.pdf-sw{display:flex;gap:3px}
.pdf-sw i{width:12px;height:12px;display:block;border:1px solid #C7C6BD}
.pdf-sw i.on{outline:1px solid #23221E;outline-offset:1px}
.pdf-pick{border:1px solid #C7C6BD;background:#FFFFFF;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#23221E;padding:1px 6px}
/* work area */
.pdf-work{flex:1;display:flex;min-height:0}
.pdf-strip{width:26px;flex:none;background:#E4E3DC;border-right:1px solid #D7D6CE;display:flex;flex-direction:column;align-items:center;gap:7px;padding-top:7px}
.pdf-strip .pn{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#23221E;line-height:1.25;text-align:center}
.pdf-rail{width:88px;flex:none;background:#E4E3DC;border-right:1px solid #D7D6CE;overflow:hidden}
.pdf-rail-h{display:flex;gap:8px;padding:6px 7px 4px;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.pdf-rail-h .on{color:#23221E;font-weight:700}
.pdf-pg{margin:0 7px 5px;background:#FFFFFF;border:1px solid #C7C6BD}
.pdf-pg.here{box-shadow:inset 3px 0 0 #C8102E}
.pdf-pg .mini{height:64px;padding:5px 6px;overflow:hidden}
.pdf-pg .mini i{display:block;background:#C7C6BD;height:2px;margin-bottom:3px}
.pdf-pg .mini i.t{background:#23221E;height:3px;width:74%;margin-bottom:5px}
.pdf-pg .mini i.s{width:52%}
.pdf-pg .n{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;text-align:center;color:#3C3A34;line-height:16px;border-top:1px solid #E6E5DF}
.pdf-canvas{flex:1;background:#F3F3F0;display:flex;justify-content:center;overflow:hidden;padding:9px 0 0}
.pdf-page{width:100%;max-width:560px;background:#FFFFFF;border:1px solid #C7C6BD;padding:28px 34px}
/* status */
.pdf-status{display:flex;align-items:center;gap:12px;height:23px;padding:0 8px;background:#F1F1EC;border-top:1px solid #D7D6CE;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#3C3A34;flex:none}
.pdf-status .sep{width:1px;height:11px;background:#C7C6BD}
.pdf-status .r{margin-left:auto;color:#6B6A64}
.pdf-status .warn{color:#C8102E}
/* document body */
.pdf-h{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:14px;color:#23221E;margin:0 0 13px}
.pdf-p{font-size:10.5px;color:#3C3A34;line-height:1.9;margin:0}
.pdf-live{display:inline-block;padding:0 4px;border:1px solid #C8102E;background:#FBEEF0;color:#23221E}
/* dialog */
.pdf-behind{position:absolute;inset:0}
.pdf-behind::after{content:"";position:absolute;inset:0;background:rgba(35,34,30,0.28)}
.pdf-over-scrim{position:relative;width:800px;height:600px;display:flex;align-items:center;justify-content:center;overflow:hidden}
.pdf-over-scrim .pdf-dlg{position:relative;z-index:2}
.pdf-dlg{width:404px;background:#FFFFFF;border:1px solid #767368;box-shadow:0 6px 16px rgba(35,34,30,0.26)}
.pdf-dlg-t{display:flex;align-items:center;height:26px;padding:0 10px;background:#FFFFFF;color:#23221E;border-bottom:2px solid #23221E;font-family:Fraunces,Georgia,serif;font-weight:700;font-size:11.5px}
.pdf-dlg-b{padding:13px 15px;display:flex;flex-direction:column;gap:10px;font-size:10.5px;color:#3C3A34}
.pdf-dlg-a{display:flex;justify-content:flex-end;gap:6px;padding:0 15px 13px}
.pdf-kv{display:grid;grid-template-columns:82px 1fr;gap:4px 10px;align-items:baseline}
.pdf-kv .k{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.09em;text-transform:uppercase;color:#767368}
.pdf-in{border:1px solid #C7C6BD;background:#FFFFFF;padding:3px 7px;font-size:10.5px;color:#23221E;display:flex;align-items:center}
.pdf-in .cv{margin-left:auto;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;color:#767368}
/* direction board */
.board{width:800px;background:#F3F3F0;padding:11px;display:flex;flex-direction:column;gap:11px}
.board h3{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:12.5px;color:#23221E;margin:0}
.board .why{font-size:10px;color:#3C3A34;margin:0}
.board .cost{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.06em;text-transform:uppercase;color:#767368;margin:0}
.board .card{background:#FFFFFF;border:1px solid #C7C6BD;padding:9px 10px;display:flex;flex-direction:column;gap:6px}
.board .strip{border:1px solid #D7D6CE}
"""
# ── icons: one 20px grid, stroke only ────────────────────────────────────────
P = {
"Open": ['M2 6h6l2 2h8v9H2z'],
"Save": ['M3 3h11l3 3v11H3z', 'M6 3v5h7V3', 'M6 17v-5h8v5'],
"Print": ['M6 8V3h8v5', 'M3 8h14v6h-3v4H6v-4H3z'],
"Scan": ['M3 5V3h4', 'M17 5V3h-4', 'M3 15v2h4', 'M17 15v2h-4', 'M2 10h16'],
"OCR": ['M3 6V3h3', 'M17 6V3h-3', 'M3 14v3h3', 'M17 14v3h-3', 'M6 9h8', 'M6 12h5'],
"Select": ['M5 3l11 8-5 1 3 5-2 1-3-5-4 3z'],
"Text": ['M4 5h12', 'M10 5v11'],
"Mark": ['M4 15l3-9h2l3 9', 'M6 12h5', 'M14 15h3'],
"Draw": ['M3 17l3-1 9-9-2-2-9 9z'],
"Shape": ['M3 8h8v8H3z', 'M11 4h6v6h-6z'],
"Sign": ['M3 14c3-6 5 3 7-2s4 2 7-3', 'M3 17h14'],
"Stamp": ['M6 16h8', 'M7 13h6l-1-5a2 2 0 10-4 0z'],
"Image": ['M3 4h14v12H3z', 'M3 13l4-4 3 3 3-3 4 4'],
"Crop": ['M6 2v12h12', 'M2 6h12v12'],
"Pages": ['M4 3h8v14H4z', 'M12 6h4v11H8'],
"Search": ['M13 13l4 4', 'M4 9a5 5 0 1010 0 5 5 0 10-10 0'],
"Undo": ['M7 6L3 10l4 4', 'M3 10h9a4 4 0 010 8'],
"Redo": ['M13 6l4 4-4 4', 'M17 10H8a4 4 0 000 8'],
"Merge": ['M3 5h6v4H3z', 'M11 11h6v4h-6z', 'M6 9v3h5'],
"Flatten":['M6 3h8v7H6z', 'M3 13h14', 'M3 16h14'],
}
def ico(n, on=False, dim=False):
col = "#FFFFFF" if on else ("#767368" if dim else "#23221E")
d = "".join(f'<path d="{p}"/>' for p in P.get(n, ['M4 4h12v12H4z']))
return (f'<svg width="15" height="15" viewBox="0 0 20 20" fill="none" stroke="{col}" '
f'stroke-width="1.35" stroke-linecap="square">{d}</svg>')
def T(n, on=False, dim=False):
c = "pdf-t on" if on else ("pdf-t dim" if dim else "pdf-t")
return f'<div class="{c}">{ico(n, on, dim)}<span class="lb">{n}</span></div>'
ZOOM = ('<span class="pdf-zoom"><b>FIT WIDTH</b><i>&minus;</i><i>+</i></span>')
OVER = ('<div class="pdf-over"><svg width="14" height="14" viewBox="0 0 14 14" fill="#23221E">'
'<circle cx="3" cy="7" r="1.2"/><circle cx="7" cy="7" r="1.2"/><circle cx="11" cy="7" r="1.2"/></svg></div>')
def title(name="BON-2026-0847 delivery note.pdf", tag=""):
t = f'<span class="new">{tag}</span>' if tag else ''
return (f'<div class="w-title"><img class="mmd-logo" src="mmd-logo-red.svg" alt="MMD" '
f'style="height:13px"><span class="app">MMD PDF</span>'
f'<span class="name">{name}</span>{t}<span class="spring"></span>'
f'<span class="ctl"><span>&minus;</span><span>&#9723;</span><span>&times;</span></span></div>')
def strip_collapsed(n="1"):
return (f'<div class="pdf-strip"><svg width="11" height="11" viewBox="0 0 12 12" fill="none" '
f'stroke="#23221E" stroke-width="1.3"><path d="M4 2l4 4-4 4"/></svg>'
f'<span class="pn">{n}</span></div>')
def rail_open(pages=("1", "2", "3")):
pg = "".join(
f'<div class="pdf-pg{" here" if i == 0 else ""}"><div class="mini">'
f'<i class="t"></i><i></i><i></i><i class="s"></i><i></i></div>'
f'<div class="n">{p}</div></div>' for i, p in enumerate(pages))
return (f'<div class="pdf-rail"><div class="pdf-rail-h"><span class="on">Pages</span>'
f'<span>Marks</span></div>{pg}</div>')
DOC = ('<h1 class="pdf-h">MMD STEEL GROUP &mdash; DELIVERY NOTE</h1>'
'<p class="pdf-p">Supplier: Fabrimetal SARL<br>Reference: BON-2026-0847<br>'
'Quantity delivered: 12 tonnes<br>Vehicle: DK-4471-AB &middot; Driver: M. Sow<br><br>'
'Received by: ______________________<br><br>'
'Dakar plant &middot; corridor freight &middot; weighbridge ticket WB-4471</p>')
DOC_EDIT = ('<h1 class="pdf-h">MMD STEEL GROUP &mdash; DELIVERY NOTE</h1>'
'<p class="pdf-p">Supplier: Fabrimetal SARL<br>Reference: BON-2026-0847<br>'
'<span class="pdf-live">Quantity delivered: 19 tonnes</span><br>'
'Vehicle: DK-4471-AB &middot; Driver: M. Sow<br><br>'
'Received by: ______________________<br><br>'
'Dakar plant &middot; corridor freight &middot; weighbridge ticket WB-4471</p>')
def status(left, right, warn=False):
cls = "warn" if warn else ""
return (f'<div class="pdf-status"><span class="{cls}">{left}</span>'
f'<span class="r">{right}</span></div>')
HEAD = """<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&family=JetBrains+Mono:wght@400;500;600&display=swap">
<style>
%s
%s
</style>
</helmet>
""" % (RP, EXT)
TAIL = "</x-dc>\n</body>\n</html>\n"
def w(name, inner):
open(os.path.join(OUT, name), "w", encoding="utf-8").write(HEAD + inner + TAIL)
# ── Direction A: one labelled strip, fourteen tools, rest behind overflow ────
A_TOOLS = ["Open", "Save", "Print", "Scan", "OCR"]
A_EDIT = ["Select", "Text", "Mark", "Draw", "Shape", "Sign"]
A_DOC = ["Pages", "Search", "Undo"]
def strip_A(active="Select", h=40):
return (f'<div class="pdf-tools" style="height:{h}px">'
+ "".join(T(t) for t in A_TOOLS) + '<span class="pdf-rule"></span>'
+ "".join(T(t, t == active) for t in A_EDIT) + '<span class="pdf-rule"></span>'
+ "".join(T(t) for t in A_DOC)
+ f'<div class="pdf-end">{ZOOM}</div>{OVER}</div>')
w("Main.dc.html",
'<div class="pdf">' + title() + strip_A("Select") +
'<div class="pdf-work">' + strip_collapsed() +
'<div class="pdf-canvas"><div class="pdf-page">' + DOC + '</div></div></div>' +
status("Ready", "1 OF 1 &middot; FIT WIDTH &middot; 100%") + '</div>')
# ── Editing text, context bar present ───────────────────────────────────────
ctx = ('<div class="pdf-ctx"><span class="lbl">Colour</span>'
'<span class="pdf-sw"><i class="on" style="background:#23221E"></i>'
'<i style="background:#C8102E"></i><i style="background:#3C3A34"></i>'
'<i style="background:#767368"></i><i style="background:#FFFFFF"></i></span>'
'<span class="lbl">Size</span><span class="pdf-pick">11 pt</span>'
'<span class="pdf-pick">B</span><span class="pdf-pick">I</span>'
'<span class="spring"></span>'
'<span class="lbl">Enter keeps it &middot; Esc throws it away</span></div>')
w("EditText.dc.html",
'<div class="pdf">' + title(tag="Changed") + strip_A("Text") + ctx +
'<div class="pdf-work">' + strip_collapsed() +
'<div class="pdf-canvas"><div class="pdf-page">' + DOC_EDIT + '</div></div></div>' +
status("The old quantity is removed from the file when you save",
"1 OF 1 &middot; FIT WIDTH &middot; 100%", warn=True) + '</div>')
# ── Rail open, three pages ──────────────────────────────────────────────────
w("PageRail.dc.html",
'<div class="pdf">' + title("Weighbridge tickets week 34.pdf") + strip_A("Select") +
'<div class="pdf-work">' + rail_open() +
'<div class="pdf-canvas"><div class="pdf-page">' + DOC + '</div></div></div>' +
status("Ready", "1 OF 3 &middot; FIT WIDTH &middot; 100%") + '</div>')
# ── Nothing open ────────────────────────────────────────────────────────────
rows = "".join(
f'<tr><td class="ref"{" style=box-shadow:inset~3px~0~0~#C8102E".replace(chr(126),chr(32)) if i == 0 else ""}>{r}</td>'
f'<td>{d}</td><td class="num">{n}</td><td><span class="w-state">{s}</span></td></tr>'
for i, (r, d, n, s) in enumerate([
("BON-2026-0847", "Delivery note &mdash; Fabrimetal SARL", "1", "Changed"),
("INV-4471", "Supplier invoice &mdash; Fabrimetal SARL", "3", "Signed"),
("WB-4471", "Weighbridge ticket &mdash; Dakar plant", "1", "Scanned"),
("INSP-0912", "Mill inspection &mdash; Kigali", "8", "Read"),
("PO-AO-2231", "Refractory bricks &mdash; Vesuvius Angola", "2", "Read"),
("BON-2026-0839", "Delivery note &mdash; Continental Sahel", "1", "Signed"),
("INV-4402", "Freight invoice &mdash; corridor Dakar&ndash;Bamako", "2", "Read"),
("WB-4468", "Weighbridge ticket &mdash; Dakar plant", "1", "Scanned"),
("PO-SN-24099", "Diesel gensets &mdash; Groupe S&eacute;n&eacute;gal &Eacute;nergie", "4", "Read"),
("BON-2026-0831", "Delivery note &mdash; SMS Concast", "1", "Read"),
("INSP-0908", "Mill inspection &mdash; Dakar", "6", "Read"),
("WB-4455", "Weighbridge ticket &mdash; Dakar plant", "1", "Scanned"),
("INV-4377", "Supplier invoice &mdash; RHI Magnesita", "3", "Signed"),
("PO-RW-24107", "Rolling mill rollers &mdash; Danieli Service", "2", "Read"),
("BON-2026-0824", "Delivery note &mdash; Nexans Angola", "1", "Read"),
]))
w("Nothing.dc.html",
'<div class="pdf">' + title("No document open") +
f'<div class="pdf-tools" style="height:40px">'
+ "".join(T(t) for t in A_TOOLS) + '<span class="pdf-rule"></span>'
+ "".join(T(t, dim=True) for t in A_EDIT) + '<span class="pdf-rule"></span>'
+ "".join(T(t, dim=True) for t in A_DOC)
+ f'<div class="pdf-end">{ZOOM}</div>{OVER}</div>'
+ '<div class="pdf-work"><div class="pdf-canvas" style="padding:0"><div style="width:100%">'
'<div class="w-toolbar"><h2 class="w-h1">Recent</h2>'
'<span class="w-count">on this machine</span>'
'<span class="w-filters"><span class="w-chip">Open a file&hellip;</span>'
'<span class="w-cta">Scan a document</span></span></div>'
'<table class="w-tbl"><thead><tr><th>Reference</th><th>Document</th>'
'<th class="num">Pages</th><th>State</th></tr></thead><tbody>' + rows +
'</tbody></table></div></div></div>' +
status("Pick a document, or scan one", "NOTHING OPEN") + '</div>')
# ── Saving over the original ────────────────────────────────────────────────
def behind(doc=DOC, active="Select", st=("Ready", "1 OF 1 &middot; FIT WIDTH &middot; 100%")):
return ('<div class="pdf-behind"><div class="pdf" style="box-shadow:none;border:0">'
+ title() + strip_A(active)
+ '<div class="pdf-work">' + strip_collapsed()
+ '<div class="pdf-canvas"><div class="pdf-page">' + doc + '</div></div></div>'
+ status(*st) + '</div></div>')
w("Save.dc.html",
'<div class="pdf-over-scrim">' + behind(DOC_EDIT, "Text",
("The old quantity is removed from the file when you save",
"1 OF 1 &middot; FIT WIDTH &middot; 100%")) +
'<div class="pdf-dlg">'
'<div class="pdf-dlg-t">Save</div><div class="pdf-dlg-b">'
'<div>Write the change into <b>BON-2026-0847 delivery note.pdf</b>?</div>'
'<div class="pdf-kv">'
'<span class="k">Was</span><span>Quantity delivered: 12 tonnes</span>'
'<span class="k">Becomes</span><span>Quantity delivered: 19 tonnes</span>'
'<span class="k">The old text</span><span>is taken out of the file, not covered over</span>'
'</div></div><div class="pdf-dlg-a">'
'<span class="w-chip">Cancel</span><span class="w-chip">Keep both</span>'
'<span class="w-cta">Replace</span></div></div></div>')
# ── Scan ────────────────────────────────────────────────────────────────────
def field(k, v, note=""):
n = f'<span class="cv">{note}</span>' if note else ''
return f'<span class="k">{k}</span><span class="pdf-in">{v}{n}</span>'
w("Scan.dc.html",
'<div class="pdf-over-scrim">' + behind() + '<div class="pdf-dlg">'
'<div class="pdf-dlg-t">Scan</div><div class="pdf-dlg-b">'
'<div>Pages arrive in the document you have open.</div>'
'<div class="pdf-kv">'
+ field("Copier", "Ricoh IM C3000 &mdash; Dakar plant", "ready")
+ field("Feed", "Both sides")
+ field("Colour", "Greyscale")
+ field("Detail", "300 dpi", "print")
+ '</div>'
'<div><span class="w-state">Text search on</span> &nbsp;French and English</div>'
'</div><div class="pdf-dlg-a">'
'<span class="w-chip">Cancel</span><span class="w-cta">Scan</span></div></div></div>')
# ── The three directions ────────────────────────────────────────────────────
def strip_B(active="Select"):
tools = A_TOOLS + A_EDIT + ["Stamp", "Image", "Crop", "Merge", "Flatten"] + A_DOC + ["Redo"]
return ('<div class="pdf-tools pdf-tools--icons" style="height:30px">'
+ "".join(ico_t(t, t == active) for t in tools)
+ f'<div class="pdf-end">{ZOOM}</div></div>')
def ico_t(n, on=False):
c = "pdf-t on" if on else "pdf-t"
return f'<div class="{c}">{ico(n, on)}</div>'
def strip_C(tab="Edit"):
tabs = ("Document", "Edit", "Pages")
row = {"Document": A_TOOLS + ["Merge", "Flatten"],
"Edit": A_EDIT + ["Stamp", "Image", "Crop"],
"Pages": ["Pages", "Search", "Undo", "Redo"]}[tab]
return ('<div class="pdf-tabs">' + "".join(
f'<span class="pdf-tab{" on" if t == tab else ""}">{t}</span>' for t in tabs)
+ '</div><div class="pdf-tools" style="height:34px">'
+ "".join(T(t, t == "Select") for t in row)
+ f'<div class="pdf-end">{ZOOM}</div></div>')
board = f'''<div class="board">
<div class="card">
<h3>A &mdash; one row, named tools</h3>
<div class="strip">{strip_A("Select", 40)}</div>
<p class="why">Fourteen tools carry their name. Everything else &mdash; stamp, image, crop, merge, flatten, redo &mdash; lives behind the three dots on the right.</p>
<p class="cost">40px of chrome &middot; 512px left for the page &middot; 16 of 30 tools hidden</p>
</div>
<div class="card">
<h3>B &mdash; icons only, nothing hidden</h3>
<div class="strip">{strip_B("Select")}</div>
<p class="why">All thirty fit, name on hover. Fastest once someone knows the icons; a plant clerk opening it for the first time has to guess.</p>
<p class="cost">30px of chrome &middot; 522px left for the page &middot; nothing hidden</p>
</div>
<div class="card">
<h3>C &mdash; three tabs, named tools, nothing hidden</h3>
<div class="strip">{strip_C("Edit")}</div>
<p class="why">Document, Edit, Pages. Every tool keeps its name and every tool is reachable, at the price of one click to change tab and a second bar of chrome.</p>
<p class="cost">56px of chrome &middot; 496px left for the page &middot; nothing hidden, one click deeper</p>
</div>
</div>'''
w("Directions.dc.html", board)
# ── canvas ──────────────────────────────────────────────────────────────────
GX, GY = W + 90, H + 150
canvas = {
"artboards": [
{"file": "Directions.dc.html", "x": 0, "y": 0, "w": W, "h": 470,
"title": "Three ways to fit the toolbar — pick one"},
{"file": "Main.dc.html", "x": GX, "y": 0, "w": W, "h": H, "title": "A document open"},
{"file": "EditText.dc.html", "x": 2 * GX, "y": 0, "w": W, "h": H, "title": "Changing text on the page"},
{"file": "PageRail.dc.html", "x": 0, "y": GY, "w": W, "h": H, "title": "Page list open"},
{"file": "Nothing.dc.html", "x": GX, "y": GY, "w": W, "h": H, "title": "Nothing open yet"},
{"file": "Save.dc.html", "x": 2 * GX, "y": GY, "w": W, "h": H, "title": "Saving over the original"},
{"file": "Scan.dc.html", "x": GX, "y": 2 * GY, "w": W, "h": H, "title": "Scanning — not built yet"},
],
"annotations": [
{"id": "brief", "x": 0, "y": -150, "w": 660,
"text": "MMD PDF — the Windows PDF editor for staff.\nEvery frame is 800x600, the plant PC screen. Styling is the new MMD shell system, taken from its own source. Official MMD lockup only.\n600 minus 28 title bar minus 20 status bar leaves 552px for toolbar and page."},
{"id": "decision", "x": 0, "y": 490, "w": 620,
"text": "The one thing that needs your answer: a PDF editor has about thirty tools and thirty named tools need roughly 1400px. A, B and C give up different things. Mark the one you want and the rest follows from it."},
{"id": "scan-note", "x": GX, "y": 2 * GY - 90, "w": 420,
"text": "Scanning does not exist in the application yet. This is the design for it, not a picture of something that works."},
{"id": "edit-note", "x": 2 * GX, "y": -90, "w": 430,
"text": "This is the moment the old wording is destroyed. The status bar says so, and Enter/Esc are spelled out because both were guessed wrong during testing."},
],
"launch": {"view": "canvas"},
}
json.dump(canvas, open(os.path.join(OUT, "canvas.json"), "w"), indent=2)
print("written 7 artboards")
+93
View File
@@ -0,0 +1,93 @@
{
"artboards": [
{
"file": "Directions.dc.html",
"x": 0,
"y": 0,
"w": 800,
"h": 470,
"title": "Three ways to fit the toolbar \u2014 pick one"
},
{
"file": "Main.dc.html",
"x": 890,
"y": 0,
"w": 800,
"h": 600,
"title": "A document open"
},
{
"file": "EditText.dc.html",
"x": 1780,
"y": 0,
"w": 800,
"h": 600,
"title": "Changing text on the page"
},
{
"file": "PageRail.dc.html",
"x": 0,
"y": 750,
"w": 800,
"h": 600,
"title": "Page list open"
},
{
"file": "Nothing.dc.html",
"x": 890,
"y": 750,
"w": 800,
"h": 600,
"title": "Nothing open yet"
},
{
"file": "Save.dc.html",
"x": 1780,
"y": 750,
"w": 800,
"h": 600,
"title": "Saving over the original"
},
{
"file": "Scan.dc.html",
"x": 890,
"y": 1500,
"w": 800,
"h": 600,
"title": "Scanning \u2014 not built yet"
}
],
"annotations": [
{
"id": "brief",
"x": 0,
"y": -150,
"w": 660,
"text": "MMD PDF \u2014 the Windows PDF editor for staff.\nEvery frame is 800x600, the plant PC screen. Styling is the new MMD shell system, taken from its own source. Official MMD lockup only.\n600 minus 28 title bar minus 20 status bar leaves 552px for toolbar and page."
},
{
"id": "decision",
"x": 0,
"y": 490,
"w": 620,
"text": "The one thing that needs your answer: a PDF editor has about thirty tools and thirty named tools need roughly 1400px. A, B and C give up different things. Mark the one you want and the rest follows from it."
},
{
"id": "scan-note",
"x": 890,
"y": 1410,
"w": 420,
"text": "Scanning does not exist in the application yet. This is the design for it, not a picture of something that works."
},
{
"id": "edit-note",
"x": 1780,
"y": -90,
"w": 430,
"text": "This is the moment the old wording is destroyed. The status bar says so, and Enter/Esc are spelled out because both were guessed wrong during testing."
}
],
"launch": {
"view": "canvas"
}
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

+103
View File
@@ -0,0 +1,103 @@
body{margin:0;background:#F3F3F0;font-family:"PP Neue Machina","Neue Machina",system-ui,-apple-system,"Segoe UI",sans-serif;color:#3C3A34;-webkit-font-smoothing:antialiased}
a{color:#C8102E} a:hover{color:#8E0B20}
*{box-sizing:border-box}
.root{padding:16px;background:#F3F3F0}
.shell{width:1180px;display:flex;flex-direction:column;font-size:11.5px;background:#FFFFFF;border:1px solid #C7C6BD}
.s-title{display:flex;align-items:center;gap:10px;padding:0 10px;height:30px;background:#C8102E;color:#fff;font-family:Fraunces,Georgia,serif;font-weight:700;font-size:12.5px}
.s-title .mmd-logo{height:19px;width:auto;display:block;flex:none;fill:#fff}
.spring{flex:1}
.s-who{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.07em;text-transform:uppercase;color:rgba(255,255,255,0.85)}
.s-signout{font-size:10px;padding:1px 0;color:#fff;text-decoration:underline;text-underline-offset:2px}
.s-bar{display:flex;align-items:stretch;gap:2px;padding:0 5px;background:#F7F7F3;border-bottom:1px solid #D7D6CE}
.s-item{display:flex;align-items:center;gap:6px;padding:6px 10px;font-size:11px;white-space:nowrap;border:1px solid transparent;color:#3C3A34}
.s-item .cv{font-size:8px;opacity:0.5}
.s-item .n{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;padding:0 4px;border:1px solid #23221E;color:#23221E;background:#FFFFFF;line-height:13px}
.s-item.on{background:#FFFFFF;border-color:#D7D6CE;border-top:2px solid #C8102E;border-bottom-color:#FFFFFF;margin-bottom:-1px;font-weight:700;color:#23221E}
.s-item.on .n{border-color:#23221E;color:#23221E}
.s-tools{margin-left:auto;display:flex;align-items:center;gap:6px;padding-right:4px}
.s-search{width:168px;padding:2px 7px;font-size:10.5px;background:#FFFFFF;border:1px solid #C7C6BD;color:#23221E}
.s-btn{padding:2px 9px;font-size:10.5px;background:#FFFFFF;border:1px solid #C7C6BD;color:#23221E}
.s-desk{position:relative;background:#D4D0C6;overflow:hidden}
.s-desk.tiled{display:grid;grid-template-columns:1.35fr 1fr;grid-template-rows:auto auto;gap:10px;padding:10px;align-items:start}
.s-desk.stacked{height:492px}
.s-desk.oneup{padding:10px}
.s-task{display:flex;align-items:center;gap:10px;padding:4px 8px;font-size:10.5px;background:#F1F1EC;border-top:1px solid #D7D6CE}
.s-task .lbl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;letter-spacing:0.1em;text-transform:uppercase;color:#767368}
.s-group{display:inline-flex;align-items:stretch;border:1px solid #D7D6CE;background:#FFFFFF}
.s-group .app{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#767368;padding:2px 7px;border-right:1px solid #D7D6CE;display:flex;align-items:center;background:#F7F7F3}
.s-group .win{padding:2px 8px;font-size:10px;color:#23221E;border-right:1px solid #D7D6CE;display:flex;align-items:center;gap:5px;background:#F1F1EC}
.s-group .win:last-child{border-right:0}
.s-group .win.on{box-shadow:inset 3px 0 0 #C8102E;font-weight:700;background:#FFFFFF}
.s-group .win.min{color:#3C3A34;background:#FFFFFF;outline:1px dashed #6B6A64;outline-offset:-3px}
.s-task .tile{font-size:10px;padding:1px 8px;border:1px solid #C7C6BD;background:#FFFFFF;color:#3C3A34}
/* windows — title bar made visible: darker plate, ink name, clear border; front = red top edge + shadow */
.win-frame{background:#FFFFFF;border:1px solid #B9B8AE;display:flex;flex-direction:column;min-width:0;box-shadow:0 1px 2px rgba(35,34,30,0.12)}
.win-frame.front{border-color:#767368;box-shadow:0 6px 16px rgba(35,34,30,0.26)}
.stacked .win-frame{position:absolute}
.w-title{display:flex;align-items:center;gap:8px;height:28px;padding:0 6px 0 8px;background:#E4E3DC;border-bottom:1px solid #C9C6BC;font-size:11px;color:#3C3A34}
.front .w-title{background:#FFFFFF;color:#23221E;border-top:3px solid #C8102E;height:31px}
.w-title .app{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.1em;text-transform:uppercase;color:#23221E;font-weight:700}
.w-title .app::after{content:"/";margin-left:8px;color:#6B6A64}
.w-title .name{font-family:Fraunces,Georgia,serif;font-weight:600;font-size:12px;color:#3C3A34}
.front .w-title .name{color:#23221E;font-weight:700}
.w-title .new{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.12em;text-transform:uppercase;color:#23221E;background:#E4E3DC;padding:0 6px;line-height:15px}
.w-title .ctl{display:flex;gap:8px}
.w-title .ctl span{width:24px;height:24px;display:flex;align-items:center;justify-content:center;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:12px;color:#23221E;background:transparent;border:0}
.w-body{padding:0;overflow:hidden}
.w-toolbar{display:flex;align-items:center;gap:8px;padding:5px 8px;background:#FAFAF8;border-bottom:1px solid #E6E5DF}
.w-h1{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:13px;letter-spacing:-0.01em;margin:0;color:#23221E}
.w-count{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#6B6A64}
.w-count b{color:#C8102E;font-weight:600}
.w-filters{margin-left:auto;display:flex;gap:4px}
.w-chip{padding:1px 7px;font-size:9.5px;font-family:"JetBrains Mono",ui-monospace,monospace;border:1px solid #D7D6CE;background:#FFFFFF;color:#3C3A34}
.w-chip.on{border-color:#767368;color:#23221E;font-weight:600}
.w-cta{padding:2px 9px;font-size:10px;background:#C8102E;color:#FFFFFF;border:1px solid #C8102E;font-weight:600}
table.w-tbl{width:100%;border-collapse:collapse;font-size:10.5px;background:#FFFFFF}
.w-tbl th{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;text-align:left;padding:4px 8px;white-space:nowrap;background:#F1F1EC;color:#23221E;border-bottom:1px solid #D7D6CE;border-right:1px solid #E6E5DF}
.w-tbl td{padding:4px 8px;border-bottom:1px solid #E6E5DF;border-right:1px solid #E6E5DF;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}
.w-tbl td:last-child,.w-tbl th:last-child{border-right:0}
.w-tbl tr:nth-child(even) td{background:#FAFAF8}
.w-tbl td.num{font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums;text-align:right}
.w-tbl th.num{text-align:right}
.w-tbl td.ref{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.03em}
.w-tbl tr.sel td{background:#F7F7F3;box-shadow:inset 3px 0 0 #C8102E}
.w-state{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.07em;text-transform:uppercase;padding:1px 5px;background:#F1F1EC;color:#23221E}
.rec{display:grid;grid-template-columns:repeat(2, minmax(0, 1fr));gap:0}
.rec .col{padding:6px 10px 8px;border-right:1px solid #E6E5DF}
.rec .col:last-child{border-right:0}
.rec h4{margin:4px 0 4px;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.12em;text-transform:uppercase;color:#767368;font-weight:600;border-bottom:1px solid #E6E5DF;padding-bottom:3px}
.kv{display:grid;grid-template-columns:96px 1fr;gap:2px 8px;font-size:10.5px;margin:0}
.kv dt{color:#767368}
.kv dd{margin:0;color:#23221E}
.kv dd.mono{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:10px;font-variant-numeric:tabular-nums}
.rec-actions{display:flex;gap:6px;padding:6px 10px;border-top:1px solid #E6E5DF;background:#FAFAF8}
.rec-actions span{padding:2px 9px;font-size:10px;border:1px solid #C7C6BD;background:#FFFFFF;color:#23221E}
.rec-actions span.primary{color:#FFFFFF;background:#C8102E;border:1px solid #C8102E;font-weight:600}
.steps{display:flex;gap:0;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.06em;text-transform:uppercase;border-bottom:1px solid #E6E5DF}
.steps span{padding:3px 8px;border-right:1px solid #E6E5DF;color:#6B6A64}
.steps span.done{color:#767368}
.steps span.now{color:#C8102E;font-weight:700;box-shadow:inset 0 -2px 0 #C8102E}
.rep{padding:6px 10px}
.rep .row{display:grid;grid-template-columns:150px 1fr;gap:10px;padding:4px 0;border-bottom:1px solid #E6E5DF;font-size:10.5px}
.rep .row:last-child{border-bottom:0}
.rep .name{color:#23221E;font-weight:600}
.rep .name small{display:block;font-family:"JetBrains Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:0.08em;text-transform:uppercase;color:#6B6A64;font-weight:400}
.rep .hl{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;color:#3C3A34;font-variant-numeric:tabular-nums}
/* title-bar option closeups */
.opt{width:600px;padding:16px;background:#D4D0C6}
.opt .cap{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:0.12em;text-transform:uppercase;color:#767368;margin:0 0 8px}
.opt .win-frame{margin-bottom:14px}
.opt .win-frame:last-child{margin-bottom:0}
/* Option B: ink strip */
.optB .front .w-title{background:#3C3A34;color:#fff;border-top:0;height:28px;border-bottom:1px solid #23221E}
.optB .front .w-title .name{color:#fff}
.optB .front .w-title .app{color:#fff}
.optB .front .w-title .app::after{color:rgba(255,255,255,0.35)}
.optB .front .w-title .ctl span{color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,0.6)}
.optB .front .w-title .new{color:#fff;border-color:rgba(255,255,255,0.7)}
/* Option C: ruled */
.optC .w-title{background:#FFFFFF;border-bottom:2px solid #23221E;height:28px}
.optC .front .w-title{background:#FFFFFF;border-top:3px solid #C8102E;height:31px;border-bottom:2px solid #23221E}
.optC .win-frame{border-color:#23221E}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

-6
View File
@@ -1,6 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
]
}