/* ruum — the design language, written once.
   =========================================================================

   Loaded by the public pages and by the internal browser's base template,
   after `ruum.css` (which owns the colours) and `fonts.css` (which owns the
   faces). This file owns everything else: the type scale, the two label
   registers, the rules that do the grid work, and the handful of components
   that appear on both sides of the login.

   Before it, `.btn`, `.mark`, `.wordmark` and the whole label register were
   written twice -- once in `web/index.html` and once inside a `<style>` block
   in `src/web/templates/base.html`. They had not drifted yet, but the landing
   page's button was 18px/34px and the app's was 14px/15px, which is the same
   component at two sizes rather than two components, and nothing said so.

   ------------------------------------------------------------- the rules

   Corners are square and there are no shadows. Depth is done with rules, and
   rules come in exactly two weights, which is the whole grammar of the page:

     2px `--rule`   structural. Band boundaries, the masthead, the edge of a
                    panel that is the subject of the page. It bleeds to the
                    viewport; the text inside it does not.
     1px `--line`   incidental. Row separators, column dividers, the edge of
                    something that is merely a box.

   A third weight, or a 2px `--line`, reads as a mistake. If a boundary needs
   more presence, it is structural and takes `--rule`.

   ------------------------------------------------------- the two registers

   Prose is Archivo. Every figure -- price, mileage, count, percentage, the
   spread -- is IBM Plex Mono with tabular figures, via `.n`. This is not a
   stylistic preference: the browse table puts prices in a column, and a
   proportional face makes that column ragged and makes a number read as a
   word. `.mono-caps` is the third thing the mono face does: 11px uppercase
   with wide tracking, used for every eyebrow, facet label and nav item, and
   it is the only uppercase on the page apart from the hero.               */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Links are ink with a brand underline. Orange is legible as a 2px rule at
   any size and fails AA as 16px text, so this is the one way the identity
   colour is allowed near running prose. */
a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--brand);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

:where(input, select, button, textarea) { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }
::selection { background: var(--brand); color: var(--brand-ink); }

/* ------------------------------------------------------------- type scale
   Six sizes and no more. The landing page previously ran 19/17/15.5/15/14/13
   for body copy -- close enough that they read as noise rather than
   hierarchy, which was most of what "bland" meant. */

h1, h2, h3 { margin: 0; font-weight: 800; text-wrap: balance; }

.h-hero {
  /* 46px min rather than 52: at a 320px viewport "AUTO SKUP?" at 52px
     overruns the measure and puts a horizontal scrollbar on the narrowest
     phones. The line break is authored in the markup, so no `text-wrap`
     here -- the two would fight over the same line. */
  font-size: clamp(46px, 11vw, 112px);
  line-height: .9;
  letter-spacing: -.05em;
  text-transform: uppercase;
  text-wrap: initial;
}
.h-page {
  font-size: clamp(30px, 5.4vw, 52px);
  line-height: 1.02;
  letter-spacing: -.04em;
}
.h-sect {
  font-size: clamp(26px, 4.2vw, 40px);
  line-height: 1.04;
  letter-spacing: -.035em;
}
h3, .h-box { font-size: 17px; line-height: 1.3; letter-spacing: -.02em; }

.lede  { font-size: 19px; line-height: 1.5; color: var(--muted); margin: 0; max-width: 44ch; }
.sub   { font-size: 17px; line-height: 1.55; color: var(--muted); margin: 0; max-width: 60ch; }
.fine  { font-size: 13px; line-height: 1.6; color: var(--faint); margin: 0; }
.lede strong, .sub strong { color: var(--ink); font-weight: 700; }

/* -------------------------------------------------------- label registers */

/* `.eyebrow` is the name the app templates already used for this; both are
   kept so neither side has to be renamed to read the same. */
.mono-caps, .eyebrow {
  font: 600 11px/1.3 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* A figure. Tabular so columns of them line up. */
.n {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* The numbered eyebrow that opens a section, with its 8px brand rule. */
.section-num {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  color: var(--brand);
  font: 600 11px/1.3 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.section-num::before {
  content: "";
  width: 32px;
  height: 2px;
  background: var(--brand);
  flex: none;
}

/* ---------------------------------------------------------------- measure */

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 28px; }
@media (max-width: 620px) { .wrap { padding: 0 18px; } }

/* A band is a full-width row whose top rule bleeds to the viewport while the
   text inside stays on the measure. Real elements rather than `100vw`, which
   counts the scrollbar and puts a horizontal scroll on the page. */
.band { border-top: 2px solid var(--rule); }
.band > .wrap { padding-top: 60px; padding-bottom: 60px; }

/* Heading left, content right. The variation between sections is in what
   sits in the right column, never in the column widths. */
.split { display: grid; grid-template-columns: 1fr 1.25fr; gap: 44px; }
@media (max-width: 860px) { .split { grid-template-columns: 1fr; gap: 28px; } }

/* ------------------------------------------------------------- utilities */

/* The only texture the design allows: fine grid paper, masked so it fades out
   rather than ending on a hard edge. Decorative, so it is always on an
   `aria-hidden` element behind the content. */
.grid-paper {
  background-image:
    linear-gradient(to right, color-mix(in oklab, var(--line) 60%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in oklab, var(--line) 60%, transparent) 1px, transparent 1px);
  background-size: 28px 28px;
}

/* A link that fills with brand on hover instead of changing colour. Used
   where links are a list rather than part of a sentence. */
.link-rule { transition: background-color 120ms ease; }
.link-rule:hover {
  background: var(--brand);
  color: var(--brand-ink);
  text-decoration-color: transparent;
}

/* A table of numbers has a width below which it stops being a table, and a
   phone is under it. Rather than reflow the columns into stacked cards --
   which loses the one thing a table is for, reading down a column -- the table
   keeps its shape and the box around it scrolls sideways.

   Declared here because five screens had declared it for themselves: admin,
   model, model_build, model_compare and promet each carried the identical
   `.scroll { overflow-x: auto }`, which is how `detail`'s peers table came to
   be the one wide table with no box around it at all. */
.scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  /* Without this a grid or flex parent sizes the box to the table's
     min-content width instead of to the space on screen, and the scroll never
     engages -- the whole page widens instead. */
  max-width: 100%; min-width: 0;
}

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
.rise { animation: rise 620ms cubic-bezier(.2, .7, .2, 1) both; }

/* One entrance animation, and it is the first thing to go. Anything that
   moves is suppressed wholesale rather than per-rule, so a component added
   later cannot forget to opt in. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------ components */

.mark {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  background: var(--brand);
  color: var(--brand-ink);
  font: 700 13px/1 var(--mono);
  flex: none;
}
.mark.sm { width: 20px; height: 20px; font-size: 10px; }
.wordmark { font-weight: 800; font-size: 19px; letter-spacing: -.04em; }

.brand {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; color: var(--ink);
}
.brand:hover { background: none; }

.card { background: var(--panel); border: 1px solid var(--line); }
/* A panel that is the subject of its page, rather than one item among many. */
.panel { background: var(--panel); border: 2px solid var(--rule); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px;
  border: 2px solid var(--rule);
  background: var(--accent); color: var(--accent-ink);
  font-size: 15px; font-weight: 700; letter-spacing: -.01em;
  text-decoration: none; cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
/* Hover was `brightness(1.08)` on a black fill, which is invisible -- the
   button had no hover state in light mode at all. Orange is the identity
   colour doing the one job it is allowed to do at this size: a fill. */
.btn:hover { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }
.btn.lg { padding: 17px 30px; font-size: 17px; }
.btn.sm { padding: 6px 12px; font-size: 13px; }
.btn.ghost { background: transparent; color: var(--ink); }
.btn.ghost:hover { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }
.btn.block { width: 100%; }

.linkbtn {
  border: 0; background: none; color: var(--muted); cursor: pointer;
  font-size: 13px; padding: 0; text-decoration: underline;
  text-decoration-color: var(--brand); text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
.linkbtn:hover { color: var(--ink); }

/* Pills are labels, not prose, so they take the monospace register the rest
   of the numeric layer uses. Deliberately no smaller box and no uppercase:
   the verdict pill sits in a fixed column on the browse card next to as many
   as five flag pills, and any extra advance width wraps it. */
.pill {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  padding: 3px 9px;
  border: 1px solid var(--line);
  background: var(--sunk); color: var(--muted);
  font: 600 12px/1.35 var(--mono);
  font-variant-numeric: tabular-nums;
}
.pill.cheap { border-color: var(--cheap); background: var(--cheap-wash); color: var(--cheap); }
.pill.dear  { border-color: var(--dear);  background: var(--dear-wash);  color: var(--dear); }
.pill.warn  { border-color: var(--warn-line); background: var(--warn-bg); color: var(--warn-ink); }
.cheap-ink { color: var(--cheap); }
.dear-ink  { color: var(--dear); }
.fair-ink  { color: var(--fair); }

input[type=text], input[type=number], input[type=search],
input[type=email], input[type=password], select, textarea {
  width: 100%;
  padding: 8px 11px;
  border: 2px solid var(--line);
  background: var(--panel); color: var(--ink);
  font-family: var(--mono); font-size: 13px;
  font-variant-numeric: tabular-nums;
}
input:focus, select:focus, textarea:focus { border-color: var(--rule); }
input::placeholder { color: var(--faint); }

/* 16px is not a taste choice: Safari on iOS zooms the page in when a field
   smaller than that takes focus, and it does not zoom back out, so one tap on
   a filter leaves the reader on a page they now have to pan. Only where the
   pointer is coarse -- a desktop mouse gets the denser 13px the panels are
   drawn for. Height comes with it, which is the other half of the problem:
   these were 33px boxes, under the 44px a thumb needs. */
@media (pointer: coarse) {
  /* The `:not()`s are load-bearing twice over. They keep the rule off boxes
     and radios, which do not take a font size and do take a width -- and they
     lift it above the per-page overrides (`.rail input`, `.who form input`)
     that set 12.5px and would otherwise win the cascade from a later sheet.
     A floor this cheap to break is worth stating once, here, rather than
     re-stating in every screen that draws a field. */
  input:not([type=checkbox]):not([type=radio]):not([type=hidden]),
  select:not([hidden]):not([multiple]):not([size]),
  textarea:not([hidden]):not([readonly]):not([disabled]) {
    font-size: 16px; padding: 10px 11px;
  }

  /* 44px is the other half of the same rule: a control a thumb cannot land on
     is as unusable as one that zooms the page. Where the element is a row in a
     flex line -- nav links, the mark -- the height comes from padding, which
     is invisible, rather than from a box that would redraw the design. */
  .btn.sm { min-height: 44px; }
  .navlink { padding: 13px 0; }
  .brand { min-height: 44px; }
  /* Both of these stand alone on their line -- "Poništi sve" in the filter
     bar, "← natrag" at the top of the model screens -- so both are controls
     and both get a control's height. */
  .linkbtn, a.back { display: inline-block; padding: 12px 0; }
  .sitefoot .links a { padding: 6px 0; }
  /* A link that stands on its own line is a control, whatever it is made of,
     and gets the height of one. Links inside a sentence are left alone: there
     is no honest way to make a word in a paragraph 44px tall. */
  a.link-rule { display: inline-block; padding: 10px 0; }
}

code, .code {
  font-family: var(--mono);
  background: var(--sunk);
  border: 1px solid var(--line);
  padding: 2px 6px;
  font-size: 14px;
}

/* The caution note. Not a price verdict, so it takes the warn family and a
   thick left rule rather than any part of the cheap/dear ramp.

   Called `.caution` and not `.note`, which is what it was for about an hour:
   `.note` is the sort of word every page reaches for -- the detail page had
   its own `.note` for the aside in a card header -- and a shared stylesheet
   cannot own a name that generic. It turned two unrelated captions yellow
   before it was renamed. */
.caution {
  border: 1px solid var(--warn-line);
  border-left: 4px solid var(--warn-ink);
  background: var(--warn-bg);
  padding: 14px 16px;
}
.caution .fam { font: 700 12px/1 var(--mono); letter-spacing: .04em; color: var(--warn-ink); }
.caution p { margin: 7px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink); }

/* ------------------------------------------------------------ site chrome
   The public masthead. Translucent with a blur so the grid paper behind the
   hero shows through as the page scrolls under it, but backed by an opaque
   fallback first: `backdrop-filter` is the one property here that silently
   does nothing on older engines, and without the fallback the nav would sit
   on bare page. */

.masthead {
  position: sticky; top: 0; z-index: 40;
  background: var(--bg);
  background: color-mix(in oklab, var(--bg) 95%, transparent);
  border-bottom: 2px solid var(--rule);
}
@supports (backdrop-filter: blur(8px)) {
  .masthead { backdrop-filter: blur(8px); }
}
/* The same height as the signed-in `.topbar`, and the same mark inside it.
   They were 60px and 52px, so signing in nudged the whole page up by eight
   pixels and shrank the mark -- on the one navigation people cross most
   often, which made it read as two different sites rather than two states of
   one. `--chrome-h` is the total including the 2px rule, and browse.html's
   sticky rail is pinned to the same token rather than to a repeated 52. */
.masthead .top {
  display: flex; align-items: center; gap: 12px;
}
.masthead nav { margin-left: auto; display: flex; align-items: center; gap: 24px; }

/* A nav item is a label, and the current one is underlined with a brand rule
   drawn inside the box so it does not shift the row. */
.navlink {
  color: var(--faint); text-decoration: none;
  transition: color 120ms ease;
}
.navlink:hover { color: var(--ink); background: none; }
.navlink[aria-current="page"] {
  color: var(--ink);
  box-shadow: inset 0 -2px 0 var(--brand);
}

/* Below 700px the nav moves to its own scrolling strip under the masthead,
   so the site stays one connected thing instead of collapsing into a
   hamburger that hides three links. */
/* Both selectors carry `.masthead` on purpose: `.masthead nav` above already
   sets `display: flex`, and a bare `.narrow-nav` loses to it on specificity --
   which showed up as the small-screen strip sitting under the desktop nav at
   every width. */
.masthead .wide { display: flex; }
.masthead .narrow-nav { display: none; }
@media (max-width: 700px) {
  .masthead .wide { display: none; }
  .masthead .narrow-nav {
    display: flex; gap: 18px; overflow-x: auto;
    border-top: 1px solid var(--line);
    padding: 10px 28px;
    margin: 0 -28px;
    -webkit-overflow-scrolling: touch;
  }
  .narrow-nav .navlink { white-space: nowrap; }
  .narrow-nav .navlink[aria-current="page"] { color: var(--brand); box-shadow: none; }
}
/* `.masthead` again, for the same reason the two rules above carry it: the
   700px block sets the strip's padding through `.masthead .narrow-nav`, so a
   bare `.narrow-nav` here loses on specificity and the -28px bleed stayed
   while `.wrap` narrowed to 18px -- which put the strip 10px past the right
   edge of every public page below 620px. */
@media (max-width: 620px) {
  .masthead .narrow-nav { padding: 10px 18px; margin: 0 -18px; }
}

.sitefoot { border-top: 2px solid var(--rule); padding: 40px 0 56px; }
.sitefoot .cols { display: grid; grid-template-columns: 1fr auto; gap: 32px; }
@media (max-width: 700px) { .sitefoot .cols { grid-template-columns: 1fr; } }
.sitefoot .links {
  display: grid; grid-template-columns: repeat(2, auto); gap: 10px 40px;
  font-size: 15px; font-weight: 600; align-content: start;
}
@media (min-width: 701px) { .sitefoot .links { text-align: right; } }

/* Every page ends pointing at the next one, so no route is a dead end. */
.nextup {
  display: grid; grid-template-columns: auto 1fr; gap: 24px;
  align-items: baseline;
  border-top: 2px solid var(--rule);
  padding: 40px 0;
  text-decoration: none;
  transition: background-color 120ms ease;
}
.nextup:hover { background: var(--sunk); }
@media (max-width: 700px) { .nextup { grid-template-columns: 1fr; gap: 8px; } }
.nextup .to {
  font-size: clamp(22px, 3.4vw, 34px); font-weight: 800;
  line-height: 1.05; letter-spacing: -.035em;
}
.nextup .arrow { display: inline-block; margin-left: 12px; transition: transform 120ms ease; }
.nextup:hover .arrow { transform: translateX(4px); }

/* -------------------------------------------------------------- app chrome
   Narrower and denser than the public masthead: this one is looked at all
   day. `--panel` rather than `--bg` so the app reads as a tool sitting on the
   page rather than as more page. */

.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 0 18px;
  height: var(--chrome-h);
  background: var(--panel);
  /* Structural, so it takes `--rule` -- the same 2px bar that separates the
     bands on the landing page. box-sizing keeps the thicker border inside the
     box, so the height above is the total. */
  border-bottom: 2px solid var(--rule);
  position: sticky; top: 0; z-index: 30;
}
/* The masthead carries its rule on itself rather than on this row, so the row
   is short by exactly that and the two chromes come out the same total. */
.masthead .top { height: calc(var(--chrome-h) - 2px); }
.topbar .mark, .masthead .mark { width: 24px; height: 24px; font-size: 11px; }
.topbar .wordmark, .masthead .wordmark { font-size: 17px; }
/* The nav lives inside a `<details>` so the phone can put it behind a button.
   On a desktop that element is open and does nothing: the row of links is the
   row of links it always was. */
.topbar .menu { margin-left: auto; display: flex; }
.topbar .menu-toggle { display: none; }
.topbar nav { display: flex; align-items: center; gap: 22px; }
.topbar .who { font-family: var(--mono); font-size: 12px; color: var(--faint); }
.topbar form { margin: 0; display: flex; }
.private {
  font: 600 9px/1 var(--mono); letter-spacing: .13em; text-transform: uppercase;
  color: var(--faint); border: 1px solid var(--line); background: var(--sunk);
  padding: 5px 7px;
}
/* The address used to be hidden here, because it was competing for room in a
   one-row bar. It is in the menu panel now, where an account line is the
   ordinary thing to find, so only the badge goes. */
@media (max-width: 700px) {
  .topbar .private { display: none; }
}
/* Below 900px the nav goes behind a button and drops as a panel under the bar.
   Six links, an address and a way out do not fit beside a wordmark at 360px --
   a single row of them was dragging every app page out to 644px wide, and the
   scrolling strip that replaced it cut the last link in half, which is a menu
   that hides things while looking like it does not. The bar stays one row and
   stays pinned, because a 52px bar with the whole nav in it is the thing a
   phone expects at the top of a screen. 900 and not 700: the operator's six
   links did not fit a tablet at 768 either. */
@media (max-width: 900px) {
  /* The panel is positioned against this. The right gutter comes off the bar
     and goes inside the button instead: a 44px target with 18px of air around
     the glyph puts its edge exactly where the mark's edge is on the left, and
     without pulling the button out of the bar with a negative margin. */
  .topbar { position: sticky; padding-right: 4px; }
  .topbar .menu { position: static; }
  .topbar .menu-toggle {
    display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    list-style: none; cursor: pointer; color: var(--ink);
    font: 400 20px/1 var(--sans);
  }
  .topbar .menu-toggle::-webkit-details-marker { display: none; }
  /* Three bars, then a cross. The glyphs carry the state, so the button needs
     no label to change and no icon to load. */
  .topbar .menu-toggle::after { content: "\2630"; }
  .topbar .menu[open] .menu-toggle::after { content: "\00d7"; font-size: 26px; }
  /* The page behind an open menu dims, which is how a phone says the thing in
     front is modal and that tapping away will close it -- which it does, from
     the handler in _chrome.html. Fixed rather than absolute so it covers the
     whole page and not just the part of it the bar happens to sit on. */
  .topbar .menu[open]::before {
    content: ""; position: fixed; inset: var(--chrome-h) 0 0;
    background: color-mix(in oklab, var(--ink) 34%, transparent);
    z-index: 28;
  }
  .topbar .menu > nav {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 6px 18px 14px;
    background: var(--panel); border-bottom: 2px solid var(--rule);
    /* Above the page, and above the filter bar that pins under this one. */
    z-index: 29;
  }
  .topbar .menu > nav .navlink {
    padding: 14px 0; border-bottom: 1px solid var(--line);
  }
  /* The underline is drawn on the bottom of the link's box; in a stacked list
     that box has a rule of its own underneath, and two lines under one word
     read as a mistake. Colour says the same thing, which is what the public
     strip already does. */
  .topbar .menu > nav .navlink[aria-current="page"] {
    color: var(--brand); box-shadow: none;
  }
  .topbar .menu > nav .who { padding: 14px 0 10px; font-size: 12px; }
  .topbar .menu > nav .signout .btn { width: 100%; }
}

/* ------------------------------------------------- the sigma position bar
   One drawing, two sizes, used on the browse card and on the detail page so
   the two read identically -- and identically to the extension, which draws
   the same -2.5..+2.5 track. The gradient is the verdict ramp, so where the
   tick sits and what colour is under it always agree. */

.track {
  position: relative; height: 6px; overflow: visible;
  background: linear-gradient(90deg,
    var(--cheap) 0%, var(--cheap) 12%,
    var(--deep) 42%, var(--deep) 58%,
    var(--dear) 88%, var(--dear) 100%);
  /* The middle of the ramp is `--deep`, 1.33:1 against the panel it sits on,
     so without an edge the bar reads as two coloured stubs with a hole
     between them instead of one axis. An inset hairline draws the whole
     track without changing its height the way a border would. */
  box-shadow: inset 0 0 0 1px var(--line);
}
.track .mid {
  position: absolute; left: 50%; top: -3px; bottom: -3px; width: 1px;
  background: var(--panel); opacity: .85;
}
.track .tick {
  position: absolute; top: 50%; width: 11px; height: 11px;
  transform: translate(-50%, -50%); background: var(--panel);
  border: 3px solid var(--ink); box-shadow: 0 0 0 2px var(--panel);
}
.track.lg { height: 9px; }
.track.lg .tick { width: 16px; height: 16px; border-width: 4px; }
.scale {
  display: flex; justify-content: space-between; margin-top: 5px;
  font: 500 10px/1 var(--mono); color: var(--faint);
}

/* ---------------------------------------------------------- the estimate
   The panel the extension injects on an ad page, drawn in HTML at the size it
   actually appears. It is the product, so it gets the room -- and it is the
   same drawing on the landing page and on /kako-radi.

   Deliberately not called `.track`: that name belongs to the app's verdict
   ramp above, and these are two different pictures. */

.shot { background: var(--panel); border: 2px solid var(--rule); padding: 20px 24px 24px; }
.shot .head {
  display: flex; align-items: center; gap: 10px;
  padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.shot .head .title { color: var(--faint); }
.figure { display: flex; align-items: baseline; gap: 12px; margin-top: 18px; flex-wrap: wrap; }
.figure .est {
  font: 700 clamp(32px, 5vw, 44px)/1 var(--mono);
  letter-spacing: -.04em; font-variant-numeric: tabular-nums;
}
.figure .chip {
  font: 700 14px/1 var(--mono); padding: 7px 10px;
  background: var(--cheap-wash); color: var(--cheap);
  font-variant-numeric: tabular-nums;
}
.askline {
  margin: 10px 0 0; font: 13px/1.5 var(--mono); color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.gauge { margin-top: 24px; }
.gauge .bar { position: relative; height: 18px; background: var(--sunk); border: 1px solid var(--line); }
.gauge .typical {
  position: absolute; inset: 0 30%; background: var(--deep);
  border-left: 1px solid var(--line); border-right: 1px solid var(--line);
}
.gauge .mid {
  position: absolute; left: 50%; top: -4px; bottom: -4px; width: 2px;
  margin-left: -1px; background: var(--ink);
}
.gauge .peer {
  position: absolute; top: 50%; left: 14.4%; width: 11px; height: 11px;
  margin: -5.5px 0 0 -5.5px; background: var(--panel); border: 2px solid var(--ink);
}
.gauge .pin {
  position: absolute; left: 18%; top: -6px; bottom: -6px; width: 5px;
  margin-left: -2.5px; background: var(--cheap);
}
.gauge .axis {
  display: flex; justify-content: space-between; margin-top: 10px;
  font: 11px/1 var(--mono); color: var(--muted); font-variant-numeric: tabular-nums;
}
.gauge .axis .m { color: var(--faint); font-family: var(--sans); }

/* The figure column is sized to its content and the label column takes what
   is left, not the other way round: on a phone the previous `auto 1fr` gave
   the label all the slack and wrapped "17.000 € · −14,7 %" so the per-cent
   sign landed alone on the next line. A label may wrap; a number may not. */
.rows {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 16px;
  margin: 20px 0 0; padding-top: 16px; border-top: 1px solid var(--line);
  font-size: 13px;
}
.rows dt { color: var(--muted); }
.rows dd {
  margin: 0; text-align: right; white-space: nowrap;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- editorial lists */

/* Three claims separated by rules rather than boxed in cards. */
.three {
  display: grid; grid-template-columns: repeat(3, 1fr);
  margin-top: 48px; padding-top: 28px; border-top: 2px solid var(--rule);
}
@media (max-width: 860px) { .three { grid-template-columns: 1fr; } }
.three .box { padding: 0 26px; border-left: 1px solid var(--line); }
.three .box:first-child { border-left: 0; padding-left: 0; }
.three .box p { margin: 8px 0 0; font-size: 15px; line-height: 1.55; color: var(--muted); }
@media (max-width: 860px) {
  .three .box {
    border-left: 0; border-top: 1px solid var(--line);
    padding: 22px 0 0; margin-top: 22px;
  }
  .three .box:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
}

/* What the product refuses to do, marked with orange bars. Stated plainly
   because a valuation that overclaims is worse than no valuation. */
.nots { list-style: none; padding: 0; margin: 0; }
.nots li {
  padding: 20px 0 20px 20px;
  border-top: 1px solid var(--line);
  border-left: 4px solid var(--brand);
  color: var(--muted); font-size: 15.5px; line-height: 1.55;
}
.nots li strong {
  display: block; color: var(--ink); font-size: 17px; font-weight: 700;
  margin-bottom: 6px; letter-spacing: -.015em;
}

.steps { margin: 0; padding: 0; list-style: none; counter-reset: s; }
.steps li {
  counter-increment: s; position: relative;
  padding: 16px 0 16px 48px;
  border-bottom: 1px solid var(--line);
  color: var(--muted); font-size: 15.5px;
}
.steps li:last-child { border-bottom: 0; }
.steps li::before {
  content: counter(s, decimal-leading-zero);
  position: absolute; left: 0; top: 18px;
  font: 700 12px/1.4 var(--mono); color: var(--brand); letter-spacing: .08em;
}
