clone

an offline map explorer where each world, from a game map to a city's open data, ships as one .atlas file

feat/atlas-next-horizon
atlas / internal / app / assets / css / chrome.css
chrome.css 6.5K
1/*2 chrome — the whole difference between the carried stylesheet system and the3 markup this application renders.45 Every other file in this directory is carried unedited (issue #5 §9: the6 cascade is an asset, and the visual identity is unchanged). What this7 application's markup has that those files cannot know about is collected8 here rather than smeared through the files it would belong to, so the delta9 stays one file long.1011 The list is short on purpose. A difference the markup can spell instead is12 not a difference: the detail card used to be patched here, keyed off13 `:empty`, because a region rendered inside-out could not be given an14 attribute; it is an outerMorph region now and renders its own `hidden`, so15 the carried pin-detail.css works verbatim and there is nothing to say.16*/1718/*19 1. The regions the partial envelope swaps into carry ids of their own.2021 A region is one element with one id and one swap (internal/app/partials.go).22 The carried system hangs off classes almost everywhere, so the regions wear23 both: `<aside id="atlas-legend" class="sidebar">` is styled by the carried24 `.sidebar` rules and targeted by the envelope's `#atlas-legend`. Two places25 in the carried system reach for an id, and they are re-pointed here.26*/27#atlas-legend .legend .layer-section:last-child { border-bottom: 0; }2829/*30 2. The seam's surfaces are the seam's, including while a swap is happening.3132 `<atlas-viewport>` and the overview's canvas holder carry33 hx-morph-skip-children: a swap may touch their attributes and never their34 internals (issue #5 §4.3). They therefore have no styling of their own here35 beyond standing where the carried `.map` and `.overview` rules expect --36 which is what these two rules say.37*/38atlas-viewport {39 position: absolute;40 inset: 0;41 display: block;42}43atlas-chart,44atlas-globe {45 position: absolute;46 inset: 0;47 display: block;48}49atlas-globe[hidden] { display: none; }5051/*52 3. The import region.5354 An import is a streamed answer (internal/app/importing.go), so it needs55 somewhere to stand and a word for each state it passes through. Nothing in56 the carried cascade describes it, because a native file dialog whose only57 sign was the button it was raised from needed no panel at all.5859 It is one row, not a log: the region holds the run that is happening and60 nothing else, and the handler morphs it from state to state. The section61 says so itself -- it renders `hidden` when it is holding nothing, which an62 outerMorph region can do and the `:empty` rule this used to lean on could63 only guess at.6465 A row that ended well takes itself away. The news that a volume installed is66 worth a moment and is clutter after that, and the reader is not going to67 dismiss a thing they never asked to see -- so the fade is the stylesheet's68 job, on a delay, with no script and nothing for the handler to remember. A69 refusal is the opposite and stays: it is the only account of what went70 wrong, and the next import is what replaces it.71*/72.import-rows {73 position: fixed;74 right: 17px;75 bottom: 17px;76 z-index: 80;77 display: grid;78 gap: 4px;79 width: min(360px, calc(100% - 34px));80 font-size: 12px;81}82.import-rows[hidden] { display: none; }83.import-row {84 margin: 0;85 padding: 8px 11px;86 border: 1px solid var(--line);87 border-radius: 7px;88 background: var(--panel-raised);89 color: var(--muted);90 overflow: hidden;91}92.import-row[data-state="installed"] { color: var(--text-strong); border-color: var(--accent); }93.import-row[data-state="refused"] { color: #d99; border-color: #7e3f3f; }94.import-row[data-state="installing"] { color: var(--text); }9596/*97 The row stands for a few seconds, fades, and then collapses out of the98 corner it was standing in -- the collapse is what stops an invisible box99 going on sitting over the map. `forwards` is load-bearing: an animation that100 did not hold its last frame would put the row back at the end of it.101*/102.import-row-fading {103 animation: import-row-fade 500ms ease-in 4s forwards;104}105@keyframes import-row-fade {106 0% { opacity: 1; max-height: 8rem; }107 60% { opacity: 0; max-height: 8rem; }108 100% {109 opacity: 0;110 max-height: 0;111 padding-block: 0;112 border-block-width: 0;113 visibility: hidden;114 }115}116117/*118 A reader who asked for less motion still wants the row gone; what they do119 not want is the going. The delay stands and the movement does not.120*/121@media (prefers-reduced-motion: reduce) {122 .import-row-fading { animation-duration: 1ms; }123}124125/*126 4. A feature index row is three elements.127128 One element carries one request, and a row of a feature index answers three:129 the left button goes to the ground, the right button highlights it, and the130 crosshair asks for that ground and no other131 (internal/app/templates/legend.tmpl). The wrapper is the one that hears the132 contextmenu, and it is the row itself: the name flexes, the action stands in133 a gutter beside it.134135 The gutter is reserved whether or not the control is showing, which is the136 rule the carried system states where it reserves the same column on a137 collection row (layer-header.css) — a row that grew on hover would push the138 one under the cursor out from under it.139*/140.zone-index-row {141 display: flex;142 align-items: center;143}144145.zone-index-row .zone-index-item {146 flex: 1;147 min-width: 0;148}149150.zone-index-row .only-button {151 flex: none;152}153154/*155 The reveal is the carried rule's own, said again for a row the carried system156 never had. `.only-button` is drawn at `opacity: 0` and revealed under157 `.is-hovered` — the class the seam writes from where the pointer actually is158 rather than from `:hover`, because a list that scrolls under a still cursor159 is exactly what `:hover` gets wrong (render/hover.ts).160161 A zone that IS the highlight keeps its crosshair lit unasked. The control is162 the way back out of the filter it set, and a way out that only appears once163 the reader has found it is not one.164*/165.zone-index-row.is-hovered .only-button,166.zone-index-row .only-button[aria-pressed="true"] {167 opacity: 1;168}169170.zone-index-row .only-button[aria-pressed="true"] {171 background: rgba(58, 165, 201, 0.14);172}173174/*175 5. A pane put away is put away.176177 Both panes are absolutely positioned and `display: block`, which is stronger178 than the `[hidden]` the browser's own sheet carries — so without this the179 chart went on standing behind the sphere at full size, and the one question180 a renderer answers from its window (how much of the map is in view, how a181 cell fits it) went on being answered by a window nobody was looking through.182*/183atlas-chart[hidden] { display: none; }