/*
 * IWMP design system (see design-system.md and the
 * approved "Parzellenbaum" mockup). A deliberate palette/typography, not
 * stock Bootstrap defaults: Public Sans for UI/body text, IBM Plex Mono for
 * tabular data (dates, numbers), a warm neutral ground instead of
 * Bootstrap's default grey, a muted gold instead of a plain warning yellow
 * for Flaeche/polygon accents (kept distinct from the brand green so drawn
 * shapes read clearly against green UI chrome). requirements.md mandates a
 * light, green-based scheme; no dark-mode branch is needed here - this is a
 * real deployed app under our own control, not a claude.ai Artifact with a
 * viewer-controlled theme.
 *
 * Bootstrap 5.3's compiled CSS bakes per-component colour variables
 * (--bs-btn-bg etc.) rather than referencing --bs-primary/--bs-border-radius
 * throughout, so retheming without a Sass rebuild means overriding the
 * classes we actually use directly, not just the root Bootstrap variables.
 *
 * The :root values below are the core defaults. Each deployment profile
 * loads app/static/profiles/<key>/css/brand.css after this file, which may
 * override the brand (--brand*), typography (--font-*), logo size and
 * navbar (--navbar-*) tokens only - see
 * design-system.md's "Per-profile branding". Everything else here is
 * shared, so a rule that hardcodes a brand colour instead of reading the
 * token silently stays Thurgau-green in every profile.
 */

:root {
  /* Brand colour - green by default (Thurgau's); named for its role, not
   * its hue, since a profile's brand.css may make it anything. */
  --brand: #68a94a;
  --brand-dark: #4f8038;
  /* --brand as bare r, g, b - for the translucent focus rings, which CSS
   * can't derive from a hex token without color-mix(). Keep in sync with
   * --brand in every brand.css that overrides it. */
  --brand-rgb: 104, 169, 74;
  --brand-tint: #eef5e9;
  /* One step deeper than --brand-tint, same hue family - used for the
   * Kulturen body (.baum-kulturen) nested *inside* a Nutzungsfläche box, itself
   * inside a Bewirtschaftungseinheit's already-green-tinted body (.baum-nutzflaechen). Without
   * this, .baum-kulturen used --surface-sunken, which is close enough to
   * --brand-tint in both hue and lightness that the two nesting levels were
   * hard to tell apart at a glance. */
  --brand-tint-deep: #d9ead2;

  /* Neutrals - chosen with a slight warm/green bias, not plain grey */
  --ink: #23261f;
  --ink-soft: #5b6154;
  --ground: #f6f7f2;
  --surface: #ffffff;
  --surface-sunken: #f0f2ea;
  --line: #dfe3d6;
  --line-soft: #ebede4;
  --muted-badge: #9aa08e;

  /* Flaeche/polygon accent (map draw layer, list thumbnails - see
   * app/static/js/geoadmin-map.js, app/betrieb/bwe.py) */
  --amber: #b8860b;
  --amber-tint: #fbf1d9;
  --amber-line: #e4c876;

  /* Betrieb map marker (farm icon) - deliberately distinct from --amber
   * above (that's the Flaeche/polygon accent). Not readable from JS/Python,
   * so kept in sync by hand: baked into app/static/img/betrieb-marker.png
   * (see the generation notes in design-system.md's "Map markers") and used
   * by app/static/js/geoadmin-map.js's betriebMarkerStyle(). */
  --betrieb-marker: #e07b1a;

  /* Chart series palette (app/static/js/telemetrie-chart.js). Six
   * categorical hues for a multi-series line chart on white. Shared across
   * profiles like the marker colours below, and deliberately NOT
   * overridable in a brand.css: a palette derived from --brand would mean
   * "the green line" is a different field in Thurgau than in AgriAqua, so
   * two screenshots of the same data would not be comparable. Kept clear of
   * --brand, --amber and both marker colours, so a chart never borrows a
   * hue that already means something on the map. Six because the picker
   * caps one chart at six series.
   * Unlike the markers, these ARE read from JS (getComputedStyle), so they
   * are not kept in sync by hand - see design-system.md's "Charts". */
  --serie-1: #1b7f79;
  --serie-2: #b5502f;
  --serie-3: #7b3f6b;
  --serie-4: #4f6b2a;
  --serie-5: #8a5a12;
  --serie-6: #556070;

  /* Device map marker - a 5th distinct color, so a located Device
   * doesn't get lost against the Betrieb marker/Bewirtschaftungseinheiten+Nutzungsfläche polygon
   * colors already on screen at once (Betrieb detail view). Not readable
   * from JS/SVG, so kept in sync by hand with
   * app/static/img/device-marker.svg and geoadmin-map.js's
   * deviceMarkerStyle(). */
  --device-marker: #0000ff;

  /* Typography - a profile with its own brand typeface overrides these
   * (and loads the font itself; base.html only loads these two). */
  --font-ui: "Public Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Consolas, monospace;

  /* Height of the logo in the navbar (_nav.html's .navbar-logo). Per
   * profile, because logos come with different amounts of built-in
   * whitespace - a padded raster needs more height to read at the same
   * size as a tightly cropped wordmark. */
  --logo-height: 40px;

  /* Top navbar (_nav.html) - white with ink text by default. Per profile:
   * a profile's brand.css may make it a dark bar (Thurgau does). The user
   * menu's outline button and the bottom border key off these too, so
   * both variants stay legible without template changes. */
  --navbar-bg: var(--surface);
  --navbar-ink: var(--ink);
  --navbar-border: var(--line);

  --shadow: 0 1px 2px rgba(35, 38, 31, 0.06), 0 4px 14px rgba(35, 38, 31, 0.05);
  --radius: 10px;
}

body {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-ui);
}

/* Bootstrap's .navbar keys its link colours off --bs-navbar-* variables, so
 * setting those is enough - no per-link overrides needed. */
.navbar {
  background-color: var(--navbar-bg);
  --bs-navbar-color: var(--navbar-ink);
  --bs-navbar-hover-color: var(--navbar-ink);
  --bs-navbar-active-color: var(--navbar-ink);
  --bs-navbar-brand-color: var(--navbar-ink);
  --bs-navbar-brand-hover-color: var(--navbar-ink);
  border-bottom: 1px solid var(--navbar-border);
}

/* The user menu toggle (_nav.html) - an outline button in the navbar's own
 * ink, so it reads on a white bar and a dark one alike. */
.navbar .btn-navbar {
  --bs-btn-color: var(--navbar-ink);
  --bs-btn-border-color: var(--navbar-ink);
  --bs-btn-hover-color: var(--navbar-bg);
  --bs-btn-hover-bg: var(--navbar-ink);
  --bs-btn-hover-border-color: var(--navbar-ink);
  --bs-btn-active-color: var(--navbar-bg);
  --bs-btn-active-bg: var(--navbar-ink);
  --bs-btn-active-border-color: var(--navbar-ink);
}

.navbar-logo {
  height: var(--logo-height);
  width: auto;
  display: block;
}

.text-brand {
  color: var(--brand);
}

/* Tabular data - date columns in the Bewirtschaftungseinheit/Nutzungsfläche/Kultur tree
 * (_baum_macros.html), anywhere else numbers need to line up. */
.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.btn-primary {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand-dark);
  --bs-btn-hover-border-color: var(--brand-dark);
  --bs-btn-active-bg: var(--brand-dark);
  --bs-btn-active-border-color: var(--brand-dark);
  --bs-btn-disabled-bg: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
  --bs-btn-focus-shadow-rgb: var(--brand-rgb);
}

.btn {
  border-radius: 7px;
}

/* Cards and tables: same Bootstrap classes used on every page, restyled once
 * here rather than per-template. */
.card {
  background-color: var(--surface);
  border-color: var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.table {
  --bs-table-border-color: var(--line-soft);
  /* Replaces Bootstrap's default grey .table-striped rows (every table in
   * the app uses .table-striped - betriebe/_list_body.html,
   * admin/_liste_body.html) with the same green tint the Bewirtschaftungseinheit tree's
   * boxes use, instead of an unrelated grey. */
  --bs-table-striped-bg: var(--brand-tint);
  background-color: var(--surface);
  color: var(--ink);
}

.form-control,
.form-select {
  border-color: var(--line);
  border-radius: 7px;
}

.form-control:focus,
.form-select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 0.2rem rgba(var(--brand-rgb), 0.15);
}

/* The navbar's user menu (_nav.html) - the one dropdown in the app. Same
 * reason as .card/.table above: Bootstrap 5.3's compiled CSS bakes its own
 * per-component colour variables rather than keying off --bs-primary, so
 * without this the menu renders in stock Bootstrap grey next to the warm
 * neutrals every other surface uses. Hover picks up the same green tint the
 * side menu's .active state and the striped tables already use. */
.dropdown-menu {
  --bs-dropdown-bg: var(--surface);
  --bs-dropdown-color: var(--ink);
  --bs-dropdown-border-color: var(--line);
  --bs-dropdown-link-color: var(--ink);
  --bs-dropdown-link-hover-color: var(--ink);
  --bs-dropdown-link-hover-bg: var(--brand-tint);
  --bs-dropdown-divider-bg: var(--line-soft);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* Checkboxes (map layer-toggle controls - _map_shell.html - are the only
 * ones in the app so far) - Bootstrap's default checked/focus state is blue. */
.form-check-input:checked {
  background-color: var(--brand);
  border-color: var(--brand);
}

.form-check-input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 0.2rem rgba(var(--brand-rgb), 0.15);
}

/* Betrieb detail view's tabs (_detail_body.html) - Bootstrap's default
 * nav-tabs link/active color is blue. */
.nav-tabs .nav-link {
  color: var(--ink-soft);
}

.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus {
  color: var(--brand-dark);
}

.nav-tabs .nav-link.active {
  color: var(--brand-dark);
  border-bottom: 2px solid var(--brand);
}

/* Status badges (Aktuell/Vergangen - see _baum_macros.html's status_badge
 * macro): a dot indicator for "current" rather than Bootstrap's plain
 * subtle-color badge. */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  white-space: nowrap;
}

.status-badge.current {
  background: var(--brand-tint);
  color: var(--brand-dark);
}

.status-badge.current::before {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--brand);
}

.status-badge.past {
  background: var(--surface-sunken);
  color: var(--muted-badge);
}

/*
 * Bewirtschaftungseinheit/Nutzungsfläche/Kultur tree (app/templates/core/_baum_macros.html,
 * betriebe/_detail_body.html) - nested boxes with labeled fields, not a
 * table, per the approved mockup. Classes are prefixed `baum-` (not the
 * mockup's bare `.row`/`.field`/`.actions`) because `.row` in particular
 * would collide with Bootstrap's own grid row class, already used
 * elsewhere for form layout.
 */
.baum-tree {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.baum-bwe {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden; /* clips the green .baum-nutzflaechen body to the same rounded corners */
}

/* Section boxes (.abschnitt) - a titled, optionally collapsible card around a
 * whole section of a tab, first used by the Bewässerung tab's Bezüge and
 * Bezugspunkte (app/templates/core/bewaesserung/_tab.html).
 *
 * Deliberately *not* .baum-bwe reused under another name: these carry
 * the same card treatment (surface, line, radius, shadow) but none of the
 * tree's meaning - no nesting, no green-tinted child body, no grid row - and
 * a future change to how a Bewirtschaftungseinheit looks should not silently restyle a tab
 * section. The shared look lives in the tokens, which is where it belongs.
 */
.abschnitt {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden; /* clips the header's bottom rule to the rounded corners */
}

.abschnitt + .abschnitt {
  margin-top: 1rem;
}

/* The always-visible header: disclosure (optional), title, and whatever
 * controls the section needs. Those controls stay *outside* the collapse on
 * purpose - "Neuer Bezugspunkt" has to be reachable while the section is
 * folded away, which is exactly when a farm has none yet. */
.abschnitt-kopf {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--line-soft);
}

.abschnitt-kopf > .abschnitt-titel {
  margin: 0;
  margin-right: auto;
  font-size: 0.95rem;
  font-weight: 600;
}

.abschnitt-koerper {
  padding: 1rem;
}

/* A section header's filter controls, on one row (the Bewässerung tab's
 * Bezüge). The header itself still wraps, so on a narrow viewport the form
 * drops below the title rather than the controls stacking against each
 * other; `min-width: 0` lets the Bewirtschaftungseinheit/Kultur select shrink instead of
 * pushing the row wider than the card. Below the phone breakpoint it does
 * wrap - one row is a layout goal, not worth a horizontal scrollbar. */
.abschnitt-filter {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.5rem;
}

.abschnitt-filter > select {
  min-width: 0;
  max-width: 18rem;
}

@media (max-width: 575.98px) {
  .abschnitt-filter {
    flex-wrap: wrap;
  }
}

/* "Zurücksetzen" beside a section's filter. --brand-dark, not Bootstrap's
 * .btn-link blue: this app has no blue, and --brand-dark is what every other
 * piece of interactive text on white already uses (.nav-tabs .nav-link,
 * .baum-icon-btn.save, the side menu's active item). */
.filter-reset {
  color: var(--brand-dark);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  padding: 0 0.25rem;
}

.filter-reset:hover {
  color: var(--brand-dark);
  text-decoration: underline;
}

/* Sortable column headers (app/templates/core/_filter_macros.html's sort_kopf,
 * shared by the Erträge and Bewässerung tabs).
 * A <th> link that reads as a header until hovered, with the active column
 * carrying the brand colour and a ▾/▴ marker the template renders. */
.spalte-sort {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}

.spalte-sort:hover {
  color: var(--brand-dark);
}

.spalte-sort.active {
  color: var(--brand-dark);
}

.baum-row {
  display: grid;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 1rem;
}

.baum-row-bwe {
  grid-template-columns: 1.6rem 2.5rem 1.7fr 0.9fr 0.9fr 1fr 1fr auto;
}

.baum-row-nutzflaeche,
.baum-row-teilflaeche {
  grid-template-columns: 1.6rem 2.5rem 1.9fr 1.3fr 0.8fr auto;
}

.baum-row-kultur {
  grid-template-columns: 2.1fr 1.3fr 0.8fr auto;
}

/* Massnahme boxes (app/templates/profiles/tg/_massnahme_macros.html) - same shape as
 * .baum-row-kultur (name-cell, one field, status badge, actions - no
 * disclosure, Massnahmen aren't nested). */
.baum-row-massnahme {
  grid-template-columns: 2.1fr 1.3fr 0.8fr auto;
}

/* Gerät boxes (app/templates/core/_device_macros.html) - same shape as
 * .baum-row-nutzflaeche minus the Fläche thumbnail column (a Device has no
 * shape to preview); Zuordnung rows one level down reuse .baum-row-kultur's
 * own shape exactly (name-cell, one field, status badge, actions). */
.baum-row-device {
  grid-template-columns: 1.6rem 1.9fr 1.3fr 0.8fr auto;
}

.baum-row-zuordnung {
  grid-template-columns: 2.1fr 1.3fr 0.8fr auto;
}

.baum-disclosure {
  width: 1.6rem;
  height: 1.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  border-radius: 6px;
  transition: background 0.15s ease;
}

.baum-disclosure:hover {
  background: var(--surface-sunken);
}

.baum-disclosure svg {
  width: 0.75rem;
  height: 0.75rem;
  transition: transform 0.15s ease;
}

.baum-disclosure[aria-expanded="true"] svg {
  transform: rotate(90deg);
}

.baum-thumb {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 7px;
  background: var(--amber-tint);
  border: 1px solid var(--amber-line);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* A thumbnail with a shape is a <button> that zooms the map to it (see
   map-shell.js's data-zoom-ring handler) - strip the native button look. */
button.baum-thumb {
  padding: 0;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

button.baum-thumb:hover,
button.baum-thumb:focus-visible {
  border-color: var(--amber);
  box-shadow: 0 0 0 2px var(--amber-line);
  outline: none;
}

.baum-thumb.empty {
  background: var(--surface-sunken);
  border-color: var(--line);
}

.baum-thumb svg {
  width: 1.65rem;
  height: 1.65rem;
}

.baum-name-cell {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}

.baum-name-cell .name {
  font-weight: 600;
  font-size: 0.95rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.baum-row-nutzflaeche .baum-name-cell .name,
.baum-row-kultur .baum-name-cell .name {
  font-size: 0.88rem;
}

.baum-name-cell .sub {
  font-size: 0.76rem;
  color: var(--ink-soft);
}

.baum-field {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
}

.baum-field .k {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-badge);
}

.baum-field .v {
  font-size: 0.86rem;
}

.baum-field .v.mono {
  font-size: 0.83rem;
}

.baum-actions {
  display: flex;
  gap: 0.15rem;
  opacity: 0.45;
  transition: opacity 0.15s ease;
}

.baum-row:hover .baum-actions,
.baum-row:focus-within .baum-actions,
.baum-row.editing .baum-actions {
  opacity: 1;
}

.baum-icon-btn {
  width: 1.75rem;
  height: 1.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--ink-soft);
  border-radius: 6px;
  cursor: pointer;
}

.baum-icon-btn:hover {
  background: var(--surface-sunken);
  color: var(--ink);
}

.baum-icon-btn.danger:hover {
  background: #fbeaea;
  color: #b3423a;
}

.baum-icon-btn.save {
  color: var(--brand-dark);
}

.baum-icon-btn svg {
  width: 0.95rem;
  height: 0.95rem;
}

.baum-nutzflaechen {
  background: var(--brand-tint);
  border-top: 1px solid var(--line);
  padding: 0.6rem 0.6rem 0.6rem 2.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.baum-nutzflaeche {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  position: relative;
}

.baum-nutzflaeche::before {
  content: "";
  position: absolute;
  left: -1.15rem;
  top: 1.35rem;
  width: 0.9rem;
  height: 1px;
  background: var(--line);
}

.baum-kulturen {
  background: var(--brand-tint-deep);
  border-top: 1px solid var(--line);
  padding: 0.5rem 0.5rem 0.5rem 2.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.baum-kultur {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
}

/* Teilflächen (decisions/0012-teilflaechen.md) sit where a Nutzungsfläche's
 * Kulturen would - same tinted, indented body as .baum-kulturen, with boxes
 * shaped like .baum-nutzflaeche one level down. */
.baum-teilflaechen {
  background: var(--brand-tint-deep);
  border-top: 1px solid var(--line);
  padding: 0.5rem 0.5rem 0.5rem 2.4rem;
}

.baum-teilflaeche {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: 7px;
}

.baum-empty {
  padding: 1.1rem 1rem;
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-style: italic;
}

/* Telemetry chart pane, inside an expanded Gerät box or Bewirtschaftungseinheit box
 * (app/templates/core/_telemetrie_macros.html,
 * app/static/js/telemetrie-chart.js) - sits below the sub-list it belongs
 * to, on a plain surface (not the tree's green tint) since it isn't
 * another nesting level. See design-system.md's "Charts". */
.telemetrie-pane {
  padding: 0.6rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* The indent is per level, not baked into the pane: a Gerät box nests one
 * step deeper than a Bewirtschaftungseinheit box. Attribute selector for the same reason
 * .baum-disclosure[aria-expanded] uses one - the state is already in the
 * markup, so it needs no second class. */
.telemetrie-pane[data-ebene="geraet"] {
  padding-left: 2.4rem;
}

/* Both wrap: four controls (Felder, Zeitraum, Von, Bis) do not fit one row
 * in a Gerät pane, which is indented a further 2.4rem inside an already
 * narrow #data-pane. */
.telemetrie-kopf {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.telemetrie-steuerung {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.telemetrie-felder-menu {
  max-height: 20rem;
  overflow-y: auto;
}

.telemetrie-felder-menu .dropdown-item {
  display: flex;
  align-items: center;
  cursor: pointer;
}

.telemetrie-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.9rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

.telemetrie-legende-eintrag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

/* The legend swatch is a line segment, not a filled square: colour alone no
 * longer identifies a series now that its line style can be changed too. It
 * is also the button that opens the style popover, so the hit area is padded
 * out towards 24px and pulled back with a matching negative margin, leaving
 * the legend's own layout exactly where it was. The rule is drawn on ::before
 * so it lands in the optical middle of that padding instead of at the
 * button's top edge, and reads currentColor - the series colour stays the one
 * inline literal the script sets, exactly as the filled square's was.
 *
 * border-top-style's dash metrics are the browser's, so the swatch is not
 * pixel-identical to the SVG's stroke-dasharray below. A legend only has to
 * make two lines distinguishable, and this does. */
.telemetrie-legende-farbe {
  display: inline-flex;
  align-items: center;
  width: 1.15rem;
  height: 0.9rem;
  padding: 0.35rem 0.1rem;
  margin: -0.35rem -0.1rem;
  border: 0;
  background: none;
  flex: none;
  cursor: pointer;
}

.telemetrie-legende-farbe::before {
  content: "";
  display: block;
  width: 100%;
  border-top: 2px solid currentColor;
}

.telemetrie-legende-farbe.gestrichelt::before {
  border-top-style: dashed;
}

.telemetrie-legende-farbe.gepunktet::before {
  border-top-style: dotted;
}

/* An amount's swatch is a filled square, like the bars it stands for. */
.telemetrie-legende-farbe.balken::before {
  width: 0.65rem;
  height: 0.65rem;
  margin: 0 auto;
  border-top: 0;
  background: currentColor;
}

.telemetrie-legende-farbe:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

/* Wide enough that the popover is sized by its content rather than by the
 * legend entry it is anchored to. */
.telemetrie-stil-menu {
  min-width: 11rem;
}

.telemetrie-legende-eintrag.leer {
  opacity: 0.55;
}

.telemetrie-chart svg {
  max-width: 100%;
  height: auto;
  /* Dragging a range would otherwise sweep-select the axis tick labels,
   * leaving blue-highlighted text behind after every gesture. Done here
   * rather than with preventDefault() on pointerdown, which would also
   * swallow the click Bootstrap's dropdown needs to auto-close. */
  user-select: none;
}

/* Range selection by dragging across the chart. The invisible catcher
 * spans the plot band and is what pointer events land on; the grey rect is
 * drawn only while a drag is in progress and removed on release.
 * `touch-action: pan-y` keeps a vertical swipe scrolling the page and
 * claims only horizontal drags, which is exactly the axis this gesture
 * reads. */
.telemetrie-chart .telemetrie-auswahl-flaeche {
  fill: none;
  pointer-events: all;
  cursor: crosshair;
  touch-action: pan-y;
}

.telemetrie-chart .telemetrie-auswahl {
  fill: var(--ink-soft);
  fill-opacity: 0.18;
  pointer-events: none;
}

/* Axes, grid and tick text are styled here rather than through D3 .attr()
 * calls, so the "a new rule reads var(--token), never a literal colour"
 * rule covers the chart too. Only a series' own stroke comes from JS, and
 * that reads the --serie-* tokens below. */
.telemetrie-chart .tick text {
  fill: var(--ink-soft);
  font-size: 0.7rem;
}

.telemetrie-chart .tick line {
  stroke: var(--line-soft);
}

.telemetrie-chart .domain {
  stroke: var(--line);
}

.telemetrie-chart .achsen-titel {
  fill: var(--ink-soft);
  font-size: 0.68rem;
}

.telemetrie-chart .serie {
  fill: none;
  stroke-width: 1.5;
}

/* The three line styles the legend's popover offers. The dash values live
 * here rather than in the script for the same reason the axes do: JS sets a
 * series' stroke COLOUR (now user data) and nothing else about how it looks.
 * Tuned for stroke-width 1.5 against a ~560-unit viewBox, where a dasharray
 * unit is about a pixel: 5/3 reads as dashed without collapsing into dots,
 * and a near-zero dash under a round linecap draws a true 1.5 circle every 4
 * units. `0.1` rather than `0`, which a renderer is entitled to drop. */
.telemetrie-chart .serie--durchgezogen {
  stroke-dasharray: none;
}

.telemetrie-chart .serie--gestrichelt {
  stroke-dasharray: 5 3;
}

.telemetrie-chart .serie--gepunktet {
  stroke-dasharray: 0.1 4;
  stroke-linecap: round;
}

/* Amounts (reihe.summe). The colour is the <g>'s fill, set by JS like a
 * line's stroke; a little transparency keeps a line behind a bar legible. */
.telemetrie-chart .serie-balken {
  fill-opacity: 0.8;
}

/* The Gerätemanagement table (device/_verwaltung_liste.html) stripes whole
 * <tbody>s - one per device, its row plus the collapsed telemetry row -
 * where .table-striped would stripe rows inside each one. Same variables
 * Bootstrap's own rule sets, so the --brand-tint override above applies. */
.geraete-tabelle > tbody:nth-of-type(odd) > tr > * {
  --bs-table-color-type: var(--bs-table-striped-color);
  --bs-table-bg-type: var(--bs-table-striped-bg);
}

/* The chart row's pane sits on white, not on the row's stripe. */
.geraete-tabelle .telemetrie-pane {
  background: var(--surface);
}

.telemetrie-meldung {
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-style: italic;
}

/* Inline edit state */
.baum-row.editing {
  background: var(--amber-tint);
  outline: 1px dashed var(--amber-line);
  outline-offset: -1px;
  border-radius: 7px;
}

.baum-row.editing input,
.baum-row.editing select {
  font: inherit;
  font-size: 0.85rem;
  width: 100%;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--ink);
}

.baum-row.editing input[type="date"] {
  font-family: var(--font-mono);
}

/* Sorte's <select> + "type new" fallback stack vertically in
 * .baum-name-cell (see kulturen/_zeile_form.html), same spacing as the
 * cell's own name/sub pairing. */
.baum-row.editing .baum-name-cell select {
  margin-bottom: 0.25rem;
}

/* Filter toolbar (Aktuell/Alle/Zeitraum) above the tree */
.baum-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.baum-filter {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.25rem;
  box-shadow: var(--shadow);
}

.baum-filter a {
  font-size: 0.82rem;
  font-weight: 600;
  border: none;
  background: transparent;
  color: var(--ink-soft);
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}

.baum-filter a:hover {
  color: var(--ink);
}

.baum-filter a.active {
  background: var(--brand);
  color: #fff;
}

@media (max-width: 720px) {
  .baum-row-bwe {
    grid-template-columns: 1.6rem 2.2rem 1fr auto;
  }
  .baum-row-bwe .baum-field {
    display: none;
  }
  .baum-row-nutzflaeche,
  .baum-row-teilflaeche {
    grid-template-columns: 1.6rem 2.2rem 1fr auto;
  }
  .baum-row-nutzflaeche .baum-field,
  .baum-row-teilflaeche .baum-field {
    display: none;
  }
  .baum-row-kultur {
    grid-template-columns: 1fr auto;
  }
  .baum-row-kultur .baum-field {
    display: none;
  }
  .baum-row-massnahme {
    grid-template-columns: 1fr auto;
  }
  .baum-row-massnahme .baum-field {
    display: none;
  }
  .baum-row-device {
    grid-template-columns: 1.6rem 1fr auto;
  }
  .baum-row-device .baum-field {
    display: none;
  }
  .baum-row-zuordnung {
    grid-template-columns: 1fr auto;
  }
  .baum-row-zuordnung .baum-field {
    display: none;
  }
}

/*
 * Side-menu shell: a persistent left menu + a swappable right content pane,
 * the same "shell + htmx-swapped body" shape as #map-pane/#data-pane above,
 * just without a map - nothing here needs Split.js or a live JS object to
 * preserve across navigation, so the shell itself is plain CSS. First built
 * for the Admin section (app/admin/admin_router.py, app/templates/core/admin/),
 * reused as-is by every later section built the same way (Umfragen -
 * app/umfragen/, app/templates/profiles/tg/umfragen/) via these shared classes, not
 * per-section IDs - see requirements.md's "Basic UI Requirements" and
 * architecture.md's "UI Components" section: **any future epic with a
 * left-menu-of-sections + right-content-pane layout must reuse
 * `.side-menu`/`.side-menu-content` on its own menu/content elements
 * instead of writing new CSS**, so this styling (and any future tweak to
 * it) applies everywhere automatically rather than needing to be copied
 * and kept in sync per epic. Each section's own `#<section>-menu`/
 * `#<section>-content` ids stay - they're what htmx targets to swap - the
 * classes are purely for shared styling.
 */
.side-menu {
  width: 220px;
  flex-shrink: 0;
  overflow-y: auto;
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.side-menu .list-group-item {
  border: none;
  border-radius: 7px;
  color: var(--ink-soft);
  font-weight: 500;
}

.side-menu .list-group-item:hover {
  background: var(--surface-sunken);
  color: var(--ink);
}

.side-menu .list-group-item.active {
  background: var(--brand-tint);
  color: var(--brand-dark);
  font-weight: 600;
}

.side-menu-content {
  flex: 1 1 auto;
  overflow-y: auto;
  min-width: 0;
}

/*
 * Split map/data layout (see architecture.md's "Map" section). #split-container
 * fills the space below the navbar; Split.js drives the divider at >=992px
 * (see app/static/js/split-layout.js), below that the panes stack via the
 * media query at the bottom of this block.
 */
#split-container {
  min-height: 0; /* let children shrink/scroll inside a flex parent */
}

#map-pane {
  /* flex-basis must stay `auto` (the "0 0 auto" here) so Split.js's inline
   * `width` (see app/static/js/split-layout.js) actually drives sizing on
   * drag — a fixed flex-basis like `40%` would silently win over `width`
   * per the flexbox spec, making the divider look draggable but do nothing. */
  flex: 0 0 auto;
  min-height: 320px;
  position: relative; /* anchors #karten-layer-button/#karten-layer-panel */
}

#map {
  height: 100%;
  width: 100%;
}

/* Single map-layer control (see app/static/js/map-shell.js's
 * setLayerControlVisible) - this app's own entity overlay toggles
 * (Betriebe/Bewirtschaftungseinheiten/Nutzungsflächen/Geräte) together with the Core Epic's Layer
 * selection (basemap/overlay/transparency), one button+panel, top-right.
 * Lives here (not in a body partial) because #map-pane is outside the
 * htmx-swapped region — see architecture.md's Map section. */
#karten-layer-button {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 1;
  background: rgba(255, 255, 255, 0.9);
}

#karten-layer-panel {
  position: absolute;
  top: 2.75rem;
  right: 0.5rem;
  z-index: 1;
  width: 220px;
  background: rgba(255, 255, 255, 0.95);
  /* "Bewirtschaftungseinheiten" outgrew the 220px panel at body size. Small
   * like the panel's own "Basiskarte"/"Overlay" labels (.small), and allowed
   * to wrap should a profile's font run wider still. */
  font-size: 0.8rem;
}

#karten-layer-panel .form-check-label {
  overflow-wrap: anywhere;
}

#data-pane {
  flex: 1 1 auto;
  overflow-y: auto;
}

.gutter {
  background-color: var(--line);
  background-repeat: no-repeat;
  background-position: 50%;
}

.gutter.gutter-horizontal {
  cursor: col-resize;
}

@media (max-width: 991.98px) {
  #map-pane {
    flex: 0 0 auto;
    height: 45vh;
  }

  #data-pane {
    flex: 0 0 auto;
  }
}
