{{define "head"}}
{{/* Vendored, in dependency order, and deferred so neither blocks the
first paint. defer preserves document order, so each module below
is defined before the one that calls it: live.js registers
window.SheetsLive and paint.js window.SheetsPaint; grid.js calls
both once the window has loaded; menubar.js and commands.js wire
the chrome and read window.SheetsGrid, which grid.js publishes. */}}
{{end}}
{{/* The open sheet's title, and for anyone who may edit it the rename,
are the bar's (estilo's editable title slot, chrome.TitleEdit, built
in handleSheetPage). It is still a real form posting to
/sheets/{id}/rename, so Enter renames with scripting off, and the
Rename button is visually hidden until the field has focus. Escape
restores the title and leaves the field (estilo chrome.js), which
fixes the sticky focus look the audit found. A reader sees the
title read-only. */}}
{{define "main"}}
{{/* The grid gets its own , without rst-page's padding and max
width: a spreadsheet is the one screen in this app that should fill
the viewport. Everything else uses the layout's default. */}}
{{template "content" .}}
{{end}}
{{/* --- Glyphs -------------------------------------------------------
Written here rather than fetched with {{icon}}. rastrillo vendors
twelve Lucide slugs — alert-triangle, check, check-circle,
chevron-down, help-circle, info, kebab, menu, plus, search, x,
x-circle — and rastrillo.Icon returns an EMPTY STRING for a slug it
does not have, with no error. So {{icon "bold"}} is not a missing
icon, it is a button with no label and no complaint, which is the
same silent-failure shape as an invented CSS token.
Bold and italic are letters, because that is what they are on every
spreadsheet anybody has used. The three alignments are rules,
because "left" as a word is longer than the button. */}}
{{define "glyph-align-left"}}{{end}}
{{define "glyph-align-center"}}{{end}}
{{define "glyph-align-right"}}{{end}}
{{define "glyph-undo"}}{{end}}
{{define "content"}}
{{/* Row B — the menu bar and the toolbar share one row.
Six short words are about 300px; a row holding only them wastes
two-thirds of itself. They wrap onto separate rows below ~900px,
which is also what keeps the chrome inside the 320px reflow
budget. */}}
{{if .Data.MayWrite}}
{{/* The toolbar. Hidden until commands.js wires it: every control
posts, so an unwired one is a button that does nothing.
role="toolbar" with a roving tabindex, so the whole strip is one
tab stop rather than fourteen — the same shape the Docs app uses,
deliberately, so the two apps behave alike. */}}
123{{icon "chevron-down"}}
{{range .Data.NumberFormats}}
{{end}}
{{icon "chevron-down"}}
{{range .Data.FillSwatches}}
{{end}}
A{{icon "chevron-down"}}
{{range .Data.InkSwatches}}
{{end}}
{{end}}
{{/* Row C — the name box and the formula bar, full width.
The formula bar shows the selected cell's INPUT while the grid
shows its computed value, which is the difference between a
spreadsheet and a table of numbers. It is also the reliable way to
see a formula: the in-cell editor swap is best effort. */}}
Selected cell contents
{{template "contrast-notice" .Data.Warned}}
{{/* Row D — the tabs along the bottom, and the status that used to sit
in the strip above the grid.
One tab today, rendered as a link to the page it is already on, so
the strip is real markup rather than a picture of tabs. There is
deliberately no "+": nothing in this build creates, names or
switches a tab, and spec §14 makes "a second tab is reachable in
the UI" the trigger for multi-worksheet import. A + that did
nothing would fake that trigger. */}}
{{/* Deliberately NOT role="status". It changes on every arrow key, and
a live region announcing "3 cells" after each one talks over the
cell content a screen reader is trying to read. It is a glance,
and the selection itself is what announces. */}}
{{/* The one place this app can say something transient. role="status"
is right here and wrong on the selection size beside it: this
changes when you ask for something and it did not happen, which
is exactly what a person needs read out, where the selection
size changes on every arrow key and would talk over the cell. */}}
Connecting