/* realizes: docs/ui-spec.md > §7 local desktop layout, using ui/tokens.css roles */

.local-window {
  min-block-size: calc(100vh - (var(--role-desk-margin) * 2));
  block-size: calc(100vh - (var(--role-desk-margin) * 2));
}

.local-window > .window-main { min-block-size: 0; padding: 0; overflow: hidden; }

.local-layout {
  display: grid;
  grid-template-columns: minmax(var(--columns-min), .7fr) minmax(0, 2fr);
  min-block-size: 0;
  block-size: 100%;
  gap: var(--role-gutter);
  padding: var(--role-gutter);
}

.games-column {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto auto;
  min-block-size: 0;
  background: var(--face);
}

.games-column > .games-list { max-block-size: none; min-block-size: 0; }
.games-column .list-head { border-bottom: var(--rule-width) solid var(--mid); padding-inline-end: calc(var(--role-row-x) + var(--role-bevel)); }
.games-column .list-foot { flex-wrap: wrap; border-top: var(--rule-width) solid var(--mid); }
.empty-library, .build-warnings { margin: 0; padding: var(--role-row-y) var(--role-row-x); font-size: var(--role-small); }
.build-warnings { color: var(--warn-note); }

.play-region {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  min-block-size: 0;
  background: var(--face);
}

.play-region[data-controller-visible="false"] { grid-template-rows: minmax(0, 1fr); }
.play-surface { display: grid; grid-template-rows: minmax(0, 1fr) auto; min-block-size: 0; }
.play-stage { position: relative; min-block-size: 0; block-size: 100%; display: grid; }
.play-surface .canvas-frame { min-block-size: 0; block-size: 100%; overflow: hidden; }
.play-stage:fullscreen { background: var(--stage); }
.play-stage:fullscreen .canvas-frame { border: 0; box-shadow: none; }
.play-surface canvas { display: block; max-inline-size: 100%; max-block-size: 100%; }
.idle-prompt { position: absolute; inset-block-end: var(--role-row-y); margin: 0; color: var(--canvas-empty-text); font-size: var(--role-small); }
.play-meta { display: flex; justify-content: center; gap: var(--role-gutter); padding: calc(var(--role-row-y) / 2) var(--role-row-x); background: var(--face); font-size: var(--role-small); }
[data-region="controller"] { overflow: auto; border-top: var(--rule-width) solid var(--mid); }

.slot-group, .slot-group label, .pane-actions {
  display: flex;
  align-items: center;
  gap: calc(var(--role-gutter) / 2);
}

.pane-actions { justify-content: flex-end; }
.archive-detail-list { margin: 0; padding: 0; list-style: none; }
.game-verdict { font-weight: var(--weight-bold); }
.game-info { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: calc(var(--role-gutter) / 2) var(--role-gutter); }
.game-info dt { font-weight: var(--weight-bold); }
.game-info dd { margin: 0; }
.technical { font-family: var(--font-mono); }
.import-details[data-tone="bad"] { color: var(--bad); font-weight: var(--weight-bold); }

.link-button {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--title);
  text-decoration: underline;
}

.visually-hidden {
  position: absolute;
  inline-size: var(--rule-width);
  block-size: var(--rule-width);
  overflow: hidden;
  clip-path: inset(50%);
}

[data-modal="import"] .modal { inline-size: min(var(--modal-phone-width), var(--gallery-max)); }
[data-modal="settings"] .modal,
[data-modal="controls"] .modal,
[data-modal="per-game-settings"] .modal { inline-size: min(var(--modal-phone-width), var(--gallery-max)); }
[data-modal="import"] .modal-body { overflow-x: hidden; }
:fullscreen .play-meta { display: none; }
.import-pane, [data-stored-files-tab] { display: grid; gap: var(--role-gutter); }
.status-bar { flex-wrap: wrap; }
.status-bar .btn { min-height: auto; }

.settings-pane, .controls-pane {
  display: grid;
  gap: var(--role-gutter);
  padding: var(--role-row-y) var(--role-row-x);
}

.settings-check, .scope-choice label { display: inline-flex; align-items: center; gap: calc(var(--role-gutter) / 2); }
.settings-transfer, .device-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--role-gutter); }
.device-line { margin: 0; font-size: var(--role-small); }
.scope-choice { display: flex; flex-wrap: wrap; gap: var(--role-gutter); border: var(--rule-width) solid var(--mid); }
.scope-choice legend { font-weight: var(--weight-bold); }
.controls-pane .range { min-inline-size: 20em; }
.controls-pane .table td:last-child { white-space: nowrap; }
.storage-settings .kv2 > span:nth-child(even) { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--role-gutter) / 2); }


/* Modal hosts: each [data-modal] wrapper is the full-screen layer its veil fills, so it has a box of its own. */
[data-modal] { position: fixed; inset: 0; z-index: var(--z-modal); }

/* Presentation keeps the same mounted canvas and cabinet inside the page fullscreen root. */
.local-page[data-mode="presentation"] { block-size: 100vh; inline-size: 100%; overflow: hidden; background: var(--stage); }
[data-mode="presentation"] > .desk { padding: 0; background: var(--stage); }
[data-mode="presentation"] .local-window { border: 0; box-shadow: none; block-size: 100vh; min-block-size: 0; grid-template-rows: minmax(0, 1fr); }
[data-mode="presentation"] .local-layout { display: block; padding: 0; }
[data-mode="presentation"] .play-region { block-size: 100%; grid-template-rows: minmax(0, 1fr); }
[data-mode="presentation"] .play-surface { grid-template-rows: minmax(0, 1fr); }
[data-mode="presentation"] .canvas-frame { border: 0; box-shadow: none; }
.presentation-overlay { position: absolute; inset: 0; padding: var(--role-desk-margin); background: var(--desk); z-index: var(--z-veil); }
.local-page { position: relative; }
.presentation-window[data-menu="false"] { block-size: 100%; grid-template-rows: auto minmax(0, 1fr); }
.presentation-window > .window-main { min-block-size: 0; overflow: hidden; }
.presentation-columns { display: grid; grid-template-columns: minmax(22em, 1fr) minmax(0, 2fr); gap: var(--role-gutter); block-size: 100%; }
.presentation-actions { display: flex; flex-direction: column; gap: calc(var(--role-gutter) / 2); overflow: auto; }
.presentation-actions .action-button { min-block-size: var(--role-min-target); }
.presentation-actions .action-trailing { white-space: normal; text-align: end; max-inline-size: 10em; }
.presentation-mode-switch { margin-block-start: auto; padding-block-start: var(--role-gutter); }
.presentation-slot { display: grid; grid-template-columns: minmax(0, 1fr) auto; border: var(--rule-width) solid var(--mid); }
.presentation-slot .action-button { block-size: 100%; }
.presentation-slot .selector { inline-size: 100%; font-size: var(--role-small); }
.presentation-slot .selector-value { max-inline-size: 8em; padding-inline: calc(var(--role-control-x) / 2); }
.selector-value small { display: block; font-size: var(--role-tiny); font-weight: var(--weight-normal); overflow-wrap: anywhere; }
.presentation-content { min-inline-size: 0; min-block-size: 0; overflow: auto; display: flex; flex-direction: column; }
.presentation-games { min-block-size: 0; display: flex; flex-direction: column; }
.presentation-games .table { font-size: var(--role-list); }
.presentation-games tr.hl td { background: var(--active); color: var(--ink); }
.presentation-games tr[data-focus="true"] td { background: var(--title); color: var(--light); }
.presentation-playing { color: var(--ok); font-weight: var(--weight-bold); }
.presentation-bad { color: var(--bad); font-weight: var(--weight-bold); }
.presentation-frame { background: var(--stage); display: grid; place-items: center; block-size: 48vh; flex: none; overflow: hidden; }
.presentation-frame img { block-size: 48vh; inline-size: auto; max-inline-size: 100%; object-fit: contain; image-rendering: pixelated; }
.presentation-card h1 { font-size: var(--role-heading); margin-block: var(--role-gutter); }
.presentation-card p, .presentation-message { font-size: var(--role-small); }
.presentation-message { margin-block-start: auto; padding-block-start: var(--role-gutter); }
[data-controls-inline] { min-block-size: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; block-size: 100%; }
.inline-controls-body { min-block-size: 0; overflow: auto; }
[data-controls-inline] .tabs { flex-wrap: wrap; }
[data-controls-inline] .controls-pane { padding-inline: 0; }
[data-controls-inline] .modal-foot { flex-wrap: wrap; padding-inline: 0; }
[data-controls-inline] .scope-choice { align-items: center; }
[data-presentation-hint] { position: absolute; inset-inline: 0; inset-block-end: var(--role-gutter); z-index: 1; display: flex; justify-content: center; pointer-events: none; animation: presentation-hint 3s forwards; }
[data-presentation-hint] .start-hint { position: static; transform: none; margin: 0; }
@keyframes presentation-hint { 0%, 80% { opacity: 1; } 100% { opacity: 0; } }

/* Phone layouts share the desktop PlaySurface's React position and display container. */
.local-page[data-density="phone"] { --dpad-cell: 44px; --red-size: 44px; --role-control-x: 8px; }
.local-page[data-density="phone"][data-mode="local"] { block-size: 100dvh; overflow: hidden; }
[data-density="phone"] .local-window { block-size: 100dvh; min-block-size: 0; border: 0; box-shadow: none; }
[data-density="phone"][data-mode="local"] .local-layout { display: block; padding: 0; }
[data-density="phone"][data-mode="local"] .play-region { block-size: 100%; min-inline-size: 0; }
[data-density="phone"][data-mode="local"] .play-meta { display: none; }
[data-density="phone"] .title-bar { min-block-size: 44px; }
[data-density="phone"] .title-close { min-inline-size: 44px; min-block-size: 44px; }
[data-density="phone"] button, [data-density="phone"] select, [data-density="phone"] input:not([type="checkbox"]):not([type="radio"]), [data-density="phone"] .settings-check, [data-density="phone"] .scope-choice label { min-block-size: 44px; touch-action: manipulation; }
[data-density="phone"] .tab { min-inline-size: 44px; padding-inline: 8px; }
[data-density="phone"] .tabs { flex-wrap: wrap; }
[data-density="phone"] .dpad, [data-density="phone"] .red-button { touch-action: none; user-select: none; -webkit-user-select: none; }
[data-density="phone"] .dpad-key { touch-action: none; }
[data-density="phone"] .dpad[data-mini="true"] { pointer-events: none; }
[data-density="phone"] .dpad[data-mini="true"] button, [data-density="phone"] .red-button[data-mini="true"], [data-density="phone"] .pill[data-mini="true"] { min-block-size: 0; }
.phone-bar { display: flex; align-items: center; gap: 4px; padding: 4px; background: var(--face); grid-area: bar; z-index: 2; transition: opacity .25s; }
.phone-bar .btn { flex: 1; padding-inline: 6px; }
.phone-bar [data-phone-action="menu"], .phone-bar [data-phone-action="fullscreen"] { flex: 0 0 44px; }
.phone-bar [data-phone-bar-status] { flex: 1; color: var(--ink); font-size: var(--role-small); text-align: center; }
[data-bar-visible="false"] .phone-bar { opacity: 0; pointer-events: none; }
[data-layout="phone-landscape"][data-bar-visible="false"] .phone-bar { display: none; }   /* the row collapses so the canvas takes the whole screen; a tap brings it back */
:root:not([data-input="touch"]) [data-bar-visible="false"] .phone-bar:focus-within { opacity: 1; pointer-events: auto; }
.phone-switches { display: flex; gap: 8px; overflow-x: auto; padding: 4px; min-inline-size: 0; }
.phone-switches .switch-row { flex: none; flex-wrap: nowrap; }
.phone-switches .switch-label { display: block; font-size: var(--role-tiny); }
.phone-switches button { white-space: nowrap; }
[data-layout="phone-portrait"][data-mode="local"] .play-region { grid-template: "bar" auto "game" minmax(0, 1fr) "switches" auto "controller" auto / minmax(0, 1fr); }
[data-layout="phone-portrait"][data-mode="local"] .play-surface { grid-area: game; grid-template-rows: minmax(0, 1fr); }
[data-layout="phone-portrait"] .play-region > .phone-switches { grid-area: switches; }
[data-layout="phone-portrait"] .phone-controller { grid-area: controller; display: grid; grid-template-columns: 132px minmax(44px, 1fr) 132px; grid-template-rows: 66px 66px; align-items: center; justify-items: center; gap: 4px; padding: 4px; }
[data-layout="phone-portrait"] .phone-side-panel { display: contents; }
[data-layout="phone-portrait"] .phone-controller .dpad { grid-column: 1; grid-row: 1 / 3; align-self: center; justify-self: start; }   /* the element is its nine cells, nothing taller: the thumb math and tests measure it */
[data-layout="phone-portrait"] .phone-controller .button-bank { grid-column: 3; grid-row: 1 / 3; gap: 0; }
[data-layout="phone-portrait"] .phone-controller [data-control="coin"] { grid-column: 2; grid-row: 1; }
[data-layout="phone-portrait"] .phone-controller [data-control="start"] { grid-column: 2; grid-row: 2; }
[data-layout="phone-portrait"] .phone-controller .pill { padding-inline: 2px; font-size: var(--role-tiny); min-inline-size: 44px; }
[data-density="phone"] .status-bar { gap: 0; font-size: var(--role-small); }
[data-density="phone"] .status-cell { padding-block: 2px; }
[data-density="phone"] [data-status-cell="autosave"] { display: none; }
[data-layout="phone-landscape"][data-mode="local"] .local-window { grid-template-rows: minmax(0, 1fr); }
[data-layout="phone-landscape"][data-mode="local"] .local-window > .title-bar { display: none; }
/* The bar is a row of its own above the panels and the canvas (decided 2026-10-28: nothing sits over the game or the switches). */
[data-layout="phone-landscape"][data-mode="local"] .play-region { position: relative; grid-template: "bar bar bar" auto "directions game buttons" minmax(0, 1fr) / minmax(148px, 20%) minmax(0, 1fr) minmax(148px, 20%); }
[data-layout="phone-landscape"][data-mode="local"] .play-region[data-controller-visible="false"] { grid-template: "bar" auto "game" minmax(0, 1fr) / minmax(0, 1fr); }
[data-layout="phone-landscape"][data-mode="local"] .play-surface { grid-area: game; grid-template-rows: minmax(0, 1fr); }
[data-layout="phone-landscape"] .phone-bar { grid-area: bar; }
[data-layout="phone-landscape"] .phone-controller { display: contents; }
[data-layout="phone-landscape"] .phone-side-panel { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; min-block-size: 0; overflow: auto; gap: 4px; padding: 4px; background: var(--face); }
[data-layout="phone-landscape"] [data-side-panel="directions"] { grid-area: directions; }
[data-layout="phone-landscape"] [data-side-panel="buttons"] { grid-area: buttons; }
[data-layout="phone-landscape"][data-swap-sides="true"] [data-side-panel="directions"] { grid-area: buttons; }
[data-layout="phone-landscape"][data-swap-sides="true"] [data-side-panel="buttons"] { grid-area: directions; }
[data-layout="phone-landscape"] .phone-switches { flex: 0 1 auto; inline-size: 100%; min-block-size: 44px; padding: 0; overflow: auto; }
[data-layout="phone-landscape"] .phone-switches .switch-row { flex: 1; display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; }
[data-layout="phone-landscape"] .phone-switches .switch-label { flex-basis: 100%; }
[data-layout="phone-landscape"] .phone-controller .button-bank { gap: 2px; margin-block-start: auto; }
[data-layout="phone-landscape"] .phone-controller .dpad { flex: none; margin-block-start: auto; }
[data-density="phone"][data-fullscreen="true"][data-mode="local"] .local-window { grid-template-rows: minmax(0, 1fr); }
/* Fullscreen on a phone is the game and, when on, the controller: the bar goes with the title and status (decided 2026-10-28). */
[data-density="phone"][data-fullscreen="true"][data-mode="local"] .phone-bar { display: none; }
/* Fullscreen on a phone targets the page root, not the display container, so the frame's bevel and the window's
   edges would stay: drop them as the desktop's :fullscreen and the presentation stage do, and let the stage colour fill. */
[data-density="phone"][data-fullscreen="true"][data-mode="local"] .local-window { border: 0; box-shadow: none; background: var(--stage); }
[data-density="phone"][data-fullscreen="true"][data-mode="local"] .canvas-frame { border: 0; box-shadow: none; }
[data-density="phone"][data-fullscreen="true"][data-mode="local"] .play-region { gap: 0; padding: 0; background: var(--stage); }
[data-density="phone"][data-fullscreen="true"][data-mode="local"] .play-surface { padding: 0; }
[data-density="phone"][data-fullscreen="true"][data-mode="local"] .phone-controller, [data-density="phone"][data-fullscreen="true"][data-mode="local"] .phone-switches { background: var(--face); }
[data-density="phone"] .veil { padding: 0; }
[data-density="phone"] .modal { inline-size: 92%; max-block-size: 92dvh; }
[data-density="phone"] .modal-body { padding: 8px; }
[data-density="phone"] .modal-foot { flex-wrap: wrap; position: sticky; inset-block-end: 0; background: var(--face); padding: 8px; }
[data-phone-games] .games-column { display: flex; flex-direction: column; }
[data-phone-games] .games-list { flex: 1; }
[data-phone-games] .list-foot { position: sticky; inset-block-end: 0; background: var(--face); }
.phone-menu-list { display: grid; gap: 4px; padding-block: 8px; }
.phone-menu-item { display: flex; align-items: center; justify-content: space-between; gap: 8px; inline-size: 100%; min-block-size: 44px; text-align: start; }
.phone-menu-item small { font-size: var(--role-small); text-align: end; overflow-wrap: anywhere; }
.phone-menu-selector { display: flex; align-items: center; justify-content: space-between; }
.phone-game-card { display: grid; gap: 4px; padding: 8px; }
[data-density="phone"] .table { table-layout: fixed; inline-size: 100%; overflow-wrap: anywhere; }
[data-density="phone"] .table td, [data-density="phone"] .table th, [data-density="phone"] .controls-pane .table td:last-child { white-space: normal; padding: 4px; }
[data-density="phone"] .table .btn { max-inline-size: 100%; white-space: normal; }
[data-density="phone"] .controls-pane, [data-density="phone"] .settings-pane { padding: 8px 0; }
[data-density="phone"] .controls-pane .range { min-inline-size: 0; }
[data-density="phone"] .kv2 { grid-template-columns: minmax(0, 1fr); }
.phone-table-boxes { display: grid; gap: 8px; }
.phone-table-boxes fieldset { min-inline-size: 0; }
.phone-table-field { display: grid; gap: 4px; margin-block: 8px; }
[data-density="phone"] .presentation-overlay { padding: 4px; }
[data-density="phone"] .presentation-columns { grid-template-columns: minmax(230px, 1fr) minmax(0, 1fr); gap: 8px; }
[data-density="phone"] .presentation-window .window-main { padding: 4px; }
/* Eight actions must fit a phone's landscape height: single-line rows, the slot picker beside its action, small gaps. */
[data-density="phone"] .presentation-actions { gap: 3px; }
[data-density="phone"] .presentation-slot { grid-template-columns: minmax(0, 1fr) auto; }
[data-density="phone"] .presentation-slot .selector-value { max-inline-size: 9em; padding-inline: 4px; white-space: nowrap; }
[data-density="phone"] .presentation-slot .selector-value small { display: inline; margin-inline-start: 4px; }
[data-density="phone"] .presentation-actions .action-button { padding: 4px 6px; min-block-size: 36px; white-space: nowrap; }
[data-density="phone"] .presentation-actions .action-button > span { white-space: nowrap; }
[data-density="phone"] .presentation-mode-switch { padding-block-start: 3px; }
[data-density="phone"] .presentation-actions .button-glyph { display: none; }
[data-density="phone"] .presentation-frame, [data-density="phone"] [data-presentation-metadata] { display: none; }
[data-density="phone"] .presentation-window .title-secondary { font-size: var(--role-small); }
[data-density="phone"] .range { grid-template-columns: minmax(0, 1fr); }
[data-density="phone"] .field-line { min-block-size: 44px; }
[data-density="phone"] .phone-table-field > input[type="checkbox"] { min-block-size: 44px; min-inline-size: 44px; }
[data-density="phone"] [data-presentation-frame] { display: none; }
.local-page[data-density="phone"][data-mode="presentation"], [data-density="phone"] .desk { min-block-size: 100dvh; }
.local-page[data-density="phone"][data-mode="presentation"] { block-size: 100dvh; }
.phone-fps { position: absolute; inset-block-end: 4px; inset-inline-end: 8px; padding: 2px 4px; background: var(--stage); color: var(--light); font-size: var(--role-small); pointer-events: none; }
