* { box-sizing: border-box; margin: 0; padding: 0; }

/* Sol is primarily a desktop tool -- the left panel is widened here rather
   than left cramped to fit small screens too (mobile already gets its own
   full-width override below, at max-width: 580px). #info-panel/#method-panel
   and #method-panel's own width both derive their left offset from this
   same variable, so they never fall out of sync with it. */
:root {
  --left-col-w: 340px;
  /* Dempet tekst som bærer informasjon (Ricky, 2026-10-02, design-kritikk #9). #888 og
     var(--muted-blue) ga 3,5 og 3,7:1 på hvitt, under AA (4,5:1); disse to gir 5,3 og 5,5:1 og
     holder 4,8:1 selv på pille-bakgrunnen #eef0f3. Den deaktiverte «Zoom inn»-
     tilstanden (.is-far) beholder #7386a0: inaktive kontroller er unntatt WCAG 1.4.3. */
  --muted: #6b6b6b;      /* nøytral grå: etiketter, bildetekster, enheter */
  --muted-blue: #5a6a83; /* blågrå: søyle- og ringetiketter, notater, bygningspillen */
  /* Fargesystemet samles gradvis (design-kritikk #11, Ricky 2026-10-02): én mørk blekkfarge
     og tre navngitte blåfarger med hver sin rolle, i stedet for tilfeldige hex-verdier. */
  --ink: #1d2733;          /* tekst og tegn i panelene (var #1a1a2e, #1d2733) */
  --accent: #1a73e8;       /* interaktive kontroller: omriss, valgt, lenker */
  --accent-strong: #1565c0;/* fylt hovedhandling og fremdrift (5,7:1 mot hvit tekst) */
  --focus: #2f6fd0;        /* fokusring */
}

html, body { height: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }

#map { position: absolute; inset: 0; cursor: crosshair; z-index: 1; }
#map3d { position: absolute; inset: 0; z-index: 5; background: #e9e9e6; }
#map3d.hidden { display: none; }
/* Laid out and drawing, but not seen: MapLibre sizes itself from its container, and the user keeps looking at the
   2D map until the 3D one is ready. */
#map3d.map3d-preparing { visibility: hidden; pointer-events: none; }
#map3d-canvas { position: absolute; inset: 0; }
/* The rotate buttons sit with MapLibre's own zoom and compass control (bottom right), not in the top bar, where the 2D
   map's "Velg et sted ..." box stands. */
.map3d-rotate button { display: flex; align-items: center; justify-content: center; color: #333; }
.point-shade { display: flex; align-items: center; justify-content: center; gap: 8px; margin: -2px 12px 8px; font-size: 13px; font-weight: 600; color: var(--ink); }
.point-shade.hidden { display: none; }
.point-shade-dot { flex: none; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.25); }
.map3d-ground-row { display: flex; align-items: center; gap: 6px; margin: 6px 0 2px; font-size: 12px; color: #45526a; cursor: pointer; }
.map3d-ground-row.hidden { display: none; }
.map3d-msg { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 2; margin: 0; padding: .6rem 1rem; border-radius: 8px; background: rgba(0,0,0,.7); color: #fff; font: 500 .9rem/1.3 system-ui, sans-serif; }
.map3d-msg.hidden { display: none; }
/* What would otherwise sit over the 3D map (z-index 9-10) while it is open. #left-column stays. */
body.map3d-open #map-compass { visibility: hidden; }

/* The shade overlay sits in Leaflet's overlayPane, so it lands above the tiles
   and below the marker and direction handle without any z-index of its own.
   pointer-events: none keeps map clicks and drags working straight through it. */
.shadow-layer {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}
.shadow-layer.hidden { display: none; }

#map-compass {
  position: absolute;
  bottom: 16px;
  left: 16px;
  z-index: 10;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  box-shadow: 0 2px 12px rgba(0,0,0,0.15);
  pointer-events: none;
}

#map-compass span {
  position: absolute;
  font-size: 11px;
  font-weight: 600;
  color: #555;
}

.compass-n { top: 4px; left: 50%; transform: translateX(-50%); }
.compass-s { bottom: 4px; left: 50%; transform: translateX(-50%); }
.compass-e { right: 5px; top: 50%; transform: translateY(-50%); }
.compass-w { left: 5px; top: 50%; transform: translateY(-50%); }

#left-column {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: var(--left-col-w);
}

#panel, #result-panel, #underlay-panel, #info-panel, #method-panel {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  padding: 16px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.15);
}

/* The gutter is reserved even with no scrollbar showing, so a scrollbar that
   comes and goes cannot change the width the text wraps at. */
#panel { max-height: calc(100vh - 32px); overflow-y: auto; scrollbar-gutter: stable; scrollbar-width: thin; }

#result-panel {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 10;
  width: 460px;
  /* Scroll inside the panel instead of growing taller than the viewport --
     same pattern as #info-panel/#method-panel below (Ricky, 2026-09-25:
     "litt breddere og samtidig sikre ikke er lengre"). */
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}

/* Directly under the Beregn box, on the same centre line (Ricky, 2026-09-29): the
   button that runs the calculation must stay reachable while these are being
   adjusted. The centre is the middle of the free strip between the left column
   (16 + 340 + 16 = 372 px) and Solberegning (460 + 16 + 16 = 492 px), which is
   (100vw - 120px) / 2 -- the same line #calc-box sits on. 78px = the box's
   16px offset + its 54px height + an 8px gap. */
#underlay-panel {
  position: absolute;
  top: 78px;
  left: calc((100vw - 120px) / 2);
  transform: translateX(-50%);
  z-index: 8;
  width: 340px;
  max-height: calc(100vh - 94px);
  overflow-y: auto;
}
.result-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.result-panel-head h3 { margin-bottom: 0; }
/* The save icon sits at the right of the head, before the sheet's own arrow on a phone. Its hit area is 44 px like the other buttons. */
.result-save-btn { margin-left: auto; width: 44px; height: 44px; margin-top: -10px; margin-bottom: -10px; display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; border-radius: 8px; color: var(--muted); cursor: pointer; }
.result-save-btn:disabled { opacity: .4; cursor: default; }
.result-save-btn:hover:not(:disabled), .result-save-btn:focus-visible { background: rgba(0, 0, 0, 0.06); color: inherit; }

#info-panel, #method-panel {
  position: absolute;
  /* Under the Beregn box (16px offset + 54px height + 8px gap, same 78px as Underlag): at
     16px these two covered the button in the middle of the strip (design review #8). */
  top: 78px;
  left: calc(16px + var(--left-col-w) + 16px);
  z-index: 10;
  width: 320px;
  /* Scroll inside the panel instead of growing past the map and leaving a
     blank strip below it. */
  max-height: calc(100vh - 94px);
  overflow-y: auto;
}

/* The method text grew with the near-shade steps — wider so it reads as
   paragraphs, but never so wide it runs under the result panel (460px + 16px
   gaps on the right, so 492px reserved). */
/* Overskriften etter en liste (Kilder og lisenser -> Personvern) klistret seg til listen. */
#method-panel ul + h3 { margin-top: 16px; }
#method-panel { width: max(320px, min(560px, calc(100vw - (16px + var(--left-col-w) + 16px) - 492px))); }

@media (max-width: 1040px) {
  #info-panel, #method-panel {
    left: 16px; top: 224px; width: min(560px, calc(100vw - 32px));
    max-height: calc(100vh - 240px);
  }
}

/* The shadow controls live inside #panel now (Ricky, 2026-09-29), under the
   Skygge switch; they no longer float beside the map. */
#shadow-panel { margin-top: 8px; }
.shadow-switch-row { display: flex; align-items: center; gap: 8px; margin: 4px 0 8px; }
.info-btn.shadow-switch { flex: 1; min-width: 0; margin: 0; padding: 8px 12px; font-size: 12px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
/* A switch, not a text field (design review #14, Ricky 2026-10-02): it was full width with a
   1 px border and left-aligned text, the same shape as the address field above it. Centred text
   and a small ring that fills when the shade is on; the state logic and colours are unchanged. */
.info-btn.shadow-switch::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid currentColor; box-sizing: border-box; }
.info-btn.shadow-switch[aria-pressed="true"]::before { background: currentColor; }
.info-btn.shadow-switch.is-far::before { display: none; }
/* Working (fetching heights, or measuring the buildings in 3D): the ring spins. */
.info-btn.shadow-switch:disabled::before, .info-btn.shadow-switch.is-busy::before { border-color: rgba(0,0,0,.2); border-top-color: currentColor; animation: spin 0.7s linear infinite; }
/* On: soft green fill, continuing the green edge of the "ready" state. It used to
   be solid blue both before and after the press, so the only thing that changed
   was the text and nobody saw it change (Ricky, 2026-09-29). */
.info-btn.shadow-switch[aria-pressed="true"] { background: #e3f3e8; color: #1b6b35; border-color: #2e9d4f; }
.info-btn.shadow-switch[aria-pressed="true"]:hover { background: #d3ebdb; }
/* Thin green edge = "zoomed in enough, pressing this will show the shade". */
.info-btn.shadow-switch.is-ready { border-color: #2e9d4f; }
/* Too far out: reads as a hint rather than a button that will do something. */
.info-btn.shadow-switch.is-far { color: #7386a0; border-color: #c5ccd8; cursor: default; }
.info-btn.shadow-switch.is-far:hover { background: transparent; }

/* The ring, alone and centred -- the size picker used to sit beside it here,
   then moved under the time arc instead (Ricky, 2026-09-28: "flytt de
   radiobuttons ned under tids-halvbuen. Side om side"). The heading that
   used to sit above the old row ("Størrelse" + the exact metres) is gone
   too (Ricky, same day, an earlier round) -- the pill names already say
   what's chosen, and the note text at the bottom of the panel repeats the
   metres. */
.shadow-dial-row { display: none; /* the upright date slider replaces the ring (Ricky, 2026-10-12); it stays in the page and keeps its state */ justify-content: center; margin: 10px 0 0; }
/* Back to a single horizontal row (the (view-mode-only) size picker's
   original layout, before it briefly stacked vertically beside the ring) --
   same three pills, same underlying radio group, just wider now that they
   have the panel's own width instead of a narrow column. */
.shadow-level-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.shadow-level-picker { display: flex; gap: 6px; flex: 1; }
/* Round icon button, same circular recipe as .info-btn.icon-btn's "i" but
   without its italic letter-style -- a glyph doesn't need it. Spins while a
   refresh is in flight (the button's own disabled state IS the loading
   state, so nothing extra to track). */
.shadow-refresh-btn {
  width: 26px; height: 26px; padding: 0; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; font-size: 16px; line-height: 1;
}
@keyframes shadow-refresh-spin { to { transform: rotate(360deg); } }
/* Beside the switch it matches the switch's height. */
.shadow-switch-row .shadow-refresh-btn { width: 34px; height: 34px; }
.shadow-refresh-btn:disabled { animation: shadow-refresh-spin 0.8s linear infinite; }
.shadow-refresh-btn.is-far { opacity: 0.45; cursor: default; }
.shadow-refresh-btn.is-far:hover { background: transparent; }
/* One pill that names the step a press goes to (Nabolag / Område), like the 2D / 3D button. */
.shadow-level-btn {
  flex: 1; text-align: center; font: inherit; font-size: 12px; padding: 6px 0;
  border: 1px solid #dbe2ea; border-radius: 999px; background: #fff; color: #45526a; cursor: pointer;
}
@media (hover: hover) { .shadow-level-btn:hover { background: #f3f6fb; } }
.shadow-level-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

/* The date ring: 24 fixed dates (1./15. of every month) on one dial, dragged
   the same way as Panelvinkel/Himmelretning (index.html/js/app.js) -- same
   touch-action/cursor/focus-visible recipe as those widgets, so it feels like
   the same control even though the geometry is new. Grown from 168px (Ricky,
   2026-09-28: moving the pills aside made room for a bigger wheel). */
.shadow-date-wrap { display: flex; justify-content: center; flex-shrink: 0; }
.shadow-date-ring { display: block; width: 194px; height: 194px; touch-action: none; cursor: pointer; }
/* The black square is the BROWSER's focus ring, not ours, and the selector it
   answers to is plain `:focus` -- so `outline: none` had to move there. Putting
   it on `:focus-visible` (as it was first) only helps when the browser agrees
   that a just-tapped control is keyboard-focused, and a tap is exactly the case
   where it does not, so the ring stayed (Ricky, 2026-09-28, twice: "Den sorte
   firkanten er der fortsatt" / "Når man trykker på de, så vises det en sort
   firkant"). Measured in his two screenshots: a 1px black line with a 1px white
   line outside it, sharp corners, hugging the element's box exactly -- 196px
   around the 194px ring, 212px around the 210px arc. An outline traces that
   rectangular box and a browser does not round the trace to match an SVG's
   round shape the way it would a div's `border-radius`. */
.shadow-date-ring:focus { outline: none; }
/* Keyboard focus still has to be visible, so it is drawn as a drop shadow
   instead: that follows the actual rendered shape (the ring's own alpha
   silhouette) rather than its bounding box, and reads as a glow around the
   wheel. */
.shadow-date-ring:focus-visible { filter: drop-shadow(0 0 3px var(--focus)) drop-shadow(0 0 3px var(--focus)); }
/* Each wedge carries its month's colour from DOME_MONTH_COLORS (js/dome.js),
   so the ring, the 3D dome's month lines and the month pie all read as the
   same thing. Muted until picked -- 24 fully-saturated wedges at once would
   be the opposite of what this redesign was for. */
.shadow-date-wedge { fill: var(--month-color); fill-opacity: 0.35; stroke: #fff; stroke-width: 1; }
/* Spoke labels around the outside (Ricky, 2026-09-28: "få plass til å skrive
   måned-navne") -- rotated per month in js/shadow-panel.js, not curved letter
   by letter. Also answers the muted-colours-blend-together note from the
   first round: the active month reads dark/bold even when its wedge colour
   looks similar to its neighbours'. pointer-events:none keeps a click meant
   for the ring underneath from landing on a label instead. */
.shadow-date-monthlabel { font-size: 8.5px; fill: var(--muted-blue); pointer-events: none; }
.shadow-date-monthlabel.is-active { fill: var(--ink); font-weight: 700; }
.shadow-date-wedge.is-active { fill-opacity: 1; stroke: #fff; stroke-width: 2; }
.shadow-date-handle { fill: #fff; stroke: var(--ink); stroke-width: 2; cursor: grab; }
.shadow-date-label { font-size: 20px; font-weight: 600; fill: var(--ink); }
.shadow-date-sublabel { font-size: 11px; fill: var(--muted-blue); }

.shadow-clock {
  position: absolute; left: 50%; top: 58%; transform: translate(-50%, -50%);
  font-size: 20px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  pointer-events: none;
}

/* The round time track: sunrise (left) to sunset (right) over the top, in
   place of the old 0-1439 line (Ricky, 2026-09-28: "Slideren under skal vi
   prøve å gjøre rund også. Fra soloppgang til solnedgang"). Same
   touch-action/cursor/focus-visible recipe as the date ring and Panelvinkel/
   Himmelretning -- one drag language across the whole panel. */
.shadow-arc-wrap { position: relative; display: none; /* the upright clock slider replaces the half-arc; same reason */ justify-content: center; margin-top: 0; }
.shadow-time-arc { display: block; width: 210px; height: 116px; touch-action: none; cursor: pointer; }
/* Same fix as .shadow-date-ring:focus above, and the same reason -- the arc is
   a 210x116 box around a half circle, so the browser's rectangular ring lands
   as a square around it. */
.shadow-time-arc:focus { outline: none; }
.shadow-time-arc:focus-visible { filter: drop-shadow(0 0 3px var(--focus)) drop-shadow(0 0 3px var(--focus)); }
/* Grey-gold-grey, not a plain track colour -- the two ends (sunrise/sunset)
   are deliberately cooler than the middle (solar noon), the same "one warm
   mark, two quiet ones" idea the old ticks used, just carried by the track's
   own colour now instead of separate marks. */
.shadow-time-track { fill: none; stroke: url(#shadow-time-gradient); stroke-width: 8; stroke-linecap: round; }
.shadow-time-tick { fill: #8b98ab; pointer-events: none; }
.shadow-time-tick--noon { fill: #e5a400; }
.shadow-time-handle { fill: #fff; stroke: #e5a400; stroke-width: 3; cursor: grab; }

/* Empty in view mode (Ricky, 2026-09-28: "denne kan vi fjerne") -- same
   :empty pattern, so the line takes itself out of the panel instead of leaving
   a blank paragraph's margin behind. */
.shadow-window { font-size: 12px; color: #45526a; margin-top: 6px; }
.shadow-window:empty { display: none; }


.panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 12px;
}

#panel h1.app-title, #result-panel h3, #underlay-panel h3, #info-panel h3, #method-panel h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}

#panel h1.app-title { margin-block: 0.83em; } /* the old h2 margin: «Sol» is the page's h1 now (design review #18) */
#result-panel h3, #underlay-panel h3, #info-panel h3, #method-panel h3 { font-size: 15px; padding-right: 16px; margin-bottom: 10px; }

.info-btn {
  font-size: 11px;
  color: var(--accent);
  background: none;
  border: 1px solid var(--accent);
  border-radius: 6px;
  cursor: pointer;
  padding: 3px 7px;
  white-space: nowrap;
  flex-shrink: 0;
}

.info-btn:hover { background: #f0f7ff; }

.info-btn[aria-pressed="true"] { background: var(--accent); color: #fff; }
.info-btn[aria-pressed="true"]:hover { background: #1667cf; }
.info-btn:disabled { opacity: 0.6; cursor: default; }

.panel-header-actions { display: flex; gap: 6px; flex-shrink: 0; }

.info-btn.icon-btn {
  width: 22px;
  height: 22px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-style: italic;
  font-weight: 700;
}

.field-group { margin: 10px 0; }

.field-group label { display: block; font-size: 11px; color: var(--muted); margin-bottom: 4px; }

.field-group input[type="range"] { width: 100%; }

.field-group.direction-dimmed { opacity: 0.4; }

/* Kartlag: real map-crop thumbnails instead of plain checkboxes (Ricky,
   2026-09-25). The checkbox itself stays functional (js/app.js's existing
   change listeners are untouched) but is visually hidden -- clicking
   anywhere in the card still toggles it via the native <label> wrapping.
   :has() (not a JS class toggle) drives the active-state highlight. */
/* 2D | 3D: the same pill language as the level picker. */
.map-controls-row { display: flex; align-items: center; gap: 8px; margin: 4px 0 8px; }
.view-switch-row { display: flex; flex: 1; }
.view-switch-btn { flex: 1; text-align: center; font: inherit; font-size: 12px; padding: 6px 0; border: 1px solid #dbe2ea; border-radius: 999px; background: #fff; color: #45526a; cursor: pointer; }
.view-switch-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.view-switch-btn:disabled { opacity: .6; cursor: progress; }
/* Topokart as a chip beside 2D | 3D: the map crop stays as the layer's own look, only small. */
.layer-toggle {
  flex: 0 0 auto; display: flex; flex-direction: row; align-items: center; gap: 6px;
  padding: 3px 10px 3px 3px; border-radius: 999px; border: 2px solid transparent;
  background: #f4f5f6; cursor: pointer; margin: 0;
}
.layer-toggle:hover { background: #ececec; }
.layer-toggle:has(input:checked) { border-color: var(--accent); background: #e8f0fe; }
.layer-toggle:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.layer-toggle input[type="checkbox"] {
  position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0;
}
.layer-toggle img { width: 26px; height: 26px; object-fit: cover; border-radius: 50%; display: block; }
.layer-toggle span { font-size: 11px; font-weight: 600; color: #555; }
.layer-toggle:has(input:checked) span { color: var(--accent); }

/* #757575, not the #999 this used to be -- #999 on white is 2.85:1, well
   under the 4.5:1 WCAG AA minimum for normal text (measured, not guessed:
   see design-kritikk pass, 2026-09-24). #757575 measures 4.61:1. */
/* Tilt (quarter-circle) and azimuth (compass) widgets share the same visual
   language as the map's own direction handle/line (#e65100 orange needle),
   so the two "which way does it point" controls read as one system. Each
   whole field (label + status line + widget) sits on one shared card
   background (.panel-field--widget below), rather than the widget alone
   having its own -- one background, not two nested ones. */
.arc-wrap, .compass-wrap, .height-wrap, .area-wrap { width: 128px; margin: 6px auto 2px; padding: 10px; }

/* Panelvinkel/Himmelretning (Ricky, 2026-09-24): a short heading with the
   longer explanation moved to a title tooltip (kept for screen readers via
   the visually-hidden span + aria-describedby), the computed/override status
   line moved below the widget instead of above it, and the whole field on
   one card background. */
.panel-field--widget {
  background: #f4f5f6;
  border-radius: 14px;
  padding: 10px 10px 8px;
}
/* While terrain/PVGIS data is loading, the four widgets are dimmed and
   inert -- dragging one mid-fetch would just be discarded or fight with the
   values the fetch is about to overwrite (Ricky, 2026-09-25: "kanskje fryse
   de 4 sliderne"). js/app.js's setPanelFieldsLocked toggles this on #underlay-panel;
   pointer-events:none only blocks mouse/touch, so the widgets' own pointer
   and keydown handlers also check panelFieldsLocked directly, for keyboard. */
#underlay-panel.fields-locked .panel-field--widget { opacity: 0.5; pointer-events: none; }
/* A real (if small) heading now that the explanation moved into the title
   tooltip -- the base .field-group label style (11px, #888) reads as a
   caption, too faint for what's now just "Panelvinkel"/"Himmelretning". */
.panel-field--widget label { cursor: help; font-size: 13px; font-weight: 600; color: #333; margin-bottom: 6px; }

/* Tilt+azimuth (the two orientation widgets) and height+area each share a
   row (see index.html's panel-field-row). box-sizing:border-box means
   .arc-wrap/.compass-wrap/.height-wrap's own 128px already fits a ~148px
   column with room to spare, so no widget needs to shrink here. The drag
   math in js/app.js works in viewBox units, not CSS pixels, so none of this
   needs any JS changes either way. */
.panel-field-row { display: flex; gap: 12px; align-items: flex-start; }
.panel-field-row .panel-field { flex: 1; min-width: 0; }
.arc-widget, .compass-widget, .height-widget, .area-widget { display: block; width: 100%; height: auto; touch-action: none; cursor: pointer; }
.arc-track, .compass-track { fill: none; stroke: #ddd; stroke-width: 6; stroke-linecap: round; }
.compass-track { fill: #fafafa; }
/* Compound selector so this reliably beats the plain grey rule above
   regardless of source order (Ricky, 2026-09-26). Outside Norway, or before
   the region lookup resolves, the class is simply absent -- default grey. */
.arc-track.arc-track--graded { stroke: url(#tilt-quality-gradient); }
/* Segments (built in js/app.js's renderCompassGradient) paint over the
   circle's own stroke, so that stroke is hidden while graded -- otherwise
   the plain grey ring would show through any gap/antialiasing seam. */
.compass-track.compass-track--graded { stroke: none; }
.compass-gradient-seg { fill: none; stroke-width: 6; }
.compass-cardinal { font-size: 11px; font-weight: 600; fill: var(--muted); }
.arc-needle { stroke: #e65100; stroke-width: 3; stroke-linecap: round; }
.arc-handle { fill: #e65100; stroke: #fff; stroke-width: 2; cursor: grab; }
/* pointer-events was "none" here, but the native <title> tooltip (added
   2026-09-25 for the "ikke beregnet" case below) needs hover to reach this
   element to fire at all -- dragging still works because pointerdown just
   bubbles up to the widget <svg>'s own listener, nothing here stops it. */
.widget-value { font-size: 22px; font-weight: 700; }
/* A default value shown because a real computation failed (not just "no
   point yet") -- dashed underline plus its own tooltip with the reason
   (js/app.js's renderWidgetValue), so a plain fallback number doesn't read
   as a genuine result (Ricky, 2026-09-25). */
.widget-value--unresolved { text-decoration: underline dashed; text-underline-offset: 3px; }
/* The computed value's own marker: a grey "ghost" needle/dot pointing at
   where the auto-fill landed, alongside the orange one showing your own
   override (Ricky, 2026-09-25: dropped the "din verdi"/"beregnet" caption
   row entirely -- colour alone, on the widget itself, now says which is which).
   Tapping the marker accepts the computed value (clears the override) --
   see setupAngleWidget/setupHeightWidget/setupAreaWidget's tick-group
   listener -- so the whole group gets a pointer cursor. */
g[data-role="tick-group"] { cursor: pointer; }
.tick-needle { stroke: #9e9e9e; stroke-width: 2; stroke-linecap: round; }
.tick-needle.hidden-soft { opacity: 0; }
.arc-tick { fill: none; stroke: #9e9e9e; stroke-width: 2; opacity: 0.7; }
.arc-tick.hidden-soft { opacity: 0; }
/* The computed value's own number, shown next to its tick mark -- only when
   an override is hiding it from the big value text (Ricky, 2026-09-25: no
   way to read the exact computed number back once every field is overridden).
   Not pointer-events:none like .widget-value -- this text is itself part of
   the clickable "accept computed value" marker. */
.widget-tick-label { font-size: 12px; font-weight: 600; fill: #555; }
.arc-widget:focus-visible, .compass-widget:focus-visible, .height-widget:focus-visible, .area-widget:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 12px; }
.hidden-soft { visibility: hidden; }

/* Height: a horizontal slider that still "simulates" the height (Ricky,
   2026-09-25) -- drag/click is left-right, but the post connecting the
   handle to the ground line rises with the value too (see js/app.js's
   HEIGHT_TRACK/heightPointXY), so the motion reads as "how high up" even
   though the interaction itself is horizontal. Reuses .arc-needle/.arc-
   handle/.arc-tick for the post/handle/computed-marker so it matches the
   other two widgets' orange needle language. */
.height-ground { stroke: #ccc; stroke-width: 2; stroke-linecap: round; }
.height-hatch { stroke: #ddd; stroke-width: 2; stroke-linecap: round; }

/* Area: a square that grows with the value -- area is inherently 2D, unlike
   an angle or a height, so a graph-paper square reads more honestly than
   another linear slider (Ricky, 2026-09-25: "prøv deg"). The fixed-size
   grid pattern (index.html's <pattern id="area-grid">) means a bigger
   square visibly contains more unit tiles, not just a bigger single shape. */
.area-shape { fill: url(#area-grid); stroke: #e65100; stroke-width: 2; }
/* pointer-events:all so the whole square is a tap target for "accept the
   computed value", not just its thin dashed border (fill:none would
   otherwise only hit-test the stroke). */
.area-tick { fill: none; stroke: #9e9e9e; stroke-width: 1.5; stroke-dasharray: 3 2; opacity: 0.7; pointer-events: all; }
.area-tick.hidden-soft { opacity: 0; }

/* Standard visually-hidden technique: present for screen readers (e.g. as
   an aria-describedby target) but not shown on screen, for text that's
   otherwise only available via a sighted-mouse title tooltip. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.address-field-group { position: relative; }

.address-field-group input[type="text"] {
  width: 100%;
  padding: 6px 8px;
  font-size: 13px;
  border: 1px solid #ccc;
  border-radius: 6px;
}

.address-row { display: flex; gap: 6px; align-items: center; }
.address-row input { flex: 1; min-width: 0; }
.address-row .icon-btn {
  flex: none; width: 32px; height: 32px; padding: 5px;
  border: 1px solid #ddd; border-radius: 6px; background: #fff; cursor: pointer;
}
@media (hover: hover) { .address-row .icon-btn:hover { background: #f3f6fb; } }
.address-field-group.is-collapsed input[type="text"] { display: none; }
.address-field-group:not(.is-collapsed) #address-open-btn { display: none; }
.address-field-group.is-collapsed .address-label {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
/* The list is anchored under the whole group; with the field folded away there is nothing for it to hang from. */
.address-field-group.is-collapsed .address-suggestions { display: none; }
.address-row .icon-btn:disabled { opacity: 0.5; cursor: progress; }
.address-row .icon-btn svg { width: 100%; height: 100%; display: block; }
/* A bit bigger than geolocate (Ricky, 2026-09-25: "litt større ikon") so the
   X reads clearly -- padding scales with it to keep the glyph from looking
   oversized inside the button. */
.address-row .icon-btn--clear { width: 36px; height: 36px; padding: 6px; }
/* The same X now sits beside Beregn (#progress), out of .address-row, so the
   row's rules above no longer reach it. Sized to the button's height. */
#progress .icon-btn--clear {
  flex: none; width: 38px; height: 38px; padding: 7px;
  border: 1px solid #ddd; border-radius: 8px; background: #fff; cursor: pointer;
}
#progress .icon-btn--clear svg { width: 100%; height: 100%; display: block; }
@media (hover: hover) { #progress .icon-btn--clear:hover { background: #f3f6fb; } }
#progress .icon-btn--clear.hidden { display: none; }

.address-suggestions {
  position: absolute;
  top: 100%;
  left: 0;
  /* Match the input's right edge, not the row's -- the row also contains
     the geolocate button (32px) and, once a point is selected, the clear
     button (36px) beside it, plus a row gap (6px) each. */
  right: calc(32px + 36px + 12px);
  z-index: 20;
  margin-top: 2px;
  background: white;
  border: 1px solid #ddd;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  list-style: none;
  max-height: 200px;
  overflow-y: auto;
}

.address-suggestion {
  padding: 7px 10px;
  font-size: 12px;
  color: #333;
  cursor: pointer;
}

.address-suggestion:hover, .address-suggestion.highlighted { background: #f0f7ff; }

.address-suggestion-empty {
  padding: 7px 10px;
  font-size: 12px;
  color: var(--muted);
}

.direction-handle-icon {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #e65100;
  border: 2px solid white;
  box-shadow: 0 1px 4px rgba(0,0,0,0.4);
  cursor: grab;
}

.direction-handle-icon.direction-dimmed { opacity: 0.4; }


.direction-line.direction-dimmed { opacity: 0.4; }

.close-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  background: none;
  border: none;
  font-size: 18px;
  line-height: 1;
  /* #aaa gav 2,3:1; ikonkontroller skal ha minst 3:1 (WCAG 1.4.11). Design-kritikk #10, Ricky 2026-10-02. */
  color: #757575;
  cursor: pointer;
  padding: 0;
}

.close-btn:hover { color: #333; }

#info-panel ol,
#info-panel ul,
#method-panel ol,
#method-panel ul {
  padding-left: 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

#info-panel ol li,
#info-panel ul li,
#method-panel ol li,
#method-panel ul li { font-size: 12px; color: #555; line-height: 1.4; }

#info-panel p, #method-panel p {
  font-size: 12px;
  color: #555;
  line-height: 1.5;
  margin-bottom: 10px;
}

#info-panel .info-section-heading,
#method-panel .info-section-heading {
  margin-top: 16px;
}

/* Explains the grey computed-value marker on the widgets above (Ricky,
   2026-09-25: "brukeren skjønner ikke hvor den grå verdien kommer fra") --
   a small muted caption. */
.panel-field-caption {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.4;
  margin: 4px 0 10px;
}

/* Was plain 12px grey text with no background -- easy to miss next to the
   map (Ricky, 2026-09-25: "vi bør vise det mer"). Same banner treatment as
   the .panel-msg--error banner below, just in a neutral blue instead of red. */
#progress {
  font-size: 13px; font-weight: 600; color: var(--accent-strong);
  min-width: 300px; padding: 8px 12px;
  /* wrap is what puts #progress-bar on its own line: the bar asks for the whole
     width as its flex-basis, and a nowrap row would shrink it instead. */
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px;
}
/* #progress's own "display: flex" (an ID selector) otherwise outranks the
   generic ".hidden { display: none; }" (a class selector) no matter the
   source order -- without this override the banner showed on every fresh
   page load, before any point had ever been placed (Ricky, 2026-09-25). */
#progress.hidden { display: none; }
/* Was "flex: 1; text-align: right" -- splitting the row 50/50 with
   #cancel-fetch-btn regardless of actual text length, so the longer
   progress messages ("Henter bygg og trær...") wrapped onto two lines on a
   narrow panel even though the row had room (Ricky, 2026-09-25). Sized to
   its own content instead, with #cancel-fetch-btn pushed to the far right
   by its own margin-left: auto below. */
#progress-text { white-space: nowrap; }
/* The same clock as the bar, in seconds. Tabular figures so the number does not
   jitter the row's width as it counts, and a fixed min-width because "1 s" and
   "18 s" would otherwise nudge #cancel-fetch-btn sideways every tick. */
#progress-elapsed {
  font-variant-numeric: tabular-nums; min-width: 2.6em; text-align: right;
  color: #4a7cc0; font-weight: 500;
}
/* The patience bar (Ricky, 2026-09-28). It fills over the current step's
   deadline and never claims more than that: 100% means the app is out of
   patience and about to say so, not "almost done". The fill width is set by
   setProgressPhase in js/app.js, which is the only writer. */
#progress-bar {
  flex: 0 0 100%; height: 3px; margin-top: 3px; border-radius: 2px;
  background: rgba(21,101,192,0.18); overflow: hidden;
}
#progress-bar-fill {
  display: block; height: 100%; width: 0;
  background: var(--accent-strong); border-radius: 2px;
}
/* Right after the spinner text so a stray click while panning the map
   (Ricky, 2026-09-25: "får uheldigvis trykket på kartet") doesn't force a
   wait -- calls clearPoint(), the same reset an explicit × already does,
   which is also what already knows how to stop a stuck spinner/lock (see
   its own comment on recalcGeneration). */
#cancel-fetch-btn {
  margin-left: auto; border: 0; background: none; padding: 0;
  font: inherit; font-weight: 700; color: var(--accent-strong); text-decoration: underline;
  cursor: pointer;
}
/* Idle state (a point is selected but "Beregn" hasn't been pressed yet):
   only the calculate button shows. Loading state (the default, no
   .calc-bar--idle): only the spinner/text/cancel show. js/app.js's
   setCalcBarMode toggles the class; nothing else needs to change per state. */
#progress.calc-bar--idle .spinner,
#progress.calc-bar--idle #progress-text,
#progress.calc-bar--idle #progress-elapsed,
#progress.calc-bar--idle #progress-bar,
#progress.calc-bar--idle #cancel-fetch-btn { display: none; }
/* Loading: the same 38 px pill as the hint and the Beregn button, so the box
   keeps its size through all three states (Ricky, 2026-09-29). The patience bar
   is the pill's own bottom edge rather than a second row under it. */
#progress:not(.calc-bar--idle) {
  position: relative; overflow: hidden; flex-wrap: nowrap;
  min-width: 0; min-height: 38px; margin: 8px 12px; padding: 0 16px;
  background: #e8edf5; border-radius: 8px; box-sizing: border-box;
}
#progress:not(.calc-bar--idle) #progress-bar {
  position: absolute; left: 0; right: 0; bottom: 0; margin: 0; border-radius: 0;
}
#progress:not(.calc-bar--idle) #calculate-btn,
#progress:not(.calc-bar--idle) #clear-point-btn { display: none; }
#calculate-btn {
  flex: 1; min-height: 38px; border: 0; background: var(--accent-strong); color: #fff; padding: 0 20px;
  border-radius: 8px; text-align: center; font: inherit; font-size: 14px;
  font-weight: 700; cursor: pointer;
}
#calculate-btn:hover { background: #0f4f9a; }
/* Disabled (js/app.js's updateCalculateButtonState) when the panel's
   current values already match the last successful calculation -- pressing
   it again would just re-run the same thing (Ricky, 2026-09-25: "nå kan
   man kjøre den uten [en endring]"). */
#calculate-btn:disabled { background: #b9c9e3; cursor: default; }

/* A message lives by the control that caused it (js/app.js showMsg/hideMsg).
   The .hidden rule sits after this one and has the same specificity as
   .panel-msg.hidden would need, so it is repeated here to be safe. */
.panel-msg {
  margin-top: 8px;
  font-size: 12px;
  padding: 8px;
  border-radius: 6px;
}
.panel-msg--error { color: #c62828; background: #ffebee; }
.panel-msg--hint { color: #37516b; background: #eaf0f6; }
.panel-msg.hidden { display: none; }

/* Centred at the top of the map before a point is chosen. pointer-events:none
   because the invitation is to click the map underneath it. */
#calc-box {
  position: absolute; top: 16px; left: calc((100vw - 120px) / 2); transform: translateX(-50%);
  /* Centred in the strip between the left column and Solberegning, not on the
     screen: from the screen's middle it slid under Solberegning below ~1340px. */
  z-index: 9; pointer-events: none;
  background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(8px);
  border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.15);
  min-width: 352px;
  max-width: min(560px, calc(100vw - 32px));
}
/* Clickable only while it holds a control; as a plain invitation it lets the
   click through to the map it is inviting the user to click. */
#calc-box:has(#progress:not(.hidden)) { pointer-events: auto; }
/* The invitation is the Beregn button in its resting, unavailable form: the same
   pill, the same 38 px row, the same box width as the state with a point, so the
   box does not change shape when a point is chosen -- only colour and text
   (Ricky, 2026-09-29: "for stor forskjell" between the two). */
#calc-hint {
  display: flex; align-items: center; justify-content: center;
  min-height: 38px; margin: 8px 12px; padding: 0 20px; border-radius: 8px;
  background: #e8edf5; color: #5b6b85;
  font-size: 14px; font-weight: 600; text-align: center; white-space: nowrap;
}
#calc-hint.hidden { display: none; }
#calc-box .panel-msg { margin: 0 8px 8px; }

.hidden { display: none; }

@keyframes spin { to { transform: rotate(360deg); } }

.spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(21,101,192,0.25);
  border-top-color: var(--accent-strong);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
  vertical-align: middle;
  margin-right: 6px;
}

#point-sun-spinner.hidden { display: none; }

/* The number, its unit and the warning mark are a row, and the row says who belongs to whom: the number
   and the unit sit on the baseline as they always have, while the mark is centred against the number
   itself. It used to carry vertical-align: middle, which aligns to half the x-height of its PARENT --
   16 px -- so as soon as the number grew to 44 px on a wide screen the mark stayed behind near the
   baseline, 11 px low (Ricky, 2026-10-13: "den varslingen kan flyttes litt opp"). */
.result-headline { display: flex; align-items: baseline; flex-wrap: wrap; --num-size: 28px; }

.result-value {
  font-size: var(--num-size);
  font-weight: 700;
  color: var(--ink);
}

.result-unit { font-size: 13px; color: var(--muted); margin-left: 4px; }
/* The one symbol that stands for "this number rests on defaults". Press it for
   the sentence. Amber, the same family as the detail box it opens. */
.uncertain-btn {
  align-self: center; margin-left: 8px; width: 24px; height: 24px; padding: 0;
  border: 1px solid #e0b64a; border-radius: 50%; background: #fff3cd; color: #8a6100;
  font-size: 13px; line-height: 1; cursor: pointer;
}
.uncertain-btn:hover { background: #ffe9a8; }
.uncertain-btn[aria-expanded="true"] { background: #ffe08a; }
.result-uncertain.hidden { display: none; }

.star-rating {
  position: relative;
  display: inline-block;
  font-size: 18px;
  line-height: 1;
  margin-top: 6px;
}

.star-rating-bg { color: #ddd; }

.star-rating-fg {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  white-space: nowrap;
  color: #e65100;
}

.result-rating-text {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
  margin-bottom: 6px;
}

/* The year's yield, and the area it was multiplied by as a quieter line under it. A wide screen makes the
   yield the second of the two big figures (css/mobile.css); on a phone it stays the size it always was. */
.result-total { margin-top: 2px; font-variant-numeric: tabular-nums; }
.result-total-value { display: block; font-size: 12px; color: #555; }
.result-total-area { display: block; font-size: 11px; color: var(--muted); }

/* The sun dome's box (it was an inline style): a class so a wide screen can give it another height. */
.sun-dome-box { width: 100%; height: 390px; border-radius: 8px; overflow: hidden; }

/* Shown when tilt/azimuth/height/area couldn't be read off the roof at this
   point and fell back to defaults -- same banner treatment as #progress/
   .panel-msg, in amber for "uncertain" rather than blue/red (Ricky,
   2026-09-25: "vise brukeren at det er vanskelig å beregne takets
   muligheter"). js/app.js's buildUncertaintyReasons. */
.result-uncertain a { color: inherit; text-decoration: underline; }
.result-uncertain {
  font-size: 12px; font-weight: 600; color: #8a6100;
  background: #fff3cd; padding: 8px; border-radius: 6px; margin: 6px 0;
}

/* Resultatets tekststørrelser i px, ikke em (design-kritikk #12): 0,9em og 0,85em ga 14,4 og 12,75 px
   og gjorde linjene under «Solberegning» større enn selve tittelen. Skalaen i panelene er nå
   11 / 12 / 13 / 14 / 15 px for tekst, med 15 px/600 for titler. */
/* What the answer rests on. Four chips the user can read but not press, and one button beside them
   (Ricky, 2026-10-13: "«Endre ›» ser ikke ut som en knapp"). The block used to be a single wide button
   holding the values, so the reading matter and the way in were the same thing. */
.result-used { margin-top: 8px; }
.result-used-list { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; }
.result-used-chip {
  display: inline-flex; align-items: baseline; gap: 3px;
  font-size: 12px; color: #4a5568;
  background: #f6f8fb; border: 1px solid #e3e8f0; border-radius: 6px; padding: 4px 8px;
}
.result-used-mark { color: #8a6100; }
/* Amber for "this one is a guess", the same family as the detail box the ⚠ opens. */
.result-used-mark--warn { cursor: help; }
.result-used-btn {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; margin-top: 8px; padding: 0 14px;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--accent);
  background: #fff; border: 1px solid #c3d2e8; border-radius: 8px; cursor: pointer;
}
.result-used-btn:hover { background: #edf1f7; border-color: #a9bedd; }
.result-used-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.result-used-btn[aria-expanded="true"] { background: #e3ecfa; border-color: #b9cdee; }
.result-used-btn-icon { flex: none; }
.result-shade { font-size: 14px; margin-top: 4px; font-variant-numeric: tabular-nums; }
.result-user-shade { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.user-shade-step { width: 32px; height: 32px; border: 1px solid var(--line, #c9d1dc); border-radius: 8px; background: #fff; font-size: 18px; line-height: 1; cursor: pointer; color: inherit; }
.user-shade-step:disabled { opacity: .4; cursor: default; }
.user-shade-value { min-width: 3.2em; text-align: center; font-weight: 600; }

/* Where the numbers came from -- quiet, the last line of the result. */
.result-sources { font-size: 11px; color: var(--muted-blue); margin-top: 10px; }
.result-scope-note { margin-top: 4px; line-height: 1.4; }
/* Under the left column's figures, in reading size: it says what the sun window and the yearly average rest on. */
.result-sun-scope { font-size: 13px; line-height: 1.45; color: var(--ink); margin: 12px 0 0; }
.result-sun-year { font-size: 13px; margin-top: 8px; font-variant-numeric: tabular-nums; }
.result-uncertain ul { margin: 4px 0 0 18px; padding: 0; font-weight: 500; }
.result-uncertain li { margin: 2px 0; }

.section-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-top: 14px;
  margin-bottom: 2px;
}

/* Twelve stacked bars. Full height = what the month could give with no shade at
   all; from the bottom up: the sun that arrives (the month's colour, shared with
   the dome and the shadow ring), then the shade (buildings, trees and terrain
   together, one tone; Ricky 2026-10-01: two categories, Sol and Skygge). */
.month-bars { display: flex; align-items: stretch; gap: 4px; height: 130px; margin: 12px 0 2px; }
.month-bar { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.month-bar-track { position: relative; flex: 1; display: flex; align-items: flex-end; }
.month-bar-stack { width: 100%; display: flex; flex-direction: column; border-radius: 3px 3px 0 0; overflow: hidden; }
.month-bar-seg { min-height: 1px; transition: opacity 0.12s; }
.month-bar-seg--shade { background: #8b909b; }
/* The month in focus (from the chart or from the dome) stays full; the rest recede. */
.month-bars.has-active .month-bar:not(.is-active) .month-bar-seg { opacity: 0.3; }
.month-bar.is-active .month-bar-seg { filter: brightness(1.08); }
.month-bar-letter { font-size: 10px; color: var(--muted-blue); text-align: center; margin-top: 3px; }
.month-bar-share { font-size: 9px; color: var(--muted-blue); text-align: center; font-variant-numeric: tabular-nums; }
.month-bars-key { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; color: #33415a; margin-top: 8px; }
.month-bars-key span { display: inline-flex; align-items: center; gap: 6px; }
.month-key-swatch { display: inline-block; flex: none; width: 16px; height: 16px; border-radius: 3px; }
/* Sol-bitene er farget etter måned (samme farger som i kuppelen), så fargeruta
   er en rad med harde striper, ikke en glatt overgang. Glatt gradient i 10 px
   leste som en uskarp flekk (Ricky, 2026-10-01). */
.month-key-swatch--sun { width: 28px; background: linear-gradient(90deg, #5e35b1 0 25%, #2e8bc0 25% 50%, #2aa198 50% 75%, #e65100 75%); }
.month-key-swatch--shade { background: #8b909b; }
.month-bars-caption { font-size: 11px; color: var(--muted-blue); margin-top: 4px; }

#result-content { position: relative; }

.result-tooltip {
  position: absolute;
  z-index: 20;
  background: var(--ink);
  color: white;
  font-size: 11px;
  line-height: 1.5;
  padding: 6px 9px;
  border-radius: 6px;
  pointer-events: none;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
}

@media (max-width: 580px) {
  #left-column { left: 10px; right: 10px; width: auto; }
  #result-panel, #underlay-panel { left: 10px; right: 10px; top: 240px; width: auto; transform: none; }
  #info-panel { left: 10px; right: 10px; top: 240px; width: auto; }
}

/* Buildings the user draws ("hva om naboen bygger"). Grey, never orange: orange is
   reserved for direction. */
/* Its own rules, not .shadow-refresh-btn's: there, :disabled means "loading" and spins the
   icon, which is what this button did once nine boxes had been drawn (Ricky, 2026-09-30). */
.building-add-btn {
  flex: none; width: 34px; height: 34px; padding: 0;
  display: flex; align-items: center; justify-content: center; border-radius: 50%;
}
.building-add-btn:disabled { opacity: 0.45; cursor: not-allowed; animation: none; }
.building-add-btn.is-far { opacity: 0.45; cursor: default; }
.building-list { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; }
.building-list:empty { display: none; }
/* One small pill per building, several to a line: a list with a row each took a line of
   the panel for every box drawn (Ricky, 2026-09-30). */
.building-row {
  display: flex; align-items: center; gap: 2px; padding: 2px 3px; border-radius: 8px;
  background: #f6f8fb; border: 1px solid transparent; font-size: 11px; cursor: pointer;
}
.building-row.is-selected { border-color: #9aa0a6; background: #eef0f3; }
.building-row.is-off { opacity: 0.6; }
/* The grey square stands for the box on the map: a building needs no name, and this is
   what you press to pick it. */
.building-row-swatch { flex: none; width: 12px; height: 12px; padding: 0; background: #9aa0a6; border: 2px solid #5f6368; border-radius: 2px; cursor: pointer; }
.building-row-height { width: 32px; padding: 1px 3px; font: inherit; font-size: 12px; border: 1px solid #ccc; border-radius: 6px; text-align: right; appearance: textfield; -moz-appearance: textfield; }
/* The spin arrows took 15 px of a 32 px field and cut the third digit off a 999. */
.building-row-height::-webkit-inner-spin-button, .building-row-height::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.building-row-unit { color: var(--muted-blue); }
/* Etasjer: en avlesning, ikke en kontroll, så den er dempet og tar ikke imot trykk. */
.building-row-storeys { color: var(--muted-blue); font-size: 11px; white-space: nowrap; margin-left: 2px; }
.building-row-storeys[hidden] { display: none; }
.building-row-calc { position: relative; flex: none; border: 0; background: none; font-size: 14px; line-height: 1; color: #b26b00; cursor: pointer; padding: 0 2px; }
/* ☀: #e08a00 gav 2,5:1 på pillen; #b26b00 gir 3,7:1 og beholder sol-fargen (design-kritikk #10). */
.building-row-calc:hover { color: #8a4f00; }
.building-row-on { flex: none; cursor: pointer; margin: 0; }
.building-row-delete { position: relative; flex: none; border: 0; background: none; font-size: 15px; line-height: 1; color: #666; cursor: pointer; padding: 0 2px; margin-left: 4px; }
/* The pill is small on purpose (Ricky, 2026-09-30), but × deletes at once and sat 1-2 px from
   the tick; the hit areas of ☀ and × grow by pseudo-elements without changing the look
   (design review #19, WCAG 2.5.8). */
.building-row-calc::after, .building-row-delete::after { content: ''; position: absolute; inset: -6px -3px; }
/* A thin white halo round the coloured edge, so it reads against every map layer: the
   Topokart draws its buildings blue, and the terrain layers are green and brown. */
.building-rect { cursor: move; filter: drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 1px #fff); }
.building-handle { background: #fff; border: 2px solid #5f6368; box-sizing: border-box; }
.building-handle--corner { cursor: nwse-resize; }
.building-handle--rotate { border-radius: 50%; cursor: grab; }
.result-drawn { color: #5f6368; }

/* Spinners are needed to show that something is happening, so they slow down under
   prefers-reduced-motion instead of stopping (design review #21). */
@media (prefers-reduced-motion: reduce) {
  .shadow-refresh-btn:disabled { animation-duration: 2.4s; }
  .spinner { animation-duration: 2.4s; }
}

/* ---- The date and clock sliders: two horizontal tracks at the bottom (Ricky, 2026-10-15, issue #6) ----
   Shown with the shade (js/shadow-panel.js), centred along the bottom edge, at most 560 px wide, over the map's credit line.
   The ring and the half-arc they replace stay in the page, hidden, and keep their state. css/mobile.css lifts the container
   above the result sheet and the stack of texts. The clock is the lower, the date the upper; each is one 44 px high zone
   you can press anywhere, with the track inset by half a thumb so the thumb never leaves the zone. The container itself lets
   the map through. Over the maps (1, 5), under Underlag (8), Beregn (9) and Info/Metode (10). */
#mobile-sliders {
  position: fixed; z-index: 6; left: 0; right: 0; margin-inline: auto;
  width: min(560px, calc(100% - 40px)); height: 92px; bottom: 32px;
  pointer-events: none;
}
.hslider {
  position: absolute; left: 0; right: 0; height: 44px;
  pointer-events: auto; touch-action: none; user-select: none; -webkit-user-select: none;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.hslider--date { top: 0; }
.hslider--time { top: 48px; }
.hslider:focus { outline: none; }
.hslider:focus-visible .hslider-thumb { box-shadow: 0 0 0 3px var(--focus); }
/* The track: the stretch the thumb runs along, half a thumb in from each end of the zone (js/slider-math.js SLIDER_TRACK_INSET). */
.hslider-track { position: absolute; left: 14px; right: 14px; top: 0; bottom: 0; }
.hslider-bar {
  position: absolute; left: 0; right: 0; top: 8px; bottom: 8px; border-radius: 14px; overflow: hidden;
  background: rgba(255, 255, 255, 0.95); box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
}
/* The clock's bar: the arc's own grey-gold-grey (sunrise on the left). */
.hslider-bar--time { background: linear-gradient(to right, #8b98ab, #e5a400 50%, #8b98ab); }
.hslider-seg { position: absolute; top: 0; bottom: 0; background: var(--month-color); opacity: 0.35; border-right: 1px solid #fff; box-sizing: border-box; }
.hslider-seg.is-active { opacity: 1; }
.hslider-month {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  font-size: 9px; line-height: 1; font-weight: 600; color: var(--ink); pointer-events: none;
}
.hslider-month.is-active { font-weight: 800; }
.hslider-thumb {
  position: absolute; top: 50%; width: 28px; height: 28px; margin: -14px 0 0 -14px;
  border-radius: 50%; background: #fff; border: 3px solid var(--ink); box-sizing: border-box; pointer-events: none;
}
.hslider-thumb--time { border-color: #e5a400; }
.hslider-tick { position: absolute; top: 50%; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: #8b98ab; pointer-events: none; }
.hslider-tick--noon { background: #e5a400; }
.hslider-tick.hidden { display: none; }
/* The bubble over the finger: the value of the slider being dragged, over both bars (so neither the finger nor the thumb hides
   it), centred on the thumb by script. Hidden until a drag starts, and again when the finger is lifted. */
.hslider-label {
  position: absolute; bottom: calc(100% + 10px); transform: translateX(-50%); height: 36px; line-height: 36px; padding: 0 16px;
  border-radius: 18px; background: rgba(255, 255, 255, 0.98); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
  font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink);
  white-space: nowrap; pointer-events: none; user-select: none; -webkit-user-select: none;
  visibility: hidden;
}
.hslider-label.is-dragging { visibility: visible; }
#hslider-time-label { --pill-color: #e5a400; }
/* A dot in the bar's own colour ties the bubble to its bar: the month's colour for the date (set per step in js/shadow-panel.js), gold for the clock. */
.hslider-label::before {
  content: ''; display: inline-block; width: 10px; height: 10px; margin-right: 8px; border-radius: 50%;
  background: var(--pill-color, transparent); vertical-align: middle;
}
/* Sunrise and sunset in the two ends of the clock bar, no pill, so a busy map has to be read through the text itself:
   dark ink, semi-bold, and a white halo on all sides. */
.hslider-end {
  position: absolute; top: 50%; transform: translateY(-50%); font-size: 11px; line-height: 14px; font-variant-numeric: tabular-nums;
  color: var(--ink); font-weight: 600;
  text-shadow: 0 0 2px #fff, 0 0 2px #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 1px 0 #fff, 0 -1px 0 #fff;
  white-space: nowrap; pointer-events: none; user-select: none; -webkit-user-select: none;
}
.hslider-end--rise { left: 10px; }
.hslider-end--set { right: 10px; }


/* The small signature in the bottom left corner (the time is when the page was last deployed). Under every panel, and takes no touches. */
#watermark {
  position: fixed; left: 8px; bottom: calc(env(safe-area-inset-bottom, 0px) + 3px); z-index: 2; font-size: 10px; line-height: 1.2;
  color: rgba(40, 40, 40, 0.55); text-shadow: 0 0 3px rgba(255, 255, 255, 0.9); pointer-events: none; user-select: none;
}
