/* tsvsheet.web — minimal, calm chrome around the grid. The sheet is the UI.

   Theming: the OS preference decides by default, and an explicit
   data-theme="dark"/"light" on the root (the hosted page's toggle, persisted
   under the legacy playground's key) OVERRIDES it in both directions — the
   attribute must win, or the toggle is a no-op on half the machines. The dark
   palette therefore appears twice: once under the media query (gated so an
   explicit "light" beats a dark OS) and once under the attribute. */

:root {
	color-scheme: light dark;
	--border: #c9c9c9;
	--muted: #6b6b6b;
	--accent: #0b6e4f;
	--error-bg: #fbe9e7;
	--error-fg: #8c1d18;
	--paper: #ffffff;
	--mono: "IBM Plex Mono", ui-monospace, monospace;
	font-family: ui-sans-serif, system-ui, sans-serif;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		color-scheme: dark;
		--border: #3f3f3f;
		--muted: #9a9a9a;
		--error-bg: #3a1f1d;
		--error-fg: #f2b8b5;
		--paper: #12161b;
	}
}

:root[data-theme="dark"] {
	color-scheme: dark;
	--border: #3f3f3f;
	--muted: #9a9a9a;
	--error-bg: #3a1f1d;
	--error-fg: #f2b8b5;
	--paper: #12161b;
}

:root[data-theme="light"] {
	color-scheme: light;
}

body {
	margin: 0;
}

.tsvsheet-app {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	padding: 1rem;
}

.chrome {
	display: flex;
	align-items: baseline;
	gap: 1rem;
}

.title {
	font-size: 1.1rem;
	margin: 0;
}

.toolbar {
	display: flex;
	gap: 0.5rem;
}

.toolbar button,
.notice button {
	font: inherit;
	padding: 0.25rem 0.75rem;
	border: 1px solid var(--border);
	border-radius: 0.375rem;
	background: transparent;
	cursor: pointer;
}

.toolbar button:focus-visible,
.notice button:focus-visible,
[role="gridcell"]:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 1px;
}

/* The hosted product chrome (tsvsheet.com/playground and /app): one quiet
   strip above the editor — saved sheets, share, theme, help. */
.hosted-chrome {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-wrap: wrap;
	padding: 0.5rem 1rem;
	border-bottom: 1px solid var(--border);
	position: relative;
}

.hosted-chrome select,
.hosted-chrome input,
.hosted-chrome button {
	font: inherit;
	font-size: 0.9rem;
	padding: 0.25rem 0.6rem;
	border: 1px solid var(--border);
	border-radius: 0.375rem;
	background: transparent;
	color: inherit;
}

.hosted-chrome button {
	cursor: pointer;
}

.hosted-chrome input {
	width: 9rem;
}

.hosted-help {
	position: absolute;
	top: 100%;
	right: 1rem;
	z-index: 10;
	max-width: 34rem;
	border: 1px solid var(--border);
	border-radius: 0.375rem;
	background: var(--paper, Canvas);
	padding: 0.75rem 1rem;
	box-shadow: 0 8px 24px rgb(0 0 0 / 0.18);
}

.hosted-help .help-title {
	margin: 0 0 0.5rem;
	font-weight: 600;
}

.hosted-help th {
	text-align: right;
	padding-right: 0.75rem;
	white-space: nowrap;
	color: var(--muted);
	font-weight: 500;
	vertical-align: top;
}

/* The formula bar: the focus cell's address and raw source, always in view.
   Monospace, because the source IS the artifact. */
.formula-bar {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	border: 1px solid var(--border);
	border-radius: 0.375rem;
	padding: 0.3rem 0.6rem;
}

.formula-bar .addr {
	color: var(--muted);
	font-family: var(--mono);
	font-size: 0.85rem;
	min-width: 3ch;
	text-align: right;
}

.formula-bar input {
	flex: 1;
	font-family: var(--mono);
	font-size: 0.95rem;
	border: none;
	outline: none;
	background: transparent;
	color: inherit;
}

/* The editor beside its live source pane. */
.doc-main {
	display: flex;
	gap: 0.75rem;
	align-items: flex-start;
}

.grid-region {
	min-width: 0;
}

.source-pane {
	flex: 0 0 22rem;
	max-width: 40%;
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
}

.source-pane textarea {
	font-family: var(--mono);
	font-size: 0.85rem;
	line-height: 1.5;
	tab-size: 12;
	min-height: 16rem;
	resize: vertical;
	border: 1px solid var(--border);
	border-radius: 0.375rem;
	padding: 0.6rem;
	background: transparent;
	color: inherit;
	white-space: pre;
}

.source-pane[data-error="true"] textarea {
	border-color: var(--error-fg);
}

.source-pane .pane-status {
	color: var(--error-fg);
	font-size: 0.8rem;
	min-height: 1.2em;
}

/* A toolbar group reads as one unit. */
.toolbar-group {
	display: inline-flex;
	gap: 0.25rem;
	padding: 0 0.25rem;
	border-left: 1px solid var(--border);
	border-right: 1px solid var(--border);
}

.notice {
	border: 1px solid var(--error-fg);
	background: var(--error-bg);
	color: var(--error-fg);
	border-radius: 0.375rem;
	padding: 0.5rem 0.75rem;
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 1rem;
}

.empty {
	color: var(--muted);
}

table[role="grid"] {
	border-collapse: collapse;
	font-variant-numeric: tabular-nums;
}

table[role="grid"] th,
table[role="grid"] td {
	border: 1px solid var(--border);
	padding: 0.25rem 0.6rem;
	min-width: 4.5rem;
	text-align: left;
}

table[role="grid"] th {
	color: var(--muted);
	font-weight: 500;
	background: color-mix(in srgb, var(--border) 18%, transparent);
}

td.cell-error {
	background: var(--error-bg);
	color: var(--error-fg);
}

/* The range selection: a quiet accent wash over every selected cell — the
   focused cell keeps its ring, so a single-cell selection reads as today. */
table[role="grid"] td[aria-selected="true"] {
	background: color-mix(in srgb, var(--accent) 14%, transparent);
}

table[role="grid"] td[aria-selected="true"].cell-error {
	background: color-mix(in srgb, var(--accent) 14%, var(--error-bg));
}

/* What the focus cell reads (solid ring) and is read by (dashed ring) — the
   engine's own references, drawn shape-distinct so the difference never rests
   on color alone. Colorblind-safe blue/orange. */
table[role="grid"] td[data-refs] {
	position: relative;
}

table[role="grid"] td[data-refs]::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
}

table[role="grid"] td[data-refs~="reads"]::before {
	box-shadow: inset 0 0 0 2px #4477aa;
}

table[role="grid"] td[data-refs~="read-by"]::before {
	outline: 2px dashed #ee7733;
	outline-offset: -3px;
}

/* The copy marquee: a dashed rectangle around the copied block — what the next
   paste will use. Each cell carries the edges it sits on, and one overlay
   element per cell composes them into a single crisp outline. */
table[role="grid"] td[data-copied] {
	position: relative;
}

table[role="grid"] td[data-copied]::after {
	content: "";
	position: absolute;
	inset: -1px;
	pointer-events: none;
	border: 0 dashed var(--accent);
}

table[role="grid"] td[data-copied~="top"]::after {
	border-top-width: 2px;
}

table[role="grid"] td[data-copied~="bottom"]::after {
	border-bottom-width: 2px;
}

table[role="grid"] td[data-copied~="left"]::after {
	border-left-width: 2px;
}

table[role="grid"] td[data-copied~="right"]::after {
	border-right-width: 2px;
}

.cell-editor {
	font: inherit;
	width: 100%;
	box-sizing: border-box;
	border: none;
	outline: none;
	background: transparent;
	color: inherit;
}

.diagnostics {
	list-style: none;
	margin: 0;
	padding: 0;
	color: var(--error-fg);
}

.raw-text {
	border: 1px solid var(--border);
	border-radius: 0.375rem;
	padding: 0.75rem;
	overflow-x: auto;
	tab-size: 12;
}

/* The view a sheet declares for itself (`#.` directives).
   Freezing is what a viewport does, so it is CSS and nothing more: the engine
   says which rows and columns are pinned, the browser pins them. */
table[role="grid"] tr[data-frozen="true"] th,
table[role="grid"] tr[data-frozen="true"] td {
	position: sticky;
	top: 1.9rem;
	background: var(--paper, #fff);
	z-index: 2;
}

table[role="grid"] td[data-frozen="true"],
table[role="grid"] th[data-frozen="true"] {
	position: sticky;
	left: 2.5rem;
	background: var(--paper, #fff);
	z-index: 1;
}

/* A declared header row reads as a header, without becoming one structurally:
   the cells are still grid cells, because the row is still data. */
table[role="grid"] tr[data-header="true"] td {
	font-weight: 600;
}

/* The discontinuity a hidden block leaves behind. Row numbers never renumber —
   row 7 stays row 7 while 3–6 are hidden — so the skip is marked instead of
   silently closing up. */
table[role="grid"] tr[data-gap="true"] th,
table[role="grid"] tr[data-gap="true"] td {
	border-top: 3px double var(--rule, #ccc);
}

table[role="grid"] th[data-gap="true"] {
	border-left: 3px double var(--rule, #ccc);
}

/* While revealing, what the sheet hides is shown as such rather than as
   ordinary data — the declaration is still in force, the reader is just
   looking past it. Revealing never writes to the file. */
table[role="grid"] tr[data-hidden="true"] td,
table[role="grid"] tr[data-hidden="true"] th,
table[role="grid"] td[data-hidden="true"],
table[role="grid"] th[data-hidden="true"] {
	opacity: 0.55;
	font-style: italic;
}
