/* Leihnachbar — supply-side app components (auth, wizard, dashboard, lend).
   Built on the same design tokens as site.css. */

.container-narrow{max-width:var(--layout-max-narrow);margin:0 auto;padding:0 var(--layout-gutter)}

/* ── Badge tones (extend the base badges in site.css) ─────── */
.badge-success{background:var(--green-100);color:var(--green-700)}
/* Badge text is 11px on a tinted ground, so it needs a darker ink than the
   600-step: gold-600 on gold-100 read 2.71:1 and red-600 on red-100 4.23:1.
   The fills are unchanged — only the lettering gets darker. */
.badge-warning{background:var(--gold-100);color:#8a6410}
.badge-danger{background:var(--red-100);color:#9c4131}

/* ── Header additions ─────────────────────────────────────── */
.site-nav a.is-active{color:var(--ink-900);border-bottom-color:var(--clay-500)}
/* One control instead of two links and a separator: three slots in the bar to
   say one thing, and the one thing is which language you are reading. */
.lang-menu{position:relative}
.lang-menu > summary{display:inline-flex;align-items:center;gap:4px;cursor:pointer;list-style:none;
  padding:5px 9px;border-radius:var(--radius-sm);
  font:600 13px/1 var(--font-sans);color:var(--text-subtle)}
.lang-menu > summary::-webkit-details-marker{display:none}
.lang-menu > summary:hover{background:var(--paper-100);color:var(--ink-900)}
.lang-caret{display:inline-flex;transform:rotate(90deg);opacity:.65}
.lang-menu[open] .lang-caret{transform:rotate(-90deg);opacity:1}
.lang-menu[open] > summary{background:var(--paper-100);color:var(--ink-900)}
.lang-menu-list{position:absolute;right:0;top:100%;margin-top:4px;z-index:60;min-width:150px;display:grid;
  padding:6px;border-radius:var(--radius-md);border:1px solid var(--border-subtle);
  background:var(--surface-card);box-shadow:var(--shadow-sm)}
.lang-menu-list a{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--radius-sm);
  border-bottom:none;font:var(--text-body-sm);color:var(--text-body);white-space:nowrap}
.lang-menu-list a:hover{background:var(--paper-100);color:var(--ink-900)}
.lang-menu-list a.is-active{color:var(--ink-900);font-weight:600}
.lang-code{display:inline-grid;place-items:center;min-width:26px;padding:1px 5px;flex:none;
  border-radius:var(--radius-sm);background:var(--paper-100);
  font:600 11px/1.5 var(--font-sans);color:var(--text-subtle)}
.lang-menu-list a.is-active .lang-code{background:var(--clay-500);color:#fff}
/* The drawer's flat pair. Desktop keeps the compact menu; the row only exists
   below the hamburger breakpoint (site.css), where it closes the drawer. */
.lang-row{display:none}
@media (max-width:860px){
  .lang-menu{display:none}
  .lang-row{order:1;display:grid;grid-template-columns:1fr 1fr;gap:var(--space-2);
    margin-top:var(--space-2);padding-top:var(--space-4);border-top:1px solid var(--border-subtle)}
  .lang-row a{display:flex;align-items:center;justify-content:center;gap:8px;min-height:var(--control-h-md);
    padding:8px 10px;border:1px solid var(--border-subtle);border-radius:var(--radius-sm);
    font:var(--text-body-sm);color:var(--text-body)}
  .lang-row a.is-active{color:var(--ink-900);font-weight:600;border-color:var(--ink-900)}
  .lang-row a.is-active .lang-code{background:var(--clay-500);color:#fff}
}
.inline-form{display:inline-flex;margin:0}
.brand-link{border-bottom:none}

/* ── Flash messages ───────────────────────────────────────── */
.flash-stack{display:flex;flex-direction:column;gap:10px;padding:var(--space-5) 0 0}
.flash{display:flex;gap:10px;align-items:flex-start;border-radius:var(--radius-md);padding:12px 16px;
  font:var(--text-body-sm);border:1px solid var(--border-subtle);background:var(--surface-card);box-shadow:var(--shadow-xs)}
.flash .ic{flex:none;margin-top:1px}
.flash-success{border-left:3px solid var(--status-success);color:var(--green-700)}
.flash-success .ic{color:var(--status-success)}
.flash-error{border-left:3px solid var(--status-danger);color:var(--red-600)}
.flash-error .ic{color:var(--status-danger)}
.flash-info{border-left:3px solid var(--status-info);color:var(--ink-700)}
.flash-info .ic{color:var(--status-info)}

/* A class that sets `display` beats the browser's own [hidden] rule on
   specificity, so anything toggled with `el.hidden = true` — the meeting
   dialog's address field, for one — stayed on screen. Make hidden mean
   hidden. */
[hidden]{display:none !important}

/* ── Forms ────────────────────────────────────────────────── */
.form{display:flex;flex-direction:column;gap:var(--space-5)}
.field{display:flex;flex-direction:column;gap:6px}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-5)}
.field-narrow{max-width:100%}
.field label,.field legend,.seg-field legend{font:var(--text-label);color:var(--text-strong);padding:0}
.field .opt{font:var(--text-caption);color:var(--text-subtle);font-weight:400}
.field input[type=text],.field input[type=email],.field input[type=password],.field input[type=tel],
.field input[type=number],.field input[type=date],.field select,textarea{
  width:100%;height:var(--control-h-md);padding:0 14px;border:1px solid var(--border-default);border-radius:var(--radius-sm);
  background:var(--surface-card);color:var(--text-body);font:var(--text-body);outline:none;
  transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard)}
/* A textarea is in that list for its border, font and focus ring, and was
   getting the single-line control height with them — so `rows` did nothing,
   every textarea on the site was 46px tall whatever it was asked for, and a
   two-line placeholder was clipped mid-word. Three places had already patched
   their own back to a readable size one at a time; this fixes the rule instead.
   Height comes from `rows` again, with the control height as the floor so a
   one-row box still matches the inputs beside it. */
textarea{height:auto;min-height:var(--control-h-md);padding-top:11px;padding-bottom:11px;
  line-height:1.55;resize:vertical}
.field select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236b6259' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center;padding-right:40px}
.field input:focus,.field select:focus{border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.field-error{font:var(--text-caption);color:var(--red-600)}
.field-hint{display:flex;gap:6px;align-items:flex-start;margin-top:5px;font:var(--text-caption);color:var(--text-muted)}
.field-hint .ic{flex:none;margin-top:1px;color:var(--text-subtle)}
/* A hint that explains a whole field-row reads across it, rather than stacking
   into one half-width column as a stack of four-word lines. */
.field-hint.field-hint-row{margin-top:8px}
.field input[readonly]{background:var(--surface-sunken);color:var(--text-muted);cursor:not-allowed}
.address-row{grid-template-columns:1fr 90px}
.input-locked{position:relative}
.input-locked input{padding-right:42px}
.input-locked .lock-ic{position:absolute;right:14px;top:50%;transform:translateY(-50%);color:var(--text-subtle);pointer-events:none}
.field-error::before{content:"";display:inline-block}
.form .btn-block,.btn-block{width:100%}

.check{display:flex;gap:10px;align-items:flex-start;cursor:pointer;font:var(--text-body-sm);color:var(--text-body)}
.check input[type=checkbox]{width:20px;height:20px;margin-top:1px;accent-color:var(--clay-500);flex:none;cursor:pointer}
.check-inline{align-items:center}
.check-lead .check-title{display:block;font:var(--text-label);color:var(--text-strong)}
.check-lead .check-desc,.check-desc{display:block;font:var(--text-body-sm);color:var(--text-muted);margin-top:2px}

/* Segmented radio control */
.seg-field{border:none;padding:0;margin:0;display:flex;flex-direction:column;gap:6px}
.segmented{display:inline-flex;flex-wrap:wrap;gap:6px;background:var(--surface-sunken);padding:4px;border-radius:var(--radius-md);border:1px solid var(--border-subtle)}
.segmented .seg{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border-radius:var(--radius-sm);
  font:var(--text-label);color:var(--text-muted);cursor:pointer;transition:background var(--dur-fast) var(--ease-standard),color var(--dur-fast) var(--ease-standard)}
.segmented .seg input{position:absolute;opacity:0;width:0;height:0}
/* Read from the radio, not from a class written once on the server. With the
   class, pressing a segment moved the clipped radio and left the highlight
   where it was — the control looked dead and then reported the wrong answer. */
.segmented .seg:has(input:checked){background:var(--surface-card);color:var(--ink-900);box-shadow:var(--shadow-xs)}
.segmented .seg:hover{color:var(--ink-900)}
/* The radio is what the keyboard lands on, and it is invisible. */
.segmented .seg:focus-within{box-shadow:var(--focus-ring)}

.hint{display:flex;gap:8px;align-items:flex-start;font:var(--text-body-sm);color:var(--text-muted);margin:0}
/* A consequence the reader should weigh, not a tip. Warm rather than red: the
   choice is legitimate, it just has a cost worth naming before it is made. */
.hint-warn{padding:var(--space-4) var(--space-5);background:var(--gold-100);
  border-radius:var(--radius-sm);color:var(--warm-900);text-wrap:pretty;margin-top:var(--space-3)}
.hint-warn .ic{color:var(--gold-600);flex:none;margin-top:1px}
.hint .ic{flex:none;margin-top:2px;color:var(--text-subtle)}
.hint-info{color:var(--ink-700)}
.hint-info .ic{color:var(--status-info)}
.form-actions{display:flex;gap:var(--space-4);flex-wrap:wrap;margin-top:var(--space-3)}
.form-card{padding:var(--space-8)}
/* Stacked cards in the listing wizard/edit flow need breathing room between them */
.wizard .container-narrow > .card{margin-bottom:var(--space-7)}
.wizard .container-narrow > .card:last-child{margin-bottom:0}

/* ── Auth pages ───────────────────────────────────────────── */
.auth-wrap{min-height:60vh;display:grid;place-items:center;padding:var(--space-11) var(--layout-gutter);background:var(--gradient-page)}
.auth-card{width:100%;max-width:520px;padding:var(--space-9)}
.auth-lead{color:var(--text-muted);margin:var(--space-3) 0 var(--space-7)}
.auth-alt{margin-top:var(--space-6);font:var(--text-body-sm);color:var(--text-muted);text-align:center}

/* ── Lend landing ─────────────────────────────────────────── */
.lend-hero .intro{max-width:720px}
.lend-hero h1{font:var(--text-display-2);letter-spacing:var(--tracking-tight);color:var(--ink-900);margin:var(--space-5) 0 var(--space-5)}
.hero-actions{display:flex;gap:var(--space-4);flex-wrap:wrap;margin-top:var(--space-7)}
.stat-band{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-6);margin-top:var(--space-10)}
.stat{background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);padding:var(--space-6);box-shadow:var(--shadow-sm)}
.stat-v{font:var(--text-display-3);color:var(--clay-600);letter-spacing:var(--tracking-tight)}
.stat-l{font:var(--text-body-sm);color:var(--text-muted);margin-top:6px}
.who-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-6)}
.who-card{padding:var(--space-7)}
.who-ic{display:inline-grid;place-items:center;width:48px;height:48px;border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700);margin-bottom:var(--space-5)}
.who-card h3{margin-bottom:8px}

/* Sustainability band */
.section-eco{background:var(--green-100)}
.eco-head{max-width:680px;margin-bottom:var(--space-8)}
.eco-head .badge{margin-bottom:var(--space-5)}
.eco-head .section-title{margin:0}
.eco-lead{color:var(--green-700);margin-top:var(--space-4);text-wrap:pretty}
.eco-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-6)}
.eco-card{padding:var(--space-6);display:flex;flex-direction:column;gap:6px;background:var(--white);border-color:transparent;box-shadow:var(--shadow-sm)}
.eco-ic{display:inline-grid;place-items:center;width:44px;height:44px;border-radius:var(--radius-pill);background:var(--green-100);color:var(--green-700);margin-bottom:var(--space-4)}
.eco-card p{color:var(--text-muted)}
.eco-more{margin:var(--space-7) 0 0}
.eco-more a{display:inline-flex;align-items:center;gap:6px;font-weight:600;color:var(--green-700);text-decoration:none}
.eco-more a:hover{text-decoration:underline;text-underline-offset:3px}

/* /nachhaltig. Long-form prose in three bands — the environmental argument,
   the one about people, the honest limits — so a reader scrolling past can
   tell where one argument ends. The bold one-liners of the text are the
   scannable layer, so they are set as statements rather than inline bold. */
.eco-hero{background:var(--green-100);padding-bottom:var(--space-10)}
.eco-hero .lead{color:var(--green-700)}
.eco-prose p{margin:0 0 var(--space-5);color:var(--warm-800);text-wrap:pretty}
.eco-prose p:last-child{margin-bottom:0}
.eco-prose a:not(.chip){color:var(--text-link);font-weight:600}
.eco-prose h2{font:var(--text-h1);color:var(--ink-900);margin:var(--space-10) 0 var(--space-5);scroll-margin-top:var(--space-10);text-wrap:balance}
.eco-prose h3{font:var(--text-h2);color:var(--ink-900);margin:var(--space-9) 0 var(--space-4);scroll-margin-top:var(--space-10);text-wrap:balance}
.eco-prose > :first-child{margin-top:0}
.eco-prose .eco-part{font:var(--text-display-3);margin-bottom:var(--space-6)}
.eco-key{font:var(--text-h2);color:var(--green-700)!important;border-left:3px solid var(--green-600);
  padding:2px 0 2px var(--space-5);margin:var(--space-7) 0!important;text-wrap:balance}
.eco-lines{font-style:italic}
.eco-list{list-style:none;margin:0 0 var(--space-6);padding:0;display:flex;flex-direction:column;gap:var(--space-3)}
.eco-list li{display:flex;gap:var(--space-4);align-items:flex-start;color:var(--warm-800)}
.eco-list li svg{flex:none;margin-top:3px;color:var(--green-600)}
.section-eco .eco-principles li{background:var(--white);border-radius:var(--radius-md);padding:var(--space-4) var(--space-5);font-weight:600;color:var(--ink-900)}
.eco-flow{margin:0 0 var(--space-6);padding:var(--space-6);border-radius:var(--radius-lg);background:var(--surface-page)}
.eco-flow p{margin:var(--space-4) 0}
.eco-flow-row{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3)}
.eco-flow-row li{display:inline-flex;align-items:center;gap:var(--space-3)}
.eco-flow-row li + li::before{content:"→";color:var(--text-subtle)}
.eco-flow-row span{white-space:nowrap;padding:5px 12px;border-radius:var(--radius-pill);font-weight:600;font-size:15px}
.eco-flow-row.is-old span{background:var(--warm-100);color:var(--text-muted)}
.eco-flow-row.is-new span{background:var(--green-100);color:var(--green-700)}
.eco-uses{list-style:none;margin:0 0 var(--space-5);padding:0;display:flex;flex-wrap:wrap;gap:var(--space-3)}
.eco-close{background:var(--white);padding:var(--space-12) 0;border-top:1px solid var(--border-subtle)}
.eco-close h2{font:var(--text-display-2);letter-spacing:var(--tracking-tight);color:var(--ink-900);margin:0 0 var(--space-6)}
.eco-close p{font:var(--text-body-lg);color:var(--text-muted);margin:0 0 var(--space-5);text-wrap:pretty}
.eco-close .eco-close-key{font:var(--text-h1);color:var(--clay-600);margin:var(--space-8) 0 0}
/* On a phone the hero's .container drops to a 20px gutter; the prose keeps
   the same left edge instead of stepping in by another 12px under it. */
@media (max-width:560px){
  .eco-prose,.eco-close .container-narrow{padding:0 20px}
  .eco-hero ~ .section{padding:var(--space-10) 0}
  .eco-close{padding:var(--space-10) 0}
}

.cta-band{display:flex;align-items:center;justify-content:space-between;gap:var(--space-8);flex-wrap:wrap}
.cta-lead{color:var(--text-muted);max-width:520px;margin-top:var(--space-4)}

/* ── Wizard ───────────────────────────────────────────────── */
.wizard-head{margin-bottom:var(--space-8)}
.wizard-step{display:inline-block;font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;color:var(--text-subtle);margin-bottom:var(--space-4)}
.wizard-step a{font-weight:600}
.wizard-lead{color:var(--text-muted);margin-top:var(--space-4)}
.cat-group{margin-bottom:var(--space-8)}
.cat-group-head{display:flex;align-items:center;gap:10px;margin-bottom:var(--space-4)}
.cat-group-head .cat-ic{display:inline-grid;place-items:center;width:32px;height:32px;border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700)}
.model-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-4)}
.model-card{display:flex;align-items:center;gap:var(--space-5);padding:var(--space-5)}
.model-ic{display:inline-grid;place-items:center;width:48px;height:48px;border-radius:var(--radius-md);background:var(--paper-100);color:var(--warm-600);flex:none}
.model-ic.lg{width:56px;height:56px;color:var(--clay-600)}
.model-body{flex:1;min-width:0}
.model-name{font:var(--text-h4);color:var(--text-strong)}
.model-brand{font:var(--text-body-sm);color:var(--text-muted);margin:2px 0 8px}
.model-go{color:var(--text-subtle);flex:none}
.custom-link{display:inline-flex;align-items:center;gap:8px;font:var(--text-label);color:var(--clay-600);border-bottom:none}
.wizard-foot{display:flex;flex-wrap:wrap;gap:var(--space-6);margin-top:var(--space-6)}
.model-summary{display:flex;gap:var(--space-5);align-items:center;padding:var(--space-6);margin-bottom:var(--space-7)}
.summary-meta{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.acc-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.listing-form{background:transparent}

/* ── Dashboard ────────────────────────────────────────────── */
.dash-grid{display:grid;grid-template-columns:1fr 320px;gap:var(--space-8);align-items:start}
.dash-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-5);margin-bottom:var(--space-6)}
.dash-sub{color:var(--text-muted);margin-top:6px}
.listing-list{display:flex;flex-direction:column;gap:var(--space-4)}
.listing-row{display:flex;align-items:center;gap:var(--space-5);padding:var(--space-5)}
.listing-ic{display:inline-grid;place-items:center;width:52px;height:52px;border-radius:var(--radius-md);background:var(--paper-100);color:var(--clay-600);flex:none}
.listing-info{flex:1;min-width:0}
.listing-title{font:var(--text-h4);color:var(--text-strong);margin-bottom:6px}
.listing-badges{display:flex;flex-wrap:wrap;gap:6px}
.listing-status{display:flex;flex-direction:column;align-items:flex-end;gap:10px;flex:none}

.switch{--w:46px;--h:26px;width:var(--w);height:var(--h);border-radius:var(--radius-pill);border:none;cursor:pointer;
  background:var(--warm-300);position:relative;padding:0;transition:background var(--dur-base) var(--ease-standard)}
.switch .knob{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:var(--shadow-sm);transition:transform var(--dur-base) var(--ease-out)}
.switch.is-on{background:var(--status-success)}
.switch.is-on .knob{transform:translateX(20px)}

.board-title{margin:var(--space-9) 0 var(--space-5)}
.board-card{display:flex;gap:var(--space-5);align-items:flex-start;padding:var(--space-6);margin-bottom:var(--space-4)}
.board-ic{color:var(--clay-600);margin-top:2px;flex:none}
.board-body{flex:1}
.board-task{font:var(--text-h4);color:var(--text-strong);margin-bottom:4px}
.board-meta{font:var(--text-body-sm);color:var(--text-muted);margin-bottom:14px}
.board-actions{display:flex;gap:10px}
.board-empty{display:flex;gap:12px;align-items:center;padding:var(--space-6)}
.board-empty .ic{color:var(--clay-500);flex:none}
.board-empty p{margin:0;color:var(--text-muted)}

.dash-side{display:flex;flex-direction:column;gap:var(--space-5)}
.side-card{padding:var(--space-6)}
.payout-amount{font:var(--text-price-lg);color:var(--ink-900);margin-top:6px}
.payout-note{color:var(--text-muted);margin:10px 0 var(--space-6)}
.hs-teaser{display:flex;gap:12px;align-items:flex-start;border-bottom:none;color:inherit}
.hs-teaser:hover{color:inherit}
.hs-ic{display:inline-grid;place-items:center;width:34px;height:34px;border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700);flex:none}

.empty-state{display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--space-4);padding:var(--space-10) var(--space-7)}
.empty-ic{display:inline-grid;place-items:center;width:64px;height:64px;border-radius:var(--radius-pill);background:var(--paper-100);color:var(--warm-500)}
.empty-state p{color:var(--text-muted);max-width:360px}

/* ── Hidden supply ────────────────────────────────────────── */
.hs-prompt{margin-bottom:var(--space-5)}
.hs-chips{display:flex;flex-wrap:wrap;gap:10px}
.hs-chip{color:var(--ink-900)}
.hs-divider{display:flex;align-items:center;gap:14px;margin:var(--space-7) 0 var(--space-5);color:var(--text-subtle);font:var(--text-caption)}
.hs-divider::before,.hs-divider::after{content:"";flex:1;height:1px;background:var(--border-subtle)}
.hs-mine{display:flex;flex-direction:column;gap:var(--space-4)}
.hs-mine-row{display:flex;align-items:center;gap:var(--space-5);padding:var(--space-5)}

/* ── Buttons: danger ──────────────────────────────────────── */
.btn-danger{--_bg:var(--surface-card);--_fg:var(--red-600);--_bd:var(--red-100);box-shadow:var(--shadow-xs)}
.btn-danger:hover{--_bg:var(--red-100);--_bd:var(--red-600)}

/* ── Account: status cards ────────────────────────────────── */
.status-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-5);margin-bottom:var(--space-6)}
.status-card{padding:var(--space-7)}
.status-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-5)}
.status-ic{display:inline-grid;place-items:center;width:44px;height:44px;border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700)}
.status-desc{color:var(--text-muted);margin:6px 0 var(--space-6)}
.status-actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.status-done{display:inline-flex;align-items:center;gap:8px;font:var(--text-label);color:var(--green-700)}
.status-done .ic{color:var(--status-success)}
.account-payments{margin-top:var(--space-8)}

/* ── Account page layout ──────────────────────────────────── */
.account-head{margin-bottom:var(--space-7)}
.account-grid{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:var(--space-7);align-items:start}
.account-main{display:flex;flex-direction:column;gap:var(--space-6);min-width:0}
.account-side{display:flex;flex-direction:column;gap:var(--space-5);position:sticky;top:88px}

.card-head{display:flex;align-items:center;gap:12px;margin-bottom:var(--space-6)}
.card-head-ic{display:inline-grid;place-items:center;width:38px;height:38px;border-radius:var(--radius-pill);background:var(--ink-100);color:var(--ink-700);flex:none}
.card-head h2{margin:0}

/* Address sub-panel (replaces the raw fieldset) */
.address-block{background:var(--surface-sunken);border:1px solid var(--border-subtle);border-radius:var(--radius-md);padding:var(--space-5);display:flex;flex-direction:column;gap:var(--space-5)}
.address-head{display:flex;gap:12px;align-items:flex-start}
.address-ic{display:inline-grid;place-items:center;width:34px;height:34px;border-radius:var(--radius-pill);background:var(--surface-card);color:var(--clay-600);border:1px solid var(--border-subtle);flex:none}
.address-title{font:var(--text-label);color:var(--text-strong)}
.address-note{font:var(--text-body-sm);color:var(--text-muted);margin-top:2px;text-wrap:pretty}
.address-block .field input{background:var(--surface-card)}

/* Sidebar status + earnings cards */
.side-status{padding:var(--space-6)}
.side-status h2{margin-bottom:6px}
.side-status .status-desc{margin:0 0 var(--space-5)}
.side-status .status-actions{flex-direction:column;align-items:stretch;gap:10px}
/* Email preference list */
.pref-list{display:flex;flex-direction:column;gap:12px;margin-bottom:var(--space-6)}
.pref-item{padding:14px 16px;border:1px solid var(--border-subtle);border-radius:var(--radius-md);background:var(--surface-card);transition:border-color var(--dur-fast) var(--ease-standard)}
.pref-item:hover{border-color:var(--border-default)}
.card-head-ic.danger-ic{background:var(--red-100);color:var(--red-600)}

.side-earn{padding:var(--space-6)}
.side-earn-amount{font:var(--text-price-lg);color:var(--ink-900);margin:8px 0 2px}
.side-earn-note{font:var(--text-body-sm);color:var(--text-muted);margin-bottom:var(--space-5)}

/* ── Guided onboarding panel (identity + payouts as one path) ── */
.onboard-panel{padding:var(--space-7);margin-bottom:var(--space-7)}
.onboard-panel-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-6)}
.onboard-panel-head h2{margin:0}
.onboard-panel-sub{color:var(--text-muted);margin-top:4px;max-width:48ch;text-wrap:pretty}
.onboard-progress{flex:none;font:var(--text-label-sm);color:var(--clay-700);background:var(--clay-100);border:1px solid var(--clay-200);
  border-radius:var(--radius-pill);padding:6px 12px;white-space:nowrap}
.onboard-steps{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-4)}
.onboard-step{display:flex;align-items:center;gap:var(--space-5);padding:var(--space-5);
  background:var(--surface-sunken);border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
.onboard-step-n{display:inline-grid;place-items:center;width:32px;height:32px;flex:none;border-radius:var(--radius-pill);
  background:var(--surface-card);border:1px solid var(--border-default);color:var(--ink-700);font:var(--text-label)}
.onboard-step.is-done{background:var(--green-100);border-color:var(--green-100)}
.onboard-step.is-done .onboard-step-n{background:var(--status-success);border-color:var(--status-success);color:#fff}
.onboard-step-body{flex:1;min-width:0}
.onboard-step-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.onboard-step-title{font:var(--text-h4);color:var(--text-strong)}
.onboard-step-benefit{font:var(--text-body-sm);color:var(--text-muted);margin-top:3px}
.onboard-step-action{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:6px}
.onboard-step-action .inline-form{margin:0}
.onboard-consent-form{display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-3);max-width:34rem}
.onboard-consent-form .onboard-notice{margin:0;text-align:left;align-self:stretch}
.onboard-consent-form .onboard-consent{align-self:stretch;text-align:left}
.onboard-consent-form .btn{margin-top:var(--space-2)}
.onboard-panel .field-hint{margin-top:var(--space-5)}

.onboard-done{display:flex;align-items:center;gap:var(--space-5);padding:var(--space-6);margin-bottom:var(--space-7);
  background:var(--green-100);border-color:var(--green-100)}
.onboard-done-ic{display:inline-grid;place-items:center;width:44px;height:44px;flex:none;border-radius:var(--radius-pill);
  background:var(--status-success);color:#fff}
.onboard-done-b{color:var(--green-700);margin-top:2px}

/* Renter → supplier upgrade CTA (renter account page) */
.upgrade-cta{display:flex;align-items:center;gap:var(--space-5);padding:var(--space-6);margin-bottom:var(--space-7);
  text-decoration:none;color:inherit;transition:border-color .15s,box-shadow .15s}
.upgrade-cta:hover{border-color:var(--clay-400);box-shadow:var(--shadow-sm)}
.upgrade-cta-ic{display:inline-grid;place-items:center;width:44px;height:44px;flex:none;border-radius:var(--radius-pill);
  background:var(--clay-100);color:var(--clay-600)}
.upgrade-cta-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.upgrade-cta-sub{color:var(--text-muted);text-wrap:pretty}
.upgrade-cta .btn{flex:none}
@media (max-width:560px){
  .upgrade-cta{flex-wrap:wrap}
  .upgrade-cta .btn{width:100%;justify-content:center}
}

@media (max-width:960px){
  .account-grid{grid-template-columns:1fr}
  .account-side{position:static;flex-direction:row;flex-wrap:wrap}
  .account-side > *{flex:1 1 260px}
}
@media (max-width:560px){
  .account-side{flex-direction:column}
  .onboard-step{flex-wrap:wrap;align-items:flex-start}
  .onboard-step-action{width:100%;align-items:stretch;margin-top:var(--space-3)}
  .onboard-step-action .btn{width:100%;justify-content:center}
  .onboard-step-action .row-link{align-self:center}
}

/* ── Onboarding banner (dashboard) ────────────────────────── */
.onboard-banner{display:flex;align-items:center;gap:var(--space-5);padding:var(--space-5) var(--space-6);
  background:var(--clay-100);border:1px solid var(--clay-200);border-radius:var(--radius-lg);margin-bottom:var(--space-6);
  color:var(--warm-800);border-bottom:1px solid var(--clay-200);transition:background var(--dur-fast) var(--ease-standard)}
.onboard-banner:hover{background:var(--clay-200);color:var(--warm-900)}
.onboard-ic{display:inline-grid;place-items:center;width:44px;height:44px;border-radius:var(--radius-pill);background:var(--white);color:var(--clay-700);flex:none}
.onboard-text{flex:1;min-width:0}
.onboard-title{display:block;font:var(--text-h4);color:var(--ink-900)}
.onboard-body{display:block;font:var(--text-body-sm);color:var(--text-muted)}
.onboard-go{display:inline-flex;align-items:center;gap:4px;font:var(--text-label);color:var(--clay-700);white-space:nowrap;flex:none}

/* ── Listing row actions + test-checkout ──────────────────── */
.listing-actions{display:flex;align-items:center;gap:var(--space-5);margin-top:10px;flex-wrap:wrap}
.row-link{display:inline-flex;align-items:center;gap:5px;font:var(--text-label-sm);color:var(--text-muted);border-bottom:none}
.row-link:hover{color:var(--clay-600)}

/* ── Availability + danger zone ───────────────────────────── */
.avail-list{display:flex;flex-direction:column;gap:10px;margin-bottom:var(--space-6)}
.avail-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);
  padding:10px 14px;background:var(--surface-sunken);border:1px solid var(--border-subtle);border-radius:var(--radius-sm)}
.avail-dates{display:inline-flex;align-items:center;gap:8px;font:var(--text-body-sm);color:var(--text-body)}
.avail-add{border-top:1px solid var(--border-subtle);padding-top:var(--space-5)}
.danger-card{border-color:var(--red-100)}

/* ── Pricing preview (wizard/edit) ────────────────────────── */
.pricing-preview{background:var(--clay-100);border:1px solid var(--clay-200);border-radius:var(--radius-md);padding:var(--space-5) var(--space-6)}
.pp-label{font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;color:var(--clay-700)}
.pp-rows{display:flex;flex-direction:column;gap:6px;margin:10px 0 6px}
.pp-row{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font:var(--text-body);color:var(--text-body)}
.pp-row strong{font:var(--text-h4);color:var(--ink-900)}
.pp-row .pp-days{font:var(--text-caption);color:var(--text-subtle)}
.pp-you strong{color:var(--clay-700)}
.pp-note{font:var(--text-caption);color:var(--text-muted)}

/* ── Listing detail ───────────────────────────────────────── */
.detail-back{display:inline-flex;align-items:center;gap:6px;font:var(--text-label);color:var(--text-muted);border-bottom:none;margin-bottom:var(--space-5)}
.detail-back:hover{color:var(--clay-600)}
.detail-preview{margin-bottom:var(--space-6)}
.detail-grid{display:grid;grid-template-columns:1fr 380px;gap:var(--space-8);align-items:start}
/* The price card comes FIRST in the source so the page's <h1> precedes its
   <h2>s (§19). Explicit placement puts the two columns back where they
   look right; without it the sidebar would render on the left. */
.detail-main{grid-column:1}
.detail-side{grid-column:2;grid-row:1}
.detail-main{min-width:0;display:flex;flex-direction:column;gap:var(--space-7)}
/* The hero takes the photograph's shape rather than imposing one. A 4/3 box
   with object-fit:cover was slicing the top off anything squarer or taller
   than 4/3 — which is most product photos, and all Foto-Studio output. If it
   is a square, it renders as a square. max-height keeps a very tall portrait
   from pushing the whole page down; only then does contain letterbox. */
/* A <picture> is a box the layout never asked for: the hero, the thumbs and the
   card media all position the <img> itself. display:contents removes the wrapper
   from the box tree so responsive sources changed nothing about any of them. */
.gallery-hero picture,.gallery-thumb picture,.browse-card-media picture{display:contents}
.gallery-hero{border-radius:var(--radius-lg);overflow:hidden;background:var(--paper-050);border:1px solid var(--border-subtle);display:grid;place-items:center}
.gallery-hero img{display:block;width:100%;height:auto;max-height:min(74vh,640px);object-fit:contain;background:var(--paper-050)}
.gallery-thumbs{display:flex;gap:10px;margin-top:12px;flex-wrap:wrap}
.gallery-thumb{width:76px;height:60px;border-radius:var(--radius-sm);overflow:hidden;border:2px solid transparent;background:none;padding:0;cursor:pointer}
.gallery-thumb img{width:100%;height:100%;object-fit:contain;background:var(--paper-050)}
.gallery-thumb.is-active{border-color:var(--clay-500)}
.gallery-empty{aspect-ratio:16/7;border-radius:var(--radius-lg);background:var(--paper-100);border:1px dashed var(--paper-300);display:grid;place-items:center;color:var(--warm-400)}
.detail-block h2{margin-bottom:var(--space-4);display:flex;align-items:center;gap:8px}
.spec-list{display:grid;grid-template-columns:1fr;gap:0;margin:0}
.spec-list > div{display:flex;justify-content:space-between;gap:16px;padding:12px 0;border-bottom:1px solid var(--border-subtle)}
.spec-list dt{color:var(--text-muted);font:var(--text-body-sm)}
.spec-list dd{margin:0;color:var(--text-strong);font:var(--text-label);text-align:right}

/* The fee example on /vermieten, which is a sum and not a spec sheet.
   Everything below is scoped to .fee-list because .spec-list is also the
   listing's technical data, where no row is the consequence of the rows above
   it and a total rule would be a lie. */
/* Right alignment lines up the euro signs; the digits in front of them only
   line up if they are all one width. "3,00 €" and "3,45 €" were a pixel apart,
   which is enough to make a column of money look hand-set. */
.fee-list dd{font-variant-numeric:tabular-nums}
/* A rule under the last row is a rule under the bottom of the table. */
.fee-list > div:last-child{border-bottom:0}
/* The two rows the arithmetic arrives at. The rent is where the renter's price
   is settled and the total is what they are charged, so each closes the group
   of additions above it rather than sitting in the middle of them. */
.fee-list > .is-sum,
.fee-list > .is-total{border-top:1px solid var(--border-default)}
.fee-list > .is-sum dt,
.fee-list > .is-total dt{color:var(--text-strong)}
.fee-list > .is-total{padding-top:var(--space-4)}
.fee-list > .is-total dt{font:var(--text-h4)}
/* The shorthand resets font-variant-numeric, so the one number most worth
   lining up loses the tabular figures set above unless they are restated. */
.fee-list > .is-total dd{font:var(--text-price);font-variant-numeric:tabular-nums;color:var(--ink-900)}
.uses-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.uses-list li{display:flex;align-items:center;gap:8px;font:var(--text-body);color:var(--text-body)}
.uses-list .ic{color:var(--status-success)}
.safety-block{background:var(--surface-sunken);border-radius:var(--radius-lg);padding:var(--space-6)}
.safety-block h2 .ic{color:var(--clay-600)}

.detail-side{position:sticky;top:88px;display:flex;flex-direction:column;gap:var(--space-5)}
.price-card{padding:var(--space-7)}
.pc-head{display:flex;gap:8px;margin-bottom:12px}
.pc-title{margin:0 0 10px}
.pc-price{font:var(--text-price-lg);color:var(--ink-900);margin-bottom:var(--space-6)}
.pc-price span{font:var(--text-body);color:var(--text-muted)}
/* The gap below is not this margin alone — the terms row under it adds its own
   10px of top padding before the first label, so a 16px margin here read as
   32px of white against the 27px above the panel. 12px puts both sides at the
   same optical distance from the tint. */
/* The total is the answer to the ladder above it, not the next line of it —
   it was sitting flush against the last band. */
.pc-breakdown{background:var(--surface-sunken);border-radius:var(--radius-md);padding:var(--space-5);
  margin:var(--space-5) 0 var(--space-4)}
.pc-row{display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin-bottom:6px;font:var(--text-body-sm);color:var(--text-body)}
.pc-row strong{font:var(--text-h4);color:var(--ink-900)}
.pc-row .pc-sub{font:var(--text-caption);color:var(--text-subtle)}
/* The 6px is the gap BETWEEN rows. On the last one it fell inside the panel's
   own padding, so a single-row breakdown — the renter's, the common case — sat
   16px from the top and 22px from the bottom. */
.pc-breakdown > :last-child{margin-bottom:0}
.pc-you strong{color:var(--clay-700)}
.pc-note{font:var(--text-caption);color:var(--text-muted);margin-top:4px}
.pc-terms{display:flex;flex-direction:column;gap:0;margin:0 0 var(--space-6)}
.pc-terms > div{display:flex;justify-content:space-between;gap:12px;padding:10px 0;border-bottom:1px solid var(--border-subtle)}
.pc-terms dt{color:var(--text-muted);font:var(--text-body-sm)}
/* A long label (»Kautionsabwicklung (1,5 % + 0,25 €)«) was squeezing the amount
   until »– 3,00 €« broke after the number. An amount never wraps. */
.pc-terms dd{margin:0;color:var(--text-strong);font:var(--text-label);white-space:nowrap}
.provider-card{padding:var(--space-6)}
.provider-row{display:flex;gap:12px;align-items:center;margin-top:10px}
.provider-ava{display:inline-grid;place-items:center;width:44px;height:44px;border-radius:var(--radius-pill);background:var(--paper-100);color:var(--warm-600);flex:none}
.provider-name{font:var(--text-h4);color:var(--text-strong);display:flex;align-items:center;gap:6px}
.provider-meta{font:var(--text-body-sm);color:var(--text-muted)}
.verified-tick{color:var(--status-success);display:inline-flex}

/* ── Photos ───────────────────────────────────────────────── */
.photo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:12px;margin-bottom:var(--space-6)}
.photo-tile{position:relative;aspect-ratio:4/3;border-radius:var(--radius-md);overflow:hidden;border:1px solid var(--border-subtle);background:var(--paper-100)}
.photo-tile img{width:100%;height:100%;object-fit:contain;background:var(--paper-050)}
.photo-badge{position:absolute;left:8px;bottom:8px;background:rgba(11,45,95,.85);color:#fff;font:var(--text-label-sm);padding:3px 8px;border-radius:var(--radius-pill)}
.photo-del{position:absolute;top:6px;right:6px;margin:0}
.photo-del button{width:26px;height:26px;border-radius:var(--radius-pill);border:none;background:rgba(43,39,34,.6);color:#fff;
  display:grid;place-items:center;cursor:pointer;transition:background var(--dur-fast) var(--ease-standard)}
.photo-del button:hover{background:var(--red-600)}
.photo-upload{border-top:1px solid var(--border-subtle);padding-top:var(--space-5);gap:var(--space-4)}
/* position:relative + inset for the same reason as the browse card: the tile
   centres its fallback icon with place-items, and a percentage height against
   a centred grid item resolves to auto. */
.listing-ic.has-photo{padding:0;overflow:hidden;position:relative}
.listing-ic.has-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:var(--paper-050)}

/* ── Summary tiles ────────────────────────────────────────── */
/* auto-fit, not a hard 4: the earnings page has three tiles and a fixed
   four-column track left a card-shaped hole at the end of the row. */
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--space-4);margin-bottom:var(--space-7)}
.tile{background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);padding:var(--space-5) var(--space-6);box-shadow:var(--shadow-xs)}
.tile-v{font:var(--text-h2);color:var(--ink-900);letter-spacing:var(--tracking-tight)}
.tile-l{font:var(--text-body-sm);color:var(--text-muted);margin-top:4px}

/* ── Data table ───────────────────────────────────────────── */
.table-wrap{overflow-x:auto;padding:0}
.data-table{width:100%;border-collapse:collapse;font:var(--text-body-sm)}
.data-table th,.data-table td{padding:12px 16px;text-align:left;white-space:nowrap;border-bottom:1px solid var(--border-subtle)}
.data-table th{font:var(--text-label-sm);color:var(--text-subtle);text-transform:uppercase;letter-spacing:var(--tracking-overline)}
/* Money columns in the back office. Table cells are left-aligned by default,
   so a column of amounts did not line up on its decimal point and could not be
   scanned down — the one thing a column of amounts exists to allow. */
td.num-col{text-align:right;font-variant-numeric:tabular-nums}
.data-table td{color:var(--text-body)}
.data-table .num{text-align:right;font-variant-numeric:tabular-nums}
.data-table td.payout{color:var(--clay-700);font-weight:600}
.data-table tbody tr:last-child td{border-bottom:none}

/* ── Error page ───────────────────────────────────────────── */
.error-page{text-align:center;padding:var(--space-12) var(--layout-gutter)}
.error-code{font:var(--text-price-lg);color:var(--clay-400)}
.error-page h1{margin:var(--space-4) 0}
.error-page p{color:var(--text-muted);margin-bottom:var(--space-7)}
/* 404 and 410 both offer a way onward rather than only a way back (§72). */
.error-actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;
  margin-bottom:var(--space-6)}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width:960px){
  .dash-grid{grid-template-columns:1fr}
  .stat-band,.who-grid{grid-template-columns:1fr}
  .lend-hero h1{font:var(--text-display-3)}
  .detail-grid{grid-template-columns:1fr}
  /* One column: source order would put the price card above the gallery.
     order restores the original stacking. */
  .detail-main{grid-column:1;order:1}
  .detail-side{grid-column:1;grid-row:auto;order:2;position:static}
  .status-grid{grid-template-columns:1fr}
}
@media (max-width:720px){
  .field-row,.model-grid,.acc-grid{grid-template-columns:1fr}
  .tiles{grid-template-columns:1fr 1fr}
  .auth-card{padding:var(--space-7)}
  .cta-band{flex-direction:column;align-items:flex-start}
  .eco-grid{grid-template-columns:1fr}
}
@media (min-width:721px) and (max-width:960px){
  .eco-grid{grid-template-columns:repeat(3,1fr)}
}

/* ── Registration wizard ──────────────────────────────────── */
.reg-card{max-width:600px}
.reg-steps{display:flex;gap:10px;list-style:none;margin:0 0 var(--space-7);padding:0}
.reg-step{display:flex;align-items:center;gap:8px;flex:1;min-width:0;font:var(--text-caption);color:var(--text-subtle)}
.reg-step-n{display:inline-grid;place-items:center;width:26px;height:26px;flex:none;border-radius:var(--radius-pill);
  border:1px solid var(--border-default);background:var(--surface-card);color:var(--text-subtle);font:var(--text-label-sm)}
.reg-step-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.reg-step.is-current .reg-step-n{border-color:var(--clay-500);background:var(--clay-500);color:#fff}
.reg-step.is-current .reg-step-l{color:var(--text-strong);font-weight:600}
.reg-step.is-done .reg-step-n{border-color:var(--status-success);background:var(--status-success);color:#fff}
.reg-step.is-done{color:var(--text-muted)}

.reg-choices{display:flex;flex-direction:column;gap:var(--space-4);margin:var(--space-6) 0 var(--space-4)}
.reg-choice{display:flex;align-items:center;gap:var(--space-5);width:100%;text-align:left;cursor:pointer;
  padding:var(--space-5) var(--space-6);border:1px solid var(--border-default);border-radius:var(--radius-lg);
  background:var(--surface-card);color:inherit;font:inherit;
  transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard),transform var(--dur-fast) var(--ease-out)}
.reg-choice:hover{border-color:var(--clay-400);box-shadow:var(--shadow-sm);transform:translateY(-1px)}
.reg-choice-ic{display:inline-grid;place-items:center;width:48px;height:48px;flex:none;border-radius:var(--radius-md);background:var(--clay-100);color:var(--clay-700)}
.reg-choice-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.reg-choice-t{font:var(--text-h4);color:var(--text-strong)}
.reg-choice-d{font:var(--text-body-sm);color:var(--text-muted);text-wrap:pretty}
.reg-choice-go{color:var(--text-subtle);flex:none}

.reg-subhead{font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;color:var(--text-subtle);
  padding-top:var(--space-4);border-top:1px solid var(--border-subtle)}

.reg-renter{text-align:center}
.reg-renter-ic{display:inline-grid;place-items:center;width:64px;height:64px;border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700);margin:0 auto var(--space-5)}
.reg-renter-actions{display:flex;gap:var(--space-4);justify-content:center;flex-wrap:wrap;margin-top:var(--space-6)}

.verify-list{display:flex;flex-direction:column;gap:var(--space-5)}
.verify-item{border:1px solid var(--border-subtle);border-radius:var(--radius-md);padding:var(--space-5);background:var(--surface-sunken)}
.verify-item.is-done{background:var(--green-100);border-color:var(--green-100)}
.verify-head{display:flex;align-items:center;gap:12px}
.verify-ic{display:inline-grid;place-items:center;width:38px;height:38px;flex:none;border-radius:var(--radius-pill);
  background:var(--surface-card);border:1px solid var(--border-subtle);color:var(--clay-600)}
.verify-headtext{flex:1;min-width:0;display:flex;flex-direction:column}
.verify-title{font:var(--text-label);color:var(--text-strong)}
.verify-dest{font:var(--text-body-sm);color:var(--text-muted)}
.verify-body{margin-top:var(--space-5);display:flex;flex-direction:column;gap:10px}
.verify-code{width:100%;max-width:calc(6ch + 88px);letter-spacing:6px;text-indent:6px;font-size:20px;font-variant-numeric:tabular-nums;text-align:center}
.verify-resend{align-self:flex-start}
.verify-dev{display:inline-flex;align-items:center;gap:6px;font:var(--text-caption);color:var(--clay-700);background:var(--clay-100);border-radius:var(--radius-sm);padding:4px 8px;align-self:flex-start}
.verify-dev-warn{color:var(--red-600);background:var(--red-100)}

@media (max-width:560px){
  .reg-step-l{display:none}
  .reg-choice{padding:var(--space-5)}
}

/* ── Recovery + password SMS code ─────────────────────────── */
.login-forgot{align-self:flex-end;font:var(--text-caption);color:var(--text-muted);border-bottom:none;margin-top:2px}
.login-forgot:hover{color:var(--clay-600)}
.reg-recover{margin-bottom:var(--space-5)}
.reg-recover a{font-weight:600}
.pw-code-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.pw-code-row .verify-code{max-width:calc(6ch + 80px);letter-spacing:5px;text-indent:5px;font-size:18px;font-variant-numeric:tabular-nums;text-align:center}
.pw-code-row .btn{flex:none}

/* ── Demand-side browse & search ──────────────────────────── */
.browse-hero{background:var(--gradient-page);padding:var(--space-10) 0 var(--space-9)}
.browse-sub{color:var(--text-muted);margin:var(--space-4) 0 var(--space-7);max-width:640px;text-wrap:pretty}
.browse-search{display:flex;gap:var(--space-3);flex-wrap:wrap;align-items:stretch;background:var(--white);
  border:1px solid var(--border-subtle);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);padding:var(--space-4)}
.browse-search-field{flex:1 1 260px;display:flex;align-items:center;gap:8px;padding:0 12px;min-width:0}
.browse-search-field .ic{color:var(--text-subtle);flex:none;display:flex}
.browse-search-field input{flex:1;border:none;outline:none;background:transparent;font:400 16px/1.4 var(--font-sans);color:var(--text-body);min-width:0;height:44px}
.browse-search-q{flex:1 1 320px}
.browse-search-loc{flex:1 1 260px;border-left:1px solid var(--border-subtle);padding-right:4px}
.loc-btn{flex:none;display:grid;place-items:center;width:38px;height:38px;border-radius:var(--radius-md);
  border:none;background:transparent;color:var(--clay-600);cursor:pointer;transition:background var(--dur-base) var(--ease-standard),color var(--dur-base) var(--ease-standard)}
.loc-btn:hover{background:var(--clay-100);color:var(--clay-700)}
.loc-btn.is-loading{opacity:.6;pointer-events:none;animation:lnb-pulse 1s ease-in-out infinite}
.browse-search .btn{flex:none}
@keyframes lnb-pulse{50%{opacity:.35}}
.chip{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border-radius:var(--radius-pill);
  border:1px solid var(--border-default);background:var(--surface-card);font:var(--text-label-sm);color:var(--text-body);border-bottom:1px solid var(--border-default);white-space:nowrap;text-decoration:none}
.chip:hover{border-color:var(--clay-400);color:var(--ink-900)}
.chip.is-on{background:var(--ink-900);color:#fff;border-color:var(--ink-900)}

/* Browse layout: sticky filter sidebar + results grid on desktop */
.browse-body{padding-top:var(--space-8)}
.browse-layout{display:grid;grid-template-columns:236px minmax(0,1fr);gap:var(--space-7);align-items:start}
.browse-filters{position:sticky;top:88px;min-width:0;display:flex;flex-direction:column;gap:var(--space-6)}
.filter-group{min-width:0;display:flex;flex-direction:column;gap:var(--space-4)}
.filter-title{font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;color:var(--text-subtle)}
.filter-cats,.filter-radii{display:flex;flex-wrap:wrap;gap:8px}
.browse-results{min-width:0}
.browse-meta{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-5);flex-wrap:wrap}
.browse-count{font:var(--text-label);color:var(--text-strong)}
.browse-hint{display:inline-flex;align-items:center;gap:6px;font:var(--text-caption);color:var(--text-muted)}
.browse-hint-warn{color:var(--clay-700)}
.browse-locpill{display:inline-flex;align-items:center;gap:7px;padding:5px 6px 5px 12px;border-radius:var(--radius-pill);
  background:var(--paper-100);border:1px solid var(--border-subtle);font:var(--text-label-sm);color:var(--text-strong)}
.browse-locpill .ic,.browse-locpill svg{color:var(--clay-600)}
.browse-locpill-label{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.browse-locpill-x{display:grid;place-items:center;width:22px;height:22px;border-radius:var(--radius-pill);color:var(--text-subtle);background:var(--white)}
.browse-locpill-x:hover{color:var(--ink-900);background:var(--paper-200)}
.browse-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:var(--space-6)}
.browse-card{overflow:hidden;display:flex;flex-direction:column;padding:0;border-bottom:none;color:inherit;
  transition:box-shadow var(--dur-base) var(--ease-standard),transform var(--dur-base) var(--ease-out),border-color var(--dur-base) var(--ease-standard)}
.browse-card:hover{box-shadow:var(--shadow-lg);transform:translateY(-2px);border-color:var(--ink-200);color:inherit}
.browse-card-media{position:relative;aspect-ratio:4/3;background:var(--paper-100);display:grid;place-items:center;color:var(--warm-400);overflow:hidden}
/* Cards keep a fixed box — a grid has to line up — but the photo inside is
   shown whole, never cropped to fill it. Absolute rather than height:100%:
   the container centres its no-photo icon with place-items, and a percentage
   height against a centred grid item resolves to auto, so the image rendered
   at its intrinsic size and was clipped by overflow instead. */
.browse-card-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:var(--paper-050)}
.browse-dist{position:absolute;left:10px;bottom:10px;display:inline-flex;align-items:center;gap:4px;background:rgba(11,45,95,.9);color:#fff;font:var(--text-label-sm);padding:4px 9px;border-radius:var(--radius-pill)}
.browse-card-body{padding:var(--space-5);display:flex;flex-direction:column;gap:4px}
.browse-card-cat{font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;color:var(--text-subtle)}
.browse-card-title{font:var(--text-h4);color:var(--text-strong)}
.browse-card-foot{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-top:6px}
.browse-card-price{font:var(--text-body-sm);color:var(--text-muted)}
.browse-card-price strong{font:var(--text-h4);color:var(--ink-900)}
.browse-card-area{font:var(--text-caption);color:var(--text-subtle)}
/* Tablet/mobile: sidebar becomes horizontally-scrolling filter rows on top */
@media (max-width:860px){
  .browse-layout{grid-template-columns:1fr;gap:var(--space-6)}
  .browse-filters{position:static;flex-direction:column;gap:var(--space-4);
    padding-bottom:var(--space-5);border-bottom:1px solid var(--border-subtle)}
  .filter-group{gap:var(--space-3)}
  .filter-cats,.filter-radii{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    padding-bottom:2px;scroll-snap-type:x proximity}
  .filter-cats::-webkit-scrollbar,.filter-radii::-webkit-scrollbar{display:none}
  .filter-cats .chip,.filter-radii .chip{scroll-snap-align:start}
}
@media (max-width:560px){
  .browse-search{flex-direction:column}
  .browse-search-field{flex:none}
  .browse-search-field input{height:48px}
  .browse-search-loc{border-left:none;border-top:1px solid var(--border-subtle);padding-top:6px}
  .browse-search .btn{width:100%}
  .browse-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:var(--space-4)}
}

/* ── Rental requests ──────────────────────────────────────── */
.account-grid-solo{grid-template-columns:1fr}
.req-form{display:flex;flex-direction:column;gap:var(--space-5)}
/* The commitment on the page. It was one more item in an evenly spaced stack,
   the same distance from the payment choice as the payment choice was from the
   message box. */
.req-form > button[type=submit]{margin-top:var(--space-3)}
.req-form textarea{height:auto;min-height:60px;padding-top:9px;resize:vertical}
.req-form .field-narrow{max-width:96px}
.req-price{font:var(--text-body-sm);color:var(--text-muted);margin-top:6px}
.req-price strong{color:var(--ink-900)}
/* The finished bookings, folded. It borrows .report-box for the chevron and
   the quiet summary; what it adds is the gap above it, so the fold reads as a
   divider between what is running and what is over, and room for the rows once
   it is open. */
.past-requests{margin-top:var(--space-6)}
/* The Gesuche block is a second section, not a third list. It was carrying a
   hook class that no rule defined, so it sat as close to the bookings above it
   as those sat to each other; folding the finished ones away put it directly
   under the fold, where the two read as one control and its caption. */
.demand-mine-head{margin-top:var(--space-9)}
.past-requests > summary{font:var(--text-label-sm);color:var(--text-body)}
.past-requests[open] > summary{margin-bottom:var(--space-4)}
.board-task-row{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-bottom:4px}
.board-msg{font:var(--text-body-sm);color:var(--text-body);font-style:italic;margin:8px 0 12px;text-wrap:pretty}
.board-note{display:inline-flex;align-items:center;gap:6px;font:var(--text-body-sm);color:var(--text-muted)}
button.row-link{background:none;border:none;cursor:pointer;padding:0;font:var(--text-label-sm)}

/* ── Request hub (lifecycle page) ─────────────────────────── */
.req-hub-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-6);flex-wrap:wrap}
.req-timeline{display:flex;list-style:none;margin:0 0 var(--space-7);padding:0}
.req-tl-step{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;position:relative;font:var(--text-caption);color:var(--text-subtle);text-align:center}
.req-tl-step:not(:first-child)::before{content:"";position:absolute;top:13px;left:-50%;width:100%;height:2px;background:var(--border-default);z-index:0}
.req-tl-step.is-done::before,.req-tl-step.is-current::before{background:var(--status-success)}
.req-tl-dot{position:relative;z-index:1;display:inline-grid;place-items:center;width:26px;height:26px;border-radius:var(--radius-pill);background:var(--surface-card);border:1px solid var(--border-default);color:var(--text-subtle);font:var(--text-label-sm)}
.req-tl-step.is-current .req-tl-dot{border-color:var(--clay-600);background:var(--clay-600);color:#fff}
.req-tl-step.is-done .req-tl-dot{border-color:var(--status-success);background:var(--status-success);color:#fff}
.req-tl-step.is-current .req-tl-label{color:var(--text-strong);font-weight:600}
.req-hub-container{max-width:980px;margin:0 auto;padding:0 var(--layout-gutter)}
.req-hub-grid{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:var(--space-6);align-items:start}
.req-hub-main{display:flex;flex-direction:column;gap:var(--space-5);min-width:0}
.req-hub-side{display:flex;flex-direction:column;gap:var(--space-5)}
/* Every card on the request hub shares one padding, regardless of variant. */
.req-hub-grid .card{padding:var(--space-7)}
.req-hub-side .pc-terms{margin-bottom:var(--space-4)}
.req-hub-side .pc-terms > div:last-child{border-bottom:none;padding-bottom:0}
.req-stage{padding:var(--space-7)}
.req-stage h2{margin-bottom:8px}
.req-stage-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:var(--space-5)}
.req-stage-done{display:flex;align-items:center;gap:var(--space-5);background:var(--green-100);border-color:var(--green-100)}
.req-stage-warn{display:flex;align-items:flex-start;gap:var(--space-5);background:var(--gold-100);border-color:var(--gold-100)}
/* Same tint, but stacked — for panels that hold a heading, text and a form
   rather than an icon beside a sentence. */
.req-stage-alert{background:var(--gold-100);border-color:var(--gold-200,var(--gold-100))}
.req-stage-alert.is-bad{background:var(--red-100);border-color:var(--red-100)}
.req-stage-alert .req-problem{margin-top:var(--space-4)}
.req-stage-alert .form{margin-top:var(--space-4)}
.req-stage-alert .opt{display:block;margin-top:4px;font:var(--text-caption);color:var(--text-muted)}
.req-warn-ic{display:inline-grid;place-items:center;width:44px;height:44px;flex:none;border-radius:var(--radius-pill);background:var(--status-warning);color:#fff}
.req-return-form{margin-top:var(--space-5)}
.req-return-form .req-code-form{margin-top:0}
.req-problem{margin-top:var(--space-5);border-top:1px solid var(--border-subtle);padding-top:var(--space-4)}
.req-problem summary{cursor:pointer;display:inline-flex;align-items:center;gap:6px;font:var(--text-label-sm);color:var(--clay-700)}
.req-problem summary::-webkit-details-marker{display:none}
.req-problem textarea{width:100%;margin:var(--space-4) 0}
.req-problem[open] summary{margin-bottom:var(--space-2)}
.req-msg{font:var(--text-body);color:var(--text-body);font-style:italic;margin:var(--space-4) 0;text-wrap:pretty}
.req-code{display:flex;flex-direction:column;gap:6px;align-items:flex-start;margin-top:var(--space-5);background:var(--surface-sunken);border:1px dashed var(--border-default);border-radius:var(--radius-md);padding:var(--space-5) var(--space-6)}
.req-code-label{font:var(--text-caption);color:var(--text-subtle);text-transform:uppercase;letter-spacing:var(--tracking-overline)}
.req-code-value{font:var(--text-display-3);letter-spacing:10px;color:var(--ink-900);font-variant-numeric:tabular-nums}
.req-code-form{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:var(--space-5)}
.req-code-form .verify-code{
  flex:0 0 auto;width:calc(6ch + 96px);max-width:100%;height:var(--control-h-md);padding:0 10px;
  border:1px solid var(--border-default);border-radius:var(--radius-sm);background:var(--surface-card);
  color:var(--text-strong);font-family:var(--font-sans);font-size:24px;font-weight:600;
  letter-spacing:8px;text-indent:8px;text-align:center;font-variant-numeric:tabular-nums;outline:none}
.req-code-form .verify-code:focus{border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.req-code-form .verify-code::placeholder{color:var(--text-subtle);font-weight:400}
.star-input{display:inline-flex;flex-direction:row-reverse;justify-content:flex-end;gap:4px}
.star-input input{position:absolute;opacity:0;width:0;height:0}
.star-input label{color:var(--warm-300);cursor:pointer;line-height:1}
.star-input label:hover,.star-input label:hover ~ label,.star-input input:checked ~ label{color:var(--gold-600)}
/* Fill the active/selected stars (the icon is stroke-only by default). */
.star-input label:hover svg,.star-input label:hover ~ label svg,.star-input input:checked ~ label svg{fill:currentColor}
.stars{display:inline-flex;gap:2px;color:var(--warm-300);vertical-align:middle}
.stars .on{color:var(--gold-600)}
.stars .on svg{fill:currentColor}
.req-their-review{margin-top:var(--space-5);padding-top:var(--space-5);border-top:1px solid var(--border-subtle)}
.req-contact{margin-top:10px;display:flex;flex-direction:column;gap:8px}
.req-contact-name{font:var(--text-h4);color:var(--text-strong)}
.req-contact-row{display:flex;align-items:center;gap:8px;font:var(--text-body-sm);color:var(--text-body)}
.req-contact-row a{border-bottom:none}
.req-handover-notes{display:flex;gap:8px;font:var(--text-body-sm);color:var(--text-muted);background:var(--surface-sunken);padding:10px 12px;border-radius:var(--radius-sm);margin-top:6px}
@media (max-width:860px){
  .req-hub-grid{grid-template-columns:1fr}
  .req-tl-label{display:none}
}

.browse-card-rating{display:inline-flex;align-items:center;gap:4px;font:var(--text-label-sm);color:var(--gold-600)}
.browse-card-rating span{color:var(--text-subtle)}
.provider-rating{display:inline-flex;align-items:center;gap:4px;font:var(--text-body-sm);color:var(--gold-600);margin-top:4px}
.provider-rating span{color:var(--text-muted)}

/* ── v2 booking flow: thread, meetings, inbox, claims ─────────
   The hub is now a conversation with a state rail, so the main column is a
   fixed-height scroller and the rail carries the actions. */

/* Nav badge — unread messages, visible from any page */
.nav-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;margin-left:6px;border-radius:var(--radius-pill);background:var(--clay-600);color:var(--white);font:700 11px/1 var(--font-sans);font-variant-numeric:tabular-nums;vertical-align:2px}

/* ── Thread ─────────────────────────────────────────────────── */
.thread-card{display:flex;flex-direction:column;padding:0!important;overflow:hidden}
.thread-head{display:flex;align-items:center;gap:var(--space-4);padding:var(--space-5) var(--space-6);border-bottom:1px solid var(--border-subtle)}
.thread-head .t-h3{margin:0;flex:1}
.thread-live{font:var(--text-label-sm);color:var(--green-600)}

.thread-stream{display:flex;flex-direction:column;gap:var(--space-4);padding:var(--space-6);overflow-y:auto;min-height:340px;max-height:min(60vh,560px);background:var(--surface-sunken);scroll-behavior:smooth}
.thread-empty{margin:auto;max-width:38ch;text-align:center;font:var(--text-body-sm);color:var(--text-subtle)}

.thread-row{display:flex;justify-content:flex-start}
.thread-row.is-mine{justify-content:flex-end}
.thread-row.is-meeting{justify-content:center}

.bubble{max-width:min(78%,460px);background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-md);padding:var(--space-4) var(--space-5);box-shadow:var(--shadow-xs);position:relative}
.thread-row.is-mine .bubble{background:var(--ink-050);border-color:var(--ink-200)}
.bubble p{margin:0;font:var(--text-body-sm);color:var(--text-body);overflow-wrap:anywhere}
.bubble-who{font:var(--text-label-sm);color:var(--clay-600);margin-bottom:3px}
.bubble-time{display:block;margin-top:5px;font:var(--text-caption);font-size:11px;color:var(--text-subtle);text-align:right;font-variant-numeric:tabular-nums}
.bubble-photo{padding:6px 6px 4px}
.bubble-photo img{display:block;max-width:260px;width:100%;border-radius:var(--radius-sm)}
.bubble-photo a{border-bottom:none}

.thread-sys{display:flex;justify-content:center}
.thread-sys span{font:var(--text-caption);color:var(--text-subtle);background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-pill);padding:4px 14px;text-align:center}

.thread-composer{display:flex;flex-direction:column;gap:var(--space-3);padding:var(--space-5) var(--space-6);border-top:1px solid var(--border-subtle);background:var(--surface-card)}
.thread-composer textarea{width:100%;min-height:44px;max-height:160px;resize:none;padding:11px 14px;border:1px solid var(--border-default);border-radius:var(--radius-md);font:var(--text-body-sm);color:var(--text-body);background:var(--surface-card)}
.thread-composer textarea:focus{outline:none;border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.thread-composer-actions{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}
.thread-composer-actions .thread-send{margin-left:auto}
.thread-attach{position:relative;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border:1px solid var(--border-default);border-radius:var(--radius-sm);color:var(--text-muted);cursor:pointer;transition:color var(--dur-fast) var(--ease-standard),border-color var(--dur-fast) var(--ease-standard)}
.thread-attach:hover{color:var(--clay-600);border-color:var(--clay-400)}
.thread-attach:focus-within{border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.thread-attach-count{position:absolute;top:-6px;right:-6px;min-width:16px;height:16px;border-radius:var(--radius-pill);background:var(--clay-500);color:var(--white);font:700 10px/16px var(--font-sans);text-align:center}
.thread-closed{display:flex;align-items:center;gap:8px;margin:0;padding:var(--space-5) var(--space-6);border-top:1px solid var(--border-subtle);font:var(--text-body-sm);color:var(--text-subtle)}

/* ── Meeting cards ──────────────────────────────────────────── */
.meet-card{width:100%;max-width:420px;background:var(--surface-card);border:1px solid var(--border-default);border-left:3px solid var(--clay-500);border-radius:var(--radius-md);padding:var(--space-5);box-shadow:var(--shadow-sm)}
.meet-card.is-accepted{border-left-color:var(--green-600)}
.meet-card.is-cancelled,.meet-card.is-declined{border-left-color:var(--border-strong);opacity:.7}
.meet-card-head{display:flex;align-items:flex-start;gap:var(--space-4)}
.meet-ic{color:var(--clay-600);flex-shrink:0;margin-top:1px}
.meet-ic-sm{color:var(--text-subtle);flex-shrink:0}
.meet-kind{font:var(--text-label-sm);text-transform:uppercase;letter-spacing:var(--tracking-overline);color:var(--text-subtle)}
.meet-when{font:var(--text-h4);color:var(--text-strong)}
.meet-state{margin-left:auto;flex-shrink:0}
.meet-place{display:flex;align-items:flex-start;gap:7px;margin-top:var(--space-4);font:var(--text-body-sm);color:var(--text-body)}
.meet-buzzer{margin-top:var(--space-3);color:var(--text-muted)}
.meet-note{margin:var(--space-4) 0 0;font:var(--text-body-sm);color:var(--text-muted);font-style:italic}
.meet-actions{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;margin-top:var(--space-5)}
.meet-waiting{font:var(--text-caption);color:var(--text-subtle)}

/* Proposal dialog */
.meet-dialog{border:none;border-radius:var(--radius-lg);padding:0;max-width:520px;width:calc(100% - 32px);max-height:calc(100dvh - 48px);overflow:auto;overscroll-behavior:contain;background:var(--surface-card);box-shadow:var(--shadow-xl);color:var(--text-body)}
.meet-dialog::backdrop{background:rgba(43,39,34,.42)}
.meet-form{padding:var(--space-7)}
.meet-dialog-head{display:flex;align-items:center;gap:var(--space-4);margin-bottom:var(--space-6)}
.meet-dialog-head .t-h3{margin:0;flex:1}
.meet-dialog-x{background:none;border:none;cursor:pointer;color:var(--text-subtle);padding:4px;border-radius:var(--radius-xs)}
.meet-dialog-x:hover{color:var(--text-strong)}
.meet-place-choice{display:grid;gap:var(--space-3);margin-top:var(--space-3)}
@media (min-width:520px){.meet-place-choice{grid-template-columns:1fr 1fr}}
/* Scoped through its container for the same reason .cond-choices is: these are
   <label>s inside a fieldset.field, and `.field label` — a class plus an
   element — outranks a lone class and flattened the padding to nothing. */
.meet-place-choice .radio-card{padding:var(--space-4) var(--space-5)}
/* How the booking is paid: one line naming the methods, one saying the money
   is only reserved. The method itself is chosen on Stripe's page. */
.pay-track{margin:var(--space-3) 0 var(--space-4)}
.pay-track .t-label{margin:0 0 2px}
.pay-track .pc-note{margin:0}
.radio-card{display:flex;align-items:flex-start;gap:10px;padding:var(--space-4) var(--space-5);border:1px solid var(--border-default);border-radius:var(--radius-md);cursor:pointer;transition:border-color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard)}
.radio-card:hover{border-color:var(--clay-400)}
.radio-card:has(input:checked){border-color:var(--clay-500);background:var(--clay-100)}
.radio-card:focus-within{box-shadow:var(--focus-ring)}
.radio-card span{font:var(--text-label);color:var(--text-strong);display:flex;flex-direction:column;gap:3px;min-width:0;text-wrap:pretty}
.radio-card input{flex:none;margin-top:2px}
.radio-card small{font:var(--text-caption);color:var(--text-muted);font-weight:400}

/* ── Hub rail additions ─────────────────────────────────────── */
/* A deadline is the line you least want washed out: gold-600 read 2.62:1 on
   the tinted alert grounds it sits on. Same darker gold as the badges. */
.req-deadline{display:flex;align-items:center;gap:7px;margin:var(--space-4) 0 0;font:var(--text-body-sm);color:#8a6410}
.req-meet-summary{display:flex;flex-direction:column;gap:6px;margin:var(--space-4) 0 var(--space-5);padding:var(--space-4) var(--space-5);background:var(--surface-sunken);border-radius:var(--radius-md)}
.req-meet-when,.req-meet-where{display:flex;align-items:center;gap:7px;font:var(--text-body-sm);color:var(--text-body)}
.req-meet-when{font-weight:600;color:var(--text-strong)}
.req-meet-pending{font:var(--text-caption);color:#8a6410}
.req-code-locked{display:flex;align-items:center;gap:7px;margin:var(--space-4) 0 0;font:var(--text-body-sm);color:var(--text-subtle)}
.req-code-locked.is-spent{color:var(--red-600)}
.req-code-tries{display:flex;align-items:center;gap:7px;margin:var(--space-3) 0 0;font:var(--text-caption);color:var(--text-muted)}
.req-code-tries.is-low{color:var(--red-600)}
.req-code-tries .ic,.req-code-locked .ic{flex:none}
.req-contact-note{display:flex;align-items:flex-start;gap:7px;margin:var(--space-4) 0 0;font:var(--text-caption);color:var(--text-subtle)}
.req-cancel{margin-top:var(--space-5);padding-top:var(--space-4);border-top:1px solid var(--border-subtle);display:flex;flex-direction:column;gap:4px;align-items:flex-start}
.req-cancel-note{font:var(--text-caption);color:var(--text-subtle)}
.claim-amount{font:var(--text-price);color:var(--red-600);margin:var(--space-4) 0 var(--space-3)}
.ext-form{display:flex;gap:var(--space-3);align-items:center}
.ext-form input{width:72px;padding:8px 10px;border:1px solid var(--border-default);border-radius:var(--radius-sm);font:var(--text-body-sm);text-align:center}

/* ── Inbox ──────────────────────────────────────────────────── */
.inbox-filters{display:flex;gap:var(--space-3);margin-bottom:var(--space-6)}
.inbox-filter{padding:6px 14px;border-radius:var(--radius-pill);border:1px solid var(--border-default);font:var(--text-label-sm);color:var(--text-muted);background:var(--surface-card)}
.inbox-filter:hover{border-color:var(--clay-400);color:var(--clay-600)}
.inbox-filter.is-active{background:var(--ink-900);border-color:var(--ink-900);color:var(--paper-050)}

.inbox-list{display:flex;flex-direction:column;gap:var(--space-3)}
/* Three groups instead of one list ordered by last activity, which put a
   finished rental from March beside the request that arrived this morning. */
.inbox-group{display:flex;align-items:center;gap:8px;margin:var(--space-7) 0 var(--space-4);
  font:var(--text-label);color:var(--text-strong)}
.inbox-group:first-of-type{margin-top:0}
.inbox-count{display:inline-grid;place-items:center;min-width:20px;height:20px;padding:0 6px;
  border-radius:var(--radius-pill);background:var(--surface-sunken);
  font:var(--text-label-sm);color:var(--text-muted)}
.inbox-closed{margin-top:var(--space-7)}
.inbox-closed > summary{font:var(--text-label-sm);color:var(--text-body)}
.inbox-closed[open] > summary{margin-bottom:var(--space-4)}
.inbox-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:var(--space-5);padding:var(--space-5) var(--space-6);background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-md);box-shadow:var(--shadow-xs);color:inherit;transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard)}
.inbox-row:hover{border-color:var(--border-strong);box-shadow:var(--shadow-sm);color:inherit}
.inbox-row.is-mine{border-left:3px solid var(--clay-500)}
.inbox-ic{color:var(--ink-600);flex-shrink:0}
.inbox-body{display:flex;flex-direction:column;gap:5px;min-width:0}
.inbox-title{display:flex;align-items:center;gap:8px;font:var(--text-h4);color:var(--text-strong);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.inbox-unread{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:var(--radius-pill);background:var(--clay-600);color:var(--white);font:700 11px/1 var(--font-sans);font-variant-numeric:tabular-nums}
.inbox-meta{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;font:var(--text-caption);color:var(--text-muted)}
.inbox-role,.inbox-dates{display:inline-flex;align-items:center;gap:5px}
.inbox-next{display:flex;flex-direction:column;align-items:flex-end;gap:3px;text-align:right}
.inbox-action{font:var(--text-label-sm);color:var(--text-subtle)}
.inbox-action.is-mine{color:var(--clay-600)}
.inbox-amount{font:var(--text-caption);color:var(--text-muted);font-variant-numeric:tabular-nums}
.inbox-chev{color:var(--text-subtle);display:flex}

@media (max-width:640px){
  .inbox-row{grid-template-columns:auto minmax(0,1fr) auto;gap:var(--space-4)}
  .inbox-next{display:none}
}

/* ── Admin cases ────────────────────────────────────────────── */
.admin-jobs{margin-bottom:var(--space-7)}
.admin-job-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:var(--space-3);margin-top:var(--space-4)}
.admin-job{display:flex;flex-direction:column;gap:2px;padding:var(--space-3) var(--space-4);border:1px solid var(--border-subtle);border-radius:var(--radius-sm);font:var(--text-caption);color:var(--text-muted)}
.admin-job code{font-size:12px;color:var(--text-strong)}
.admin-job.is-stale{border-color:var(--gold-600);background:var(--gold-100)}
.admin-job.is-error{border-color:var(--red-600);background:var(--red-100)}
.admin-job em{color:var(--red-600);font-style:normal}
/* A case is somebody's deposit held while two accounts disagree. The card
   carries the same left rule the alarms do, because it is the same kind of
   thing: a queue item with money stopped behind it. */
.admin-case{margin-bottom:var(--space-5);padding:var(--space-6);
  border-left:4px solid var(--red-600)}
.admin-case-head{display:flex;align-items:flex-start;gap:var(--space-6);justify-content:space-between;flex-wrap:wrap}
.admin-case-head h3{margin:0 0 6px}
.admin-case-amount{text-align:right;display:flex;flex-direction:column;gap:2px}
.admin-case-amount strong{font:var(--text-price);color:var(--red-600)}
.admin-case-amount small{font:var(--text-caption);color:var(--text-subtle)}
.admin-thread{margin:var(--space-5) 0}
.admin-thread summary{cursor:pointer;font:var(--text-label-sm);color:var(--clay-600)}
.admin-thread-body{display:flex;flex-direction:column;gap:6px;margin-top:var(--space-4);max-height:320px;overflow-y:auto;padding:var(--space-4);background:var(--surface-sunken);border-radius:var(--radius-sm)}
.admin-msg{display:grid;grid-template-columns:130px 120px 1fr;gap:var(--space-4);font:var(--text-caption);color:var(--text-body)}
.admin-msg.is-sys{color:var(--text-subtle);font-style:italic}
.admin-msg-at{font-variant-numeric:tabular-nums;color:var(--text-subtle)}
.admin-msg-who{font-weight:600}
/* Where the decision is actually made. It was separated from the evidence above
   it by a hairline, which is the same weight the evidence uses between its own
   parts — so the one irreversible thing on the screen looked like another
   paragraph of it. */
.admin-decide{margin-top:var(--space-6);padding:var(--space-5);
  background:var(--surface-sunken);border:1px solid var(--border-default);
  border-radius:var(--radius-md);display:flex;flex-direction:column;gap:var(--space-4)}
.admin-decide .field{gap:5px}
.admin-decide label{font:var(--text-caption);color:var(--text-muted)}
.admin-decide .req-stage-actions{display:flex;gap:var(--space-3);flex-wrap:wrap;
  padding-top:var(--space-3);border-top:1px solid var(--border-subtle)}
.admin-decide .admin-hint{margin:0}

/* Meeting time: a slot list rather than a native spinner, plus the choice
   spelled back out so the weekday is visible before anyone agrees to it. */
.meet-time{font-variant-numeric:tabular-nums}
/* Date, time and duration belong together on one line — wrapping the duration
   onto its own row made the group read as two unrelated questions. */
.meet-form .field-row{display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:var(--space-4);align-items:end}
.meet-form .field-row .field,.meet-form .field-row .field-narrow{min-width:0}
/* On a phone the three-up row left the date field about 145px wide, which is
   narrower than iOS renders a native date control — the picker came out
   cramped and clipped. Give the date the full width and let the two short
   selects share the line below it. */
@media (max-width:560px){
  .meet-form{padding:var(--space-5)}
  .meet-form .field-row{grid-template-columns:1fr 1fr;gap:var(--space-4)}
  .meet-form .field-row > .field:first-child{grid-column:1 / -1}
}
/* iOS lays a date input out at its own intrinsic width and ignores the box
   unless the native appearance is dropped; without this the field is both the
   wrong width and vertically off-centre. */
.field input[type=date]{appearance:none;-webkit-appearance:none;line-height:normal;min-height:var(--control-h-md)}
.meet-when-preview{
  margin:calc(-1 * var(--space-3)) 0 var(--space-5);
  padding:10px 14px;
  background:var(--clay-100);
  border-radius:var(--radius-sm);
  font:var(--text-label);
  color:var(--clay-700);
  min-height:20px;
}
.meet-when-preview:empty{display:none}

/* Extension request: the same card language as a meeting proposal, because it
   is the same kind of thing — an offer in the thread that the other side
   accepts or declines, with the amount that matters to them on it. */
.ext-card{width:100%;max-width:420px;background:var(--surface-card);border:1px solid var(--border-default);border-left:3px solid var(--ink-600);border-radius:var(--radius-md);padding:var(--space-5);box-shadow:var(--shadow-sm)}
.ext-card.is-applied{border-left-color:var(--green-600)}
.ext-card.is-declined{border-left-color:var(--border-strong);opacity:.7}
.ext-card.is-awaiting_payment{border-left-color:var(--gold-600)}
.ext-card-head{display:flex;align-items:flex-start;gap:var(--space-4)}
.ext-ic{color:var(--ink-600);flex-shrink:0;margin-top:1px}
.ext-kind{font:var(--text-label-sm);text-transform:uppercase;letter-spacing:var(--tracking-overline);color:var(--text-subtle)}
.ext-when{font:var(--text-h4);color:var(--text-strong)}
.ext-state{margin-left:auto;flex-shrink:0}
.ext-money{margin:var(--space-4) 0 0;display:flex;flex-direction:column;gap:4px}
.ext-money div{display:flex;justify-content:space-between;gap:var(--space-4);font:var(--text-body-sm)}
.ext-money dt{color:var(--text-muted);margin:0}
.ext-money dd{margin:0;color:var(--text-body);font-variant-numeric:tabular-nums}
.ext-money strong{color:var(--text-strong)}
.ext-note{display:flex;align-items:flex-start;gap:7px;margin:var(--space-4) 0 0;font:var(--text-caption);color:var(--text-muted)}
.ext-waiting{margin:var(--space-4) 0 0;font:var(--text-caption);color:var(--text-subtle)}
.ext-actions{display:flex;align-items:center;gap:var(--space-4);flex-wrap:wrap;margin-top:var(--space-5)}

/* The quote block in the renter's dialog — the number they are agreeing to. */
.ext-quote{margin:var(--space-5) 0;padding:var(--space-5);background:var(--surface-sunken);border-radius:var(--radius-md);display:flex;flex-direction:column;gap:8px}
.ext-quote-row{display:flex;justify-content:space-between;gap:var(--space-4);font:var(--text-body-sm);color:var(--text-muted)}
.ext-quote-row strong{color:var(--text-strong);font-variant-numeric:tabular-nums}
.ext-quote-row.is-total{padding-top:8px;border-top:1px solid var(--border-subtle)}
.ext-quote-row.is-total strong{font:var(--text-price);color:var(--ink-900)}

/* The pending extension repeated in the rail: same card, no second frame. */
.req-ext-pending .ext-card{max-width:none;border:0;border-left:3px solid var(--ink-600);border-radius:0 var(--radius-sm) var(--radius-sm) 0;box-shadow:none;padding:var(--space-4) 0 var(--space-4) var(--space-5);margin-top:var(--space-4)}
.req-ext-pending .ext-card.is-awaiting_payment{border-left-color:var(--gold-600)}

.ext-money .is-total{padding-top:6px;margin-top:2px;border-top:1px solid var(--border-subtle)}
.req-invoices{display:flex;flex-direction:column;gap:var(--space-3);margin-top:var(--space-4)}
/* These rows carry a label AND an invoice number in a sidebar column barely
   wide enough for one of them. A `.btn` is nowrap, fixed-height and
   overflow-visible, so "Rechnung Verlängerung LN-2026-000043" pushed the
   number clean outside the pill's border. Let the row grow and the number
   drop to a second line instead — it stays whole, which matters for a
   number someone reads off to their accountant. */
.req-invoices .btn{justify-content:flex-start;gap:4px 8px;flex-wrap:wrap;
  height:auto;min-height:var(--control-h-sm);padding-top:8px;padding-bottom:8px;
  white-space:normal;text-align:left;border-radius:var(--radius-md)}
/* Always its own line, not just when it happens not to fit: otherwise the row
   changes shape between one document and the next, and between DE and EN. */
.req-invoice-no{flex:1 0 100%;text-align:right;font:var(--text-caption);color:var(--text-subtle);font-variant-numeric:tabular-nums;white-space:nowrap}

/* ── Backoffice ───────────────────────────────────────────────
   Deliberately unlike the member site: dense, monochrome, no marketing
   chrome. The dark bar is a constant reminder that this view acts on
   everyone's live data. */
.admin-body{background:var(--paper-100);color:var(--text-body)}
/* The band that says "this is not the member view". A hairline of the brand
   colour along the bottom, because the bar is otherwise the same dark block as
   any other application chrome and this one is acting on live money. */
.admin-bar{background:var(--ink-900);color:var(--paper-050);position:sticky;top:0;z-index:40;
  box-shadow:var(--shadow-md);border-bottom:2px solid var(--clay-500)}
.admin-bar-in{max-width:1400px;margin:0 auto;padding:0 var(--space-6);display:flex;align-items:center;gap:var(--space-7);height:56px}
.admin-brand{font:600 14px/1 var(--font-sans);color:var(--paper-050);white-space:nowrap}
.admin-brand span{opacity:.55;font-weight:400}
.admin-nav{display:flex;gap:var(--space-2, 6px);flex:1;flex-wrap:wrap}
/* A hit area rather than a word: the nav items were text with a 2px underline,
   so the only thing you could aim at was the glyphs themselves. */
.admin-nav a{font:600 13.5px/1 var(--font-sans);color:rgba(255,255,255,.62);
  padding:8px 11px;border-radius:var(--radius-sm);border-bottom:none;
  transition:color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard)}
.admin-nav a:hover{color:#fff;background:rgba(255,255,255,.08)}
.admin-nav a.is-active{color:var(--ink-900);background:var(--paper-050)}
.admin-nav a:focus-visible,.admin-out:focus-visible,.admin-logout:focus-visible{
  outline:2px solid var(--clay-400);outline-offset:2px}
.admin-bar-end{display:flex;align-items:center;gap:var(--space-5);white-space:nowrap}
.admin-out{font:400 12.5px/1 var(--font-sans);color:rgba(255,255,255,.55);border-bottom:none}
.admin-out:hover{color:#fff}
.admin-who{font:600 12.5px/1 var(--font-sans);color:rgba(255,255,255,.8)}
.admin-logout{background:none;border:1px solid rgba(255,255,255,.28);color:rgba(255,255,255,.85);font:600 12px/1 var(--font-sans);padding:7px 12px;border-radius:var(--radius-sm);cursor:pointer}
.admin-logout:hover{background:rgba(255,255,255,.1);color:#fff}

.admin-main{max-width:1400px;margin:0 auto;padding:var(--space-7) var(--space-6) var(--space-12)}
.admin-wrap{display:flex;flex-direction:column;gap:var(--space-5)}
/* The page's own title, and the sentence under it that says what the screen is
   for. They were the same size as the section headings below them, so a screen
   opened without a clear first thing to read. */
.admin-h1{font:600 27px/1.2 var(--font-sans);letter-spacing:-.01em;color:var(--ink-900);margin:0;
  display:flex;align-items:center;gap:var(--space-4);flex-wrap:wrap}
.admin-h2{font:600 12px/1.3 var(--font-sans);letter-spacing:.09em;text-transform:uppercase;color:var(--text-subtle);margin:var(--space-6) 0 var(--space-3);display:flex;align-items:center;gap:8px}
.admin-count{background:var(--surface-sunken);border-radius:var(--radius-pill);padding:2px 8px;font:600 11px/1.4 var(--font-sans);color:var(--text-muted);letter-spacing:0}
/* A link inside a section heading. The dashboard reached for .admin-out, which
   is the top bar's white-on-dark link — on a light heading it was white text
   sitting on top of the heading it followed. */
.admin-h2 a{margin-left:auto;font:600 11px/1.3 var(--font-sans);letter-spacing:.04em;
  color:var(--clay-700);border-bottom:none;white-space:nowrap}
.admin-h2 a:hover{color:var(--clay-500)}
.admin-hint{font:var(--text-body-sm);color:var(--text-muted);margin:calc(var(--space-4) * -1) 0 0;max-width:74ch;text-wrap:pretty}
.admin-back{font:var(--text-caption);color:var(--text-muted);border-bottom:none}
.admin-back:hover{color:var(--clay-600)}
.admin-empty{padding:var(--space-7) var(--space-6);background:var(--surface-card);
  border:1px dashed var(--border-default);border-radius:var(--radius-md);
  color:var(--text-muted);font:var(--text-body-sm);display:flex;align-items:center;
  justify-content:center;gap:10px;text-align:center;text-wrap:pretty}
.admin-empty a{color:var(--clay-700);font-weight:600}
.admin-empty.is-error{color:var(--red-600);border-color:var(--red-600)}

/* Something is wrong and somebody has to act. A left rule rather than a full
   red border: three of these stacked read as an error page, and they are a
   queue. */
.admin-alarm{display:flex;gap:var(--space-4);align-items:center;padding:var(--space-5) var(--space-6);
  background:var(--red-100);border:1px solid var(--red-100);border-left:4px solid var(--red-600);
  border-radius:var(--radius-md);color:var(--warm-900);font:var(--text-body-sm);
  transition:border-color var(--dur-fast) var(--ease-standard)}
a.admin-alarm:hover{border-color:var(--red-600);color:var(--warm-900)}
.admin-alarm b{display:block}
.admin-alarm svg{color:var(--red-600);flex-shrink:0}

.admin-figures{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:var(--space-4)}
.admin-figure{background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-md);padding:var(--space-5);display:flex;flex-direction:column;gap:3px;box-shadow:var(--shadow-xs)}
.admin-figure.is-warn{border-color:var(--gold-600);background:var(--gold-100)}
.admin-figure-l{font:600 11px/1.3 var(--font-sans);letter-spacing:.06em;text-transform:uppercase;color:var(--text-subtle)}
.admin-figure-v{font:600 21px/1.2 var(--font-sans);color:var(--ink-900);font-variant-numeric:tabular-nums}
.admin-figure-h{font:var(--text-caption);color:var(--text-subtle)}

.admin-cols{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-7)}
@media (min-width:1040px){.admin-cols{grid-template-columns:minmax(0,1fr) 340px}}

.admin-queue{display:flex;flex-direction:column;gap:var(--space-3)}
.admin-queue-row{display:flex;align-items:center;gap:var(--space-4);padding:var(--space-4) var(--space-5);background:var(--surface-card);border:1px solid var(--border-subtle);border-left:3px solid var(--border-strong);border-radius:var(--radius-sm);color:inherit}
.admin-queue-row:hover{border-color:var(--border-strong);color:inherit}
.admin-queue-row.is-high{border-left-color:var(--red-600)}
.admin-queue-row.is-medium{border-left-color:var(--gold-600)}
.admin-queue-body{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
.admin-queue-t{font:600 14px/1.4 var(--font-sans);color:var(--text-strong)}
.admin-queue-d{font:var(--text-caption);color:var(--text-muted)}
.admin-queue-id{font:600 12px/1 var(--font-mono,ui-monospace);color:var(--text-subtle)}

.admin-statuses{display:flex;flex-direction:column;gap:2px}
.admin-status{display:flex;justify-content:space-between;padding:7px 11px;border-radius:var(--radius-xs);font:var(--text-body-sm);color:var(--text-body);border-bottom:none}
.admin-status:hover{background:var(--surface-sunken);color:var(--clay-600)}
.admin-status span{font-variant-numeric:tabular-nums;color:var(--text-muted)}
.admin-status-l{color:var(--text-body)}

.admin-jobs-list{display:flex;flex-direction:column;gap:1px}
.admin-job-row{display:flex;justify-content:space-between;gap:var(--space-4);padding:5px 9px;border-radius:var(--radius-xs);font:var(--text-caption);color:var(--text-muted)}
.admin-job-row.is-stale{background:var(--gold-100);color:var(--gold-600)}
.admin-job-row.is-error{background:var(--red-100);color:var(--red-600)}
.admin-joberr{font:var(--text-caption);color:var(--red-600);margin:6px 0 0}

/* ── Back-office actions ──────────────────────────────────
   The screens where something is decided rather than read. A row of controls,
   the ones that need a reason folded behind their own button, and the panel of
   facts beside them. */
.admin-col-main{min-width:0;display:flex;flex-direction:column}
.admin-side{min-width:0;display:flex;flex-direction:column}
.admin-actions-row{display:flex;align-items:flex-start;gap:var(--space-4);flex-wrap:wrap}
.admin-hint-inline{font:var(--text-caption);color:var(--text-muted);align-self:center;max-width:44ch}
/* A destructive action that wants a reason asks for it where it is pressed,
   rather than on a page of its own. */
.admin-drop{position:relative}
.admin-drop > summary{list-style:none;cursor:pointer}
.admin-drop > summary::-webkit-details-marker{display:none}
.admin-drop-form{display:flex;flex-direction:column;gap:var(--space-3);margin-top:var(--space-3);
  padding:var(--space-5);background:var(--surface-card);border:1px solid var(--border-default);
  border-radius:var(--radius-md);max-width:520px}
.admin-drop-form label{font:var(--text-caption);color:var(--text-muted)}
.admin-drop-form button{align-self:flex-start}

.admin-form{display:flex;flex-direction:column;gap:var(--space-4);padding:var(--space-5);
  background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-md);
  max-width:640px}
.admin-field{display:flex;flex-direction:column;gap:5px;min-width:0}
.admin-field label{font:var(--text-caption);color:var(--text-muted)}
.admin-field .admin-opt{color:var(--text-subtle)}
.admin-field input,.admin-field select,.admin-field textarea{width:100%;padding:9px 12px;
  border:1px solid var(--border-default);border-radius:var(--radius-sm);background:var(--surface-card);
  font:var(--text-body-sm);color:var(--text-body)}
.admin-field textarea,.admin-drop-form textarea{resize:vertical;line-height:1.5;padding:9px 12px;
  border:1px solid var(--border-default);border-radius:var(--radius-sm);background:var(--surface-card);
  font:var(--text-body-sm);color:var(--text-body);width:100%}
.admin-field input:focus,.admin-field select:focus,.admin-field textarea:focus,
.admin-drop-form textarea:focus{outline:none;border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.admin-field.is-narrow{max-width:140px}
.admin-field-row{display:grid;grid-template-columns:1fr 140px;gap:var(--space-4)}
@media (max-width:640px){.admin-field-row{grid-template-columns:1fr}}
.admin-form button{align-self:flex-start}

/* The facts beside the actions. .admin-kv already existed as the container for
   these — nine places use it — so this only gives it a card to sit in rather
   than redefining what it means. Two rules for one class is how a page ends up
   rendering to whichever happens to come last in the file. */
.admin-panel{background:var(--surface-card);border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);padding:var(--space-3) var(--space-5)}
.admin-panel .admin-kv b,.admin-panel .admin-kv a{word-break:break-word}
/* The note is the sentence somebody typed, so it wraps rather than stretching
   the table to the width of the longest one. */
.admin-log-note{max-width:52ch;white-space:normal;text-wrap:pretty;color:var(--text-body)}
/* Two actions on one table row: the common one, and the way to the rest. */
.admin-row-actions{display:inline-flex;align-items:center;gap:var(--space-3)}
.admin-row-actions .btn{border-bottom:none}

/* ── A report waiting for a decision ──────────────────────
   Five classes the template asked for and no stylesheet defined, so the
   moderation queue — where a listing is taken down and both sides are told
   why — was the only screen in the product rendering as unstyled markup. */
.admin-report{padding:var(--space-6);display:flex;flex-direction:column;gap:var(--space-4);
  border-left:4px solid var(--gold-600)}
.admin-report + .admin-report{margin-top:var(--space-4)}
.admin-report-head{display:flex;justify-content:space-between;gap:var(--space-5);
  align-items:flex-start;flex-wrap:wrap}
.admin-report-title{font:600 15px/1.4 var(--font-sans);color:var(--text-strong);
  display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}
.admin-report-meta{margin-top:4px;font:var(--text-caption);color:var(--text-muted);line-height:1.7}
.admin-report-meta a{color:var(--clay-700);border-bottom:none}
/* What the reporter actually wrote, set apart — it is the evidence, not chrome. */
.admin-report-details{margin:0;padding:var(--space-4) var(--space-5);
  background:var(--surface-sunken);border-radius:var(--radius-sm);
  font:var(--text-body-sm);color:var(--text-body);text-wrap:pretty}
.admin-report-form{display:flex;flex-direction:column;gap:var(--space-3)}
.admin-report-form textarea{width:100%;padding:9px 12px;border:1px solid var(--border-default);
  border-radius:var(--radius-sm);background:var(--surface-card);font:var(--text-body-sm);
  color:var(--text-body);resize:vertical;line-height:1.5}
.admin-report-form textarea:focus{outline:none;border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.admin-report-actions{display:flex;gap:var(--space-3);flex-wrap:wrap}

/* What the back office already did to this thing. */
.admin-trail{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-3)}
.admin-trail li{display:flex;flex-direction:column;gap:2px;padding:var(--space-4);
  background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-sm);
  border-left:3px solid var(--clay-400)}
.admin-trail-a{font:600 13px/1.4 var(--font-sans);color:var(--text-strong)}
.admin-trail-m{font:var(--text-caption);color:var(--text-subtle)}
.admin-trail-n{font:var(--text-caption);color:var(--text-body);margin-top:3px;text-wrap:pretty}

/* The controls that narrow a list, in a strip of their own so they read as one
   thing rather than as loose widgets above a table. */
.admin-filters{display:flex;gap:var(--space-3);align-items:center;flex-wrap:wrap;
  padding:var(--space-4) var(--space-5);background:var(--surface-card);
  border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
.admin-filters select{padding:9px 12px;border:1px solid var(--border-default);border-radius:var(--radius-sm);font:var(--text-body-sm);background:var(--surface-card);color:var(--text-body)}
/* The search box is the shared component; only its width is the back office's
   business. Its own padding and border come with it. */
.admin-filters .searchfield{min-width:260px}
.admin-filters .searchfield input{height:38px;font:var(--text-body-sm)}
.admin-clear{font:var(--text-caption);color:var(--text-subtle)}

/* ── Back-office tables ───────────────────────────────────
   Fifteen tables across nine screens, and all but two were a bare <table>
   with no class on it — browser defaults inside a designed shell, which is
   most of why the back office looked unfinished next to the site it
   administers. Styled here, at the shell, so every one of them is the same
   table rather than nine pages each solving it again.

   .table-scroll is the container four of them already asked for and no
   stylesheet defined, so a wide table simply ran off the page. */
.table-scroll{overflow-x:auto;background:var(--surface-card);
  border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
.admin-main table{width:100%;border-collapse:collapse;font-size:13.5px;
  color:var(--text-body);background:var(--surface-card)}
.admin-main :not(.table-scroll) > table{border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
.admin-main thead th{position:sticky;top:0;z-index:1;
  padding:10px 13px;text-align:left;white-space:nowrap;
  background:var(--surface-sunken);color:var(--text-subtle);
  font:600 11px/1.4 var(--font-sans);letter-spacing:.06em;text-transform:uppercase;
  border-bottom:1px solid var(--border-default)}
.admin-main tbody td{padding:9px 13px;border-bottom:1px solid var(--border-subtle);vertical-align:middle}
.admin-main tbody tr:last-child td{border-bottom:none}
.admin-main tbody tr:hover{background:var(--paper-050)}
/* Figures line up on their digits, and the header sits over them. */
.admin-main .num-col{text-align:right;font-variant-numeric:tabular-nums}
.admin-main th.num-col{text-align:right}
.admin-main tbody td a{border-bottom:none;color:var(--clay-700);font-weight:600}
.admin-main tbody td a:hover{color:var(--clay-500);text-decoration:underline}

.admin-table{font-size:13.5px}
.admin-table td{padding:9px 13px}
.admin-table tr.is-flagged{background:var(--red-100)}
.admin-table tr.is-muted{opacity:.5}
/* A date range is one thing and should not be broken across two lines. */
.admin-table .nowrap-col{white-space:nowrap}
/* An absent value, said rather than left blank: an empty cell reads as a
   rendering fault, and half these columns are legitimately empty. */
.admin-none{color:var(--text-subtle)}

/* How much of the list you are seeing, and how to reach the rest. The tables
   took the newest hundred rows and said nothing about the others. */
.admin-pager{display:flex;align-items:center;justify-content:space-between;gap:var(--space-5);
  flex-wrap:wrap;margin:var(--space-5) 0;font:var(--text-body-sm);color:var(--text-muted)}
.admin-pager-count strong{color:var(--text-strong);font-variant-numeric:tabular-nums}
.admin-pager-nav{display:flex;align-items:center;gap:var(--space-4)}
.admin-pager-nav a,.admin-pager-nav .is-off{display:inline-flex;align-items:center;gap:5px;
  padding:6px 12px;border:1px solid var(--border-default);border-radius:var(--radius-sm);
  font:var(--text-label-sm);background:var(--surface-card)}
.admin-pager-nav a{color:var(--text-strong)}
.admin-pager-nav a:hover{border-color:var(--clay-400);color:var(--clay-700)}
.admin-pager-nav .is-off{color:var(--text-subtle);opacity:.55}
.admin-pager-of{font-variant-numeric:tabular-nums}

.admin-kv{display:flex;flex-direction:column;gap:1px}
.admin-kv > div{display:flex;justify-content:space-between;gap:var(--space-4);padding:7px 0;border-bottom:1px solid var(--border-subtle);font:var(--text-body-sm)}
.admin-kv > div:last-child{border-bottom:0}
.admin-kv span{color:var(--text-muted)}
.admin-kv b,.admin-kv code,.admin-kv a{color:var(--text-strong);text-align:right;font-variant-numeric:tabular-nums}
.admin-kv b.is-bad{color:var(--red-600)}
.admin-wrapid{word-break:break-all;font-size:11.5px}
.admin-action{margin-top:var(--space-4)}
.admin-quote{font:var(--text-body-sm);font-style:italic;color:var(--text-muted);margin:var(--space-3) 0 0;padding-left:var(--space-4);border-left:2px solid var(--border-default)}

.admin-thread{display:flex;flex-direction:column;gap:5px;max-height:520px;overflow-y:auto;padding:var(--space-5);background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
.admin-thread .admin-msg{display:grid;grid-template-columns:88px 116px 1fr;gap:var(--space-4);font:var(--text-caption);color:var(--text-body);align-items:baseline}
.admin-thread .admin-msg.is-sys{color:var(--text-subtle);font-style:italic}
.admin-msg-at{font-variant-numeric:tabular-nums;color:var(--text-subtle)}
.admin-msg-who{font-weight:600;overflow:hidden;text-overflow:ellipsis}
.admin-msg-body{overflow-wrap:anywhere}

.admin-login-body{display:grid;place-items:center;min-height:100vh;background:var(--ink-900)}
.admin-login{width:min(400px,calc(100% - 32px));background:var(--surface-card);border-radius:var(--radius-lg);padding:var(--space-8);box-shadow:var(--shadow-xl)}
.admin-login-head{margin-bottom:var(--space-6)}
.admin-login .admin-brand{color:var(--ink-900);font-size:16px}
.admin-login .admin-brand span{opacity:.5}

/* A frozen standoff outranks everything else in the case list: until it is
   decided, neither party's money can move at all. */
.admin-case.is-frozen{border-left:3px solid var(--red-600)}
.admin-case.is-frozen .admin-case-amount strong{color:var(--red-600)}

/* A frozen deposit is the only thing on the dashboard that nothing else can
   resolve — it gets its own banner and its own colour. */
.admin-alarm.is-frozen{background:var(--red-100);border-color:var(--red-600);color:var(--warm-900);align-items:center;text-decoration:none}
.admin-alarm.is-frozen:hover{border-color:var(--red-600);color:var(--warm-900)}
.admin-alarm.is-frozen b{display:block}
.admin-alarm-go{margin-left:auto;white-space:nowrap;font:600 13px/1 var(--font-sans);color:var(--red-600)}
.admin-figure.is-bad{border-color:var(--red-600);background:var(--red-100)}
.admin-figure.is-bad .admin-figure-v{color:var(--red-600)}

/* Said where the decision is made, not in terms nobody reads. */
.pc-warn{display:flex;align-items:flex-start;gap:7px;margin:var(--space-4) 0 var(--space-5);padding:10px 12px;background:var(--gold-100);border-radius:var(--radius-sm);font:var(--text-caption);color:var(--warm-800)}
.pc-warn svg{color:var(--gold-600);flex-shrink:0;margin-top:1px}
/* Public date check on the listing page: a visitor can ask whether the device
   is free before anybody asks them to register. .pc-free is the yes; .pc-warn
   above already carries the no. */
.pc-dates{margin:var(--space-5) 0 var(--space-3)}
/* A native date input puts its value hard left and its picker hard right, so
   the wider the box the more empty rail sits between them. Trimmed padding
   closes some of it; the rest is Chrome's own spacing between the date
   segments and the picker button, and is not reachable from here.
   The columns stay flexible on purpose — sizing them to the input's intrinsic
   width made the pair unshrinkable and pushed the whole rail 30px wider than a
   phone, which is a horizontal scrollbar traded for a few pixels of gap. */
.pc-dates .field-row{gap:var(--space-4)}
.pc-dates input[type=date]{min-width:0;padding:0 10px}

.pc-free{display:flex;align-items:flex-start;gap:7px;margin:var(--space-3) 0 var(--space-4);padding:10px 12px;background:var(--sage-100,var(--paper-100));border-radius:var(--radius-sm);font:var(--text-caption);color:var(--warm-800)}
.pc-free svg{color:var(--green-600,var(--clay-700));flex-shrink:0;margin-top:1px}

/* The identity gate is three parts — the reason, the button, how long it takes —
   and it had no rule of its own, so it took whatever the browser gave it: the
   reason wrapping its second line back under the icon, and the footnote pinned
   four pixels below a large button while a much wider gap sat above it. The
   icon holds a column of its own now, and the gaps say what belongs to what —
   16px down into the button, 8px from the button to its own footnote. No tint:
   the card already has one sunken panel, and a second would read as another
   figure rather than as the reason for the button under it. */
.pc-verify-why{display:flex;align-items:flex-start;gap:9px;margin:0 0 var(--space-5);
  font:var(--text-body-sm);color:var(--text-body);text-wrap:pretty}
.pc-verify-why svg{color:var(--ink-600);flex-shrink:0;margin-top:3px}
.pc-verify form{margin:0}
.pc-verify .pc-note{margin-top:var(--space-3);text-wrap:pretty}
.error-detail{margin-top:var(--space-6);padding:var(--space-5);background:var(--surface-sunken);border-radius:var(--radius-sm);font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--text-body);white-space:pre-wrap;overflow-x:auto}

/* ── Inserat melden (DSA notice-and-action) ────────────────────
   Deliberately quiet — it is a safety valve, not a feature to advertise —
   but it had no styling at all: no card, no padding, a full-width button and
   the browser's native disclosure triangle, which appears nowhere else here.
   It keeps the sidebar's card rhythm; the muted, small summary is what makes
   it recede, not the absence of a container. */
.report-box{background:var(--surface-card);border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg);padding:var(--space-5) var(--space-6)}
.report-box > summary{display:flex;align-items:center;gap:7px;cursor:pointer;
  list-style:none;color:var(--text-muted);font:var(--text-body-sm)}
.report-box > summary::-webkit-details-marker{display:none}
.report-box > summary:hover{color:var(--text-body)}
.report-box > summary .ic{color:var(--text-subtle);flex:none}
/* Own chevron, matching the one on the selects. */
.report-box > summary::after{content:"";flex:none;margin-left:auto;width:7px;height:7px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:translateY(-2px) rotate(45deg);
  transition:transform var(--dur-fast) var(--ease-standard)}
.report-box[open] > summary::after{transform:translateY(1px) rotate(-135deg)}
.report-box[open] > summary{margin-bottom:var(--space-5);color:var(--text-body)}
.report-form textarea{resize:vertical;min-height:76px}
/* A small secondary action, not a full-width primary one. */
.report-form .btn{align-self:flex-start}

/* ── Foto-Studio ──────────────────────────────────────────────
   The before/after card is a sibling of the tile it belongs to, inside the
   same grid, so it has to claim the whole row — otherwise it lands in a
   120px column next to the thumbnails and reads as a third photo. */
.studio-pair{grid-column:1 / -1;display:grid;grid-template-columns:1fr 1fr;gap:12px;
  align-items:start;padding:var(--space-5);background:var(--surface-sunken);
  border-radius:var(--radius-md);border:1px solid var(--border-subtle)}
.studio-pair figure{margin:0}
.studio-pair img{width:100%;aspect-ratio:1;object-fit:contain;background:var(--paper-050);
  border-radius:var(--radius-sm);border:1px solid var(--border-subtle);display:block}
.studio-pair figcaption{margin-top:6px;font:var(--text-caption);color:var(--text-muted);text-align:center}
.studio-pair .studio-actions{grid-column:1 / -1;display:flex;gap:10px;align-items:center}
.studio-pair.is-done{grid-template-columns:1fr;padding:var(--space-4) var(--space-5);background:none;border:none}

/* The tile whose proposal is on screen, and the one currently being worked on. */
.photo-tile.has-proposal{border-color:var(--clay-500);box-shadow:0 0 0 2px var(--clay-100)}
.photo-tile.is-busy{opacity:.5}
.photo-tile.is-busy::after{content:"";position:absolute;inset:0;
  background:linear-gradient(100deg,transparent 20%,rgba(255,255,255,.55) 50%,transparent 80%);
  animation:studio-sweep 1.1s linear infinite}
@keyframes studio-sweep{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
@media (prefers-reduced-motion:reduce){.photo-tile.is-busy::after{animation:none}}
.photo-tile.studio-failed{border-color:var(--red-600)}
/* Sits opposite the "Zustand" badge so the two never stack on one photo. */
.photo-badge-studio{left:auto;right:8px;bottom:8px;display:inline-flex;align-items:center;gap:4px;
  background:rgba(143,74,38,.9)}

.studio-bar{display:flex;align-items:center;gap:var(--space-5);flex-wrap:wrap;
  padding:var(--space-5) var(--space-6);margin-bottom:var(--space-4);
  background:var(--clay-100);border-radius:var(--radius-md)}
.studio-bar-text{flex:1;min-width:220px}
.studio-bar .check-title{display:flex;align-items:center;gap:7px;color:var(--clay-700)}
.studio-bar .check-desc{display:block;margin-top:2px}
.studio-actions .btn .ic{width:15px;height:15px}

/* --- Discovery landing pages (§4) -----------------------------------------
   Breadcrumbs, and the link/fact lists that carry the internal-link
   architecture §21 asks for. The trail is an <ol> because it is an ordered
   path, not a menu — the numbering is semantic and only the marker is hidden. */
.crumbs{margin:0 0 var(--space-5)}
.crumbs ol{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;
  align-items:center;gap:6px;font:var(--text-caption);color:var(--text-muted)}
.crumbs li{display:flex;align-items:center;gap:6px}
.crumbs li + li::before{content:"›";color:var(--border-strong);line-height:1}
.crumbs a{color:var(--text-muted);text-decoration:none}
.crumbs a:hover{color:var(--clay-700);text-decoration:underline}
.crumbs [aria-current="page"]{color:var(--ink-900)}

.disc-links{list-style:none;margin:0 0 var(--space-7);padding:0;
  display:flex;flex-wrap:wrap;gap:8px}
.disc-links li{margin:0}
.disc-links a,.disc-links li:not(:has(a)){display:inline-block;
  padding:6px 12px;border-radius:var(--radius-pill);
  background:var(--surface-sunken);border:1px solid var(--border-subtle);
  font:var(--text-body-sm);color:var(--ink-900);text-decoration:none}
.disc-links a:hover{border-color:var(--clay-500);color:var(--clay-700)}

.disc-uses{margin:0 0 var(--space-7);padding-left:1.15em;
  font:var(--text-body);color:var(--ink-900)}
.disc-uses li{margin-bottom:4px}
.disc-note{margin:0 0 var(--space-7);color:var(--text-muted)}

/* --- Pagination (§63) -----------------------------------------------------
   Real links, so they need real affordance: a visible current page, generous
   hit targets, and a disabled step that still occupies its space so the row
   does not shift as you move through it. */
.pager{display:flex;align-items:center;justify-content:center;gap:var(--space-4);
  flex-wrap:wrap;margin:var(--space-8) 0 var(--space-4)}
.pager-nums{list-style:none;display:flex;gap:4px;margin:0;padding:0}
.pager-num,.pager-step{
  display:inline-flex;align-items:center;gap:6px;min-width:38px;height:38px;
  padding:0 12px;justify-content:center;border-radius:var(--radius-sm);
  font:var(--text-label);color:var(--ink-900);text-decoration:none;
  border:1px solid transparent}
.pager-num:hover,.pager-step:hover{background:var(--surface-sunken)}
.pager-num.is-on{background:var(--ink-900);color:var(--paper-050);cursor:default}
.pager-step.is-off{color:var(--text-subtle);pointer-events:none}
.pager-gap{display:inline-flex;align-items:center;padding:0 4px;color:var(--text-subtle)}
.pager-count{text-align:center;font:var(--text-caption);color:var(--text-muted);
  margin:0 0 var(--space-8)}

/* --- Consent banner (§71, TTDSG §25) --------------------------------------
   A bar, not an overlay. §71 forbids putting the page behind a consent
   interaction, so nothing here dims, blocks or traps focus — the content is
   fully readable and fully crawlable with the banner still sitting there. */
.consent{position:sticky;bottom:0;z-index:50;
  background:var(--ink-900);color:var(--paper-050);
  box-shadow:0 -4px 20px rgba(11,45,95,.18)}
.consent-inner{max-width:var(--layout-max);margin:0 auto;
  padding:var(--space-5) var(--layout-gutter);
  display:flex;align-items:center;gap:var(--space-6);flex-wrap:wrap}
.consent-text{flex:1;min-width:260px;margin:0;font:var(--text-body-sm);color:var(--ink-100)}
.consent-text a{color:var(--paper-050);text-decoration:underline}
.consent-actions{display:flex;gap:10px;flex-shrink:0}
/* The banner ground is navy, so .btn-primary's navy fill disappears into it.
   Both answers are restyled for this surface — and restyled to the SAME
   weight, because a decline that reads as the lesser option is not a free
   choice, which is the point of asking. */
.consent-actions .btn{border-width:1px;box-shadow:none}
.consent-actions .btn-primary{--_bg:var(--clay-500);--_fg:var(--white);--_bd:var(--clay-500)}
.consent-actions .btn-primary:hover{--_bg:var(--clay-700);--_bd:var(--clay-700)}
.consent-actions .btn-secondary{--_bg:transparent;--_fg:var(--paper-050);--_bd:var(--ink-300)}
.consent-actions .btn-secondary:hover{--_bg:rgba(255,255,255,.1);--_bd:var(--paper-050);--_fg:var(--white)}
@media (max-width:600px){
  .consent-actions{width:100%}
  .consent-actions .btn{flex:1}
}
/* The withdrawal control sits inline in the footer legal row and has to read
   as one of those links, not as a form. */
.consent-withdraw{display:inline}
.consent-withdraw button{background:none;border:0;padding:0;cursor:pointer;
  font:inherit;color:inherit;text-decoration:underline}

/* --- Date filter (§61) ----------------------------------------------------
   Sits in the search bar beside the query and location fields. Two native
   date inputs rather than a custom picker: they work with a keyboard, with a
   screen reader and with JavaScript off, which is the same reason the rest of
   this page is plain forms. */
/* A date field's width is dictated by the date and the picker button inside
   it, not by how much bar is going spare, so this group takes the width it
   needs and the query and location fields — which truncate gracefully and are
   the ones with something to say — flex around it. Sharing the slack evenly
   squeezed dd.mm.yyyy down to dd.mm. */
.browse-search-dates{display:flex;align-items:center;gap:6px;flex:0 0 auto}
.browse-search-dates input[type="date"]{
  border:0;background:none;font:var(--text-body-sm);color:var(--ink-900);
  width:auto;padding:0}
.browse-search-dates input[type="date"]:focus{outline:none}
.browse-date-sep{color:var(--text-subtle);flex-shrink:0}
/* The label is what an empty date field says on a browser that draws no
   dd.mm.yyyy of its own, which is every iOS one, so it is text on the page
   rather than something the input is trusted to render. */
.browse-date{display:flex;align-items:center;gap:6px;flex:0 0 auto;cursor:pointer}
.browse-date-label{font:var(--text-caption);color:var(--text-subtle);flex:none}
@media (max-width:820px){
  .browse-search-dates{width:100%;flex:1 1 100%}
}
@media (max-width:560px){
  /* Two dates, their labels and a dash do not sit on one phone-width line
     without each date losing its last digits, so they take a row each and the
     dash — which only ever meant "to" — gives way to the labels that say it. */
  .browse-search-dates{flex-wrap:wrap;align-items:stretch;row-gap:0}
  /* The group's calendar icon wrapped to a line of its own once the dates
     stacked, and it was saying nothing the labels do not: each row already
     carries the browser's own picker button on its right. */
  .browse-search-dates .ic{display:none}
  .browse-search-dates input[type="date"]{width:100%;min-width:0}
  .browse-date{flex:1 1 100%;min-width:0}
  .browse-date-label{min-width:34px}
  .browse-date-sep{display:none}
}

/* --- Long-form document pages ---------------------------------------------
   The terms, privacy policy, Impressum, withdrawal form, prohibited items,
   ranking explanation and FAQ all share this wrapper.

   They had no rules at all, and site.css zeroes the margin on every heading
   and paragraph — so seven pages of legal prose rendered as one unbroken
   block with headings glued to the text above them. Nobody reads a document
   like that; they scan it looking for one answer, and there was nothing to
   scan by.

   The rhythm is deliberately asymmetric: a heading sits much closer to the
   text beneath it than to the text above. That is what makes a section read
   as one unit rather than as a label floating between two walls of prose. */
.legal-page{
  /* The measure belongs on the container, not on each child: `ch` resolves
     against the element's OWN font size, so 68ch on a 34px heading is 68
     characters of 34px type — about 1500px, which is not a measure at all.
     Here it resolves once, against the inherited 16px, and every child
     inherits the result. The gutter is added back so the TEXT is ~66
     characters rather than the box. */
  max-width:calc(66ch + 2 * var(--layout-gutter));
  padding-bottom:var(--space-9);
}

.legal-page h1{margin-bottom:var(--space-3)}

/* The version line. Quiet, but it is load-bearing on a legal document — it is
   how a reader knows which version they agreed to. */
.legal-page .legal-meta{
  font:var(--text-caption);
  color:var(--text-subtle);
  margin:0 0 var(--space-9);
  padding-bottom:var(--space-5);
  border-bottom:1px solid var(--border-subtle);
}

.legal-page h2{
  margin:var(--space-9) 0 var(--space-4);
  color:var(--ink-900);
  scroll-margin-top:var(--space-8);   /* in case a heading is ever linked */
}
.legal-page h3{margin:var(--space-7) 0 var(--space-3);color:var(--ink-900)}

/* The first heading follows the version rule, which already provides the
   separation — a second gap there reads as a missing paragraph. */
.legal-page > h2:first-of-type{margin-top:0}

/* The FAQ builds its own rhythm: each answer is a bordered block, and the
   question sits tight against it. Stated explicitly rather than left to
   :first-of-type, which happened to produce the right result only because
   every .faq-item contains exactly one h2 — true today, and silently wrong
   the day one of them gains a sub-heading. */
.legal-page .faq-item h2{margin-top:0}

.legal-page p{margin:0 0 var(--space-5);color:var(--warm-800)}
.legal-page p:last-child{margin-bottom:0}

/* Inline emphasis carries most of the structure in these documents — the
   "Konto:", "Buchungen:", "Stripe" labels are the scannable part. */
.legal-page strong,
.legal-page b{color:var(--ink-900);font-weight:600}

.legal-page ul,
.legal-page ol{margin:0 0 var(--space-5);padding-left:1.35em;color:var(--warm-800)}
.legal-page li{margin-bottom:var(--space-3)}
.legal-page li:last-child{margin-bottom:0}
.legal-page li > ul,
.legal-page li > ol{margin-top:var(--space-3)}

.legal-page a{text-decoration:underline;text-underline-offset:2px}

/* An address block: a German Anschrift is lines, not a paragraph. */
.legal-page address{font-style:normal;white-space:pre-line;margin:0 0 var(--space-5)}

.legal-page table{width:100%;border-collapse:collapse;margin:0 0 var(--space-6);font:var(--text-body-sm)}
.legal-page th,
.legal-page td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--border-subtle);vertical-align:top}
.legal-page th{font:var(--text-label);color:var(--ink-900)}

@media (max-width:600px){
  .legal-page h2{margin-top:var(--space-8)}
}

/* --- FAQ (§50) ------------------------------------------------------------
   The FAQ wears .legal-page, so every rule above applies to it: document
   paragraph spacing, an indented list, a heading rhythm meant for prose read
   in order. This page is written to be jumped into instead, and it was losing
   the argument — these rules used to sit further up the file, so at equal
   specificity the document rules won on source order alone. The answer
   paragraphs took a document's bottom margin and the question index was
   indented like a bulleted list inside its own box. They live here now, after
   what they are overriding. */

.faq-index{margin:var(--space-7) 0 0;padding:var(--space-5) var(--space-6);
  background:var(--surface-sunken);border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
/* Columns rather than a grid: a grid row is as tall as its tallest cell, so
   every question that wrapped to two lines gave its one-line neighbour a
   double-height box and the column drifted out of rhythm. Column flow packs
   each entry to its own height and reads down one column and on to the next.
   A column-width, not a count, so it becomes a single column on a phone. */
.faq-index ul{margin:0;padding:0;list-style:none;
  columns:16rem;column-gap:var(--space-6)}
.faq-index li{margin:0 0 var(--space-3);break-inside:avoid}
.faq-index li:last-child{margin-bottom:0}
.faq-index a{color:var(--text-link);text-decoration:none;font-size:.95rem}
.faq-index a:hover{color:var(--text-link-hover);text-decoration:underline}

/* An anchored answer should not land under the sticky header. */
.faq-item{scroll-margin-top:96px}
/* One question per block, separated enough to be scanned rather than read
   start to finish — the legal documents next door are written to be read in
   order, this page is written to be jumped into. */
.faq-list{margin-top:var(--space-8)}
.faq-item + .faq-item{margin-top:var(--space-7);padding-top:var(--space-7);border-top:1px solid var(--border-subtle)}
.faq-item h2{margin:0 0 var(--space-3)}
/* Every answer sits the same distance from its question and from the link
   under it, whether or not that link is there — read off the document rule,
   the gap depended on the paragraph happening to be the last child. */
.faq-item p{margin:0}
/* The more-link is one of those paragraphs, so it has to out-specify the rule
   that zeroes them; an !important here used to do the same job. */
.faq-item .faq-more{margin-top:var(--space-3)}

/* The shared CTA pair is built for the error pages, where the paragraph above
   it carries the separation. After a list of answers there is no such
   paragraph, and the buttons sat flush against the last one. */
.faq-list + .error-actions{margin-top:var(--space-9)}

/* --- Discovery page body --------------------------------------------------
   The city, district and category pages are documents with sections too: a
   grid of devices, then what people rent this for, then the equipment, then
   the safety note, then where else to look.

   Every one of those headings had margin:0, because site.css zeroes headings
   globally and nothing here put it back — so each section title sat flush
   against the list above it and the page read as one long column with bold
   words scattered through it. The rhythm is the same asymmetric one the
   legal pages use: a heading belongs to what follows it. */
.disc-body > h2{margin:var(--space-9) 0 var(--space-5);color:var(--ink-900)}
.disc-body > h2:first-child{margin-top:0}

/* The grid already carries its own bottom spacing through the pager; without
   one it needs its own. */
.disc-body > .browse-grid{margin-bottom:var(--space-7)}
.disc-body > .browse-grid:last-child{margin-bottom:0}

.disc-body > p{margin:0 0 var(--space-6);max-width:66ch;color:var(--warm-800)}

/* German compounds are long, and a display-size "Datenschutzerklärung" or
   "Verbotene Gegenstände" on a 320px screen is one word away from pushing the
   page sideways. Nothing overflows today — measured — but a longer document
   title is a content change, not a code change, and this costs nothing until
   the day it is needed. */
.legal-page h1,
.legal-page h2,
.legal-page h3,
.disc-body > h2{overflow-wrap:break-word}

/* --- Long-form legal structure --------------------------------------------
   The terms run to 42 numbered clauses across six parts. At that length the
   part dividers have to read as a level above the clauses, or the document is
   just 48 headings in a row. */
.legal-page .legal-part{
  margin:var(--space-11) 0 var(--space-7);
  padding-top:var(--space-6);
  border-top:2px solid var(--ink-900);
  color:var(--ink-900);
}
.legal-page .legal-part:first-of-type{margin-top:var(--space-9)}

/* Sub-lists lettered (a), (b) … because the clauses reference them that way —
   "Ziffer 20.2(b)" has to be findable. */
.legal-page ol.legal-alpha{list-style:lower-alpha}

/* The fee formulas in clause 8.4: a small block, set apart, so the arithmetic
   reads as arithmetic rather than as a sentence that happens to contain plus
   signs. */
.legal-page .legal-formula{
  background:var(--surface-sunken);
  border-left:3px solid var(--clay-500);
  border-radius:var(--radius-sm);
  padding:var(--space-5) var(--space-6);
  margin:0 0 var(--space-5);
  font:var(--text-body-sm);
  line-height:1.9;
}
.legal-page .legal-formula strong{color:var(--ink-900)}

/* --- Page hero ------------------------------------------------------------
   .section-hero was being used by four templates and defined by none of them.
   /leihen looked right only because it also carries .browse-hero, which
   supplies the padding; the three discovery pages used .section-hero alone and
   got zero — their breadcrumb sat flush against the site header with a 0px gap.

   Defined here with the values .browse-hero already used, so that page is
   unchanged and the others gain the spacing they should always have had. */
.section-hero{padding:var(--space-10) 0 var(--space-9)}

/* The hero's call to action needs air above it — the count line directly above
   carries no bottom margin, so the two were touching. */
.section-hero .hero-actions{margin-top:var(--space-6)}

/* A section following a hero must not add its full 96px on top of the hero's
   own 46px — that put 142px between the button and the first heading. This is
   the same correction .browse-body already makes for /leihen, and the same
   value, so the two pages share a rhythm. */
.disc-section{padding-top:var(--space-8)}

/* --- Listing assist ------------------------------------------------------
   The device-name box above the custom listing form. Deliberately reads as a
   helper rather than part of the record: it sits outside the form that saves
   anything, and nothing it fills in is final. */
.assist-card{margin-bottom:var(--space-5);border-left:3px solid var(--clay-500)}
.assist-row{display:flex;gap:var(--space-3);align-items:stretch}
.assist-row input{flex:1;min-width:0}
.assist-row .btn{flex:none;white-space:nowrap}
.assist-notes{margin-bottom:var(--space-5);padding:var(--space-5) var(--space-6);background:var(--surface-sunken)}
.assist-notes p{margin:0 0 var(--space-3);color:var(--ink-900)}
.assist-notes ul{margin:0;padding-left:1.35em;color:var(--warm-800)}
@media (max-width:520px){
  .assist-row{flex-direction:column}
}

/* Busy state for the listing suggestion. The call is a round trip to a
   language model, so it takes seconds; a button that only greys out reads as
   a button that failed. Added by JS on submit, so without JS none of this
   applies and the form simply posts. */
.assist-btn[disabled]{opacity:.75;cursor:progress}
.assist-card.is-busy .assist-btn::before{
  content:"";
  width:14px;height:14px;flex:none;
  /* .btn is inline-flex with gap:8px, so the pseudo-element is a flex item and
     the gap already spaces it — a margin here would double that. */
  border:2px solid currentColor;
  border-top-color:transparent;
  border-radius:50%;
  animation:assist-spin .7s linear infinite;
}
.assist-card.is-busy .assist-btn svg{display:none}
.assist-card.is-busy input{opacity:.7}
@keyframes assist-spin{to{transform:rotate(360deg)}}
/* Someone who asked for less motion gets a static ring rather than none: the
   point is that the control looks occupied, and that survives without spin. */
@media (prefers-reduced-motion:reduce){
  .assist-card.is-busy .assist-btn::before{animation:none;border-top-color:currentColor;opacity:.6}
}

/* ── Wizard steps ─────────────────────────────────────────────
   The six-screen listing flow. Nothing here is a new visual language: the
   step rail is the registration rail, the tiles are the editor's tiles, and
   the preview is the browse card. What is new is the shape of each screen —
   few enough fields to answer without scrolling to see how much is left. */

/* Condition as three named choices with the sentence that defines each. The
   segmented control could not carry the sentence, and the sentence is the
   part a claim is later argued against. */
.cond-choices{display:grid;gap:var(--space-3)}
/* Scoped through .cond-choices, not written as .cond-choice alone. These are
   <label>s inside a fieldset.field, and `.field label` — which exists to stop a
   field's own caption carrying padding — is one class plus one element, so it
   outranked a single class and flattened the padding to nothing. The boxes were
   drawn with their text against all four edges. */
.cond-choices .cond-choice{position:relative;display:grid;gap:2px;
  padding:var(--space-4) var(--space-5);cursor:pointer;
  border:1px solid var(--border-subtle);border-radius:var(--radius-md);background:var(--surface-card)}
.cond-choice input{position:absolute;opacity:0;width:0;height:0}
.cond-choice:hover{border-color:var(--clay-400)}
/* Driven by the radio, the way .radio-card above already does it. The selected
   box used to be marked by a class PHP wrote at render time and nothing ever
   updated, so clicking moved the (invisible) radio and left the highlight on
   the previous answer: it looked like the click did nothing, and the box that
   stayed lit was no longer the one that would be submitted. A state that is
   read from the input cannot drift from it. */
.cond-choices .cond-choice:has(input:checked){border-color:var(--clay-500);box-shadow:0 0 0 2px var(--clay-100)}
/* The keyboard reaches the radio, not the label, and the radio is clipped out
   of sight — without this, tabbing through the three has no visible position. */
.cond-choices .cond-choice:focus-within{border-color:var(--clay-500);box-shadow:var(--focus-ring)}
.cond-name{font:var(--text-body);font-weight:600;color:var(--text-strong)}
.cond-desc{font:var(--text-body-sm);color:var(--text-muted)}

/* The fields most people do not know offhand, out of the way of the ones
   everybody does. */
.more-fields{border-top:1px solid var(--border-subtle);padding-top:var(--space-5);margin-top:var(--space-2)}
.more-fields > summary{cursor:pointer;font:var(--text-body-sm);font-weight:600;color:var(--clay-700);list-style:none}
.more-fields > summary::-webkit-details-marker{display:none}
.more-fields > summary::before{content:"+ ";font-weight:700}
.more-fields[open] > summary::before{content:"− "}
.more-fields > summary:hover{color:var(--clay-500)}
.more-fields > *:not(summary){margin-top:var(--space-5)}

/* An anchor before the empty box: what similar devices go for, so the price
   is a choice rather than a guess. */
.price-anchor{padding:var(--space-6);margin-bottom:var(--space-6)}
.pa-label{display:block;font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;
  color:var(--text-subtle);margin-bottom:var(--space-4)}
.pa-scale{display:flex;justify-content:space-between;gap:var(--space-4);
  border-top:2px solid var(--border-subtle);padding-top:var(--space-4)}
.pa-point{display:grid;gap:2px;text-align:center;flex:1;font:var(--text-body-sm);color:var(--text-muted)}
.pa-point strong{font:var(--text-h3);color:var(--text-strong)}
.pa-point.is-mid strong{color:var(--clay-600)}

/* Named shots, counted off. An empty uploader gets one photo of the front;
   naming the four that earn rentals is what changes that. */
.shot-list{padding:var(--space-6);margin-bottom:var(--space-6)}
.shot-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-4)}
.shot-items{list-style:none;margin:0;padding:0;display:grid;gap:var(--space-3)}
.shot-item{display:flex;align-items:center;gap:10px;font:var(--text-body-sm);color:var(--text-muted)}
.shot-item.is-done{color:var(--text-strong)}
.shot-tick{display:inline-grid;place-items:center;width:22px;height:22px;flex:none;border-radius:var(--radius-pill);
  border:1px solid var(--border-subtle);background:var(--surface-sunken);color:var(--text-subtle)}
.shot-item.is-done .shot-tick{border-color:var(--status-success);background:var(--status-success);color:#fff}
.wizard-nav{margin-top:var(--space-6);align-items:center}

/* The real browse card, at the width it is really seen at. */
.preview-stage{max-width:320px;margin:0 auto var(--space-6)}
/* The pre-flight list. It was seven rows of label-and-value pushed to opposite
   ends with the edit link trailing the value as loose text — so "1 Bearbeiten"
   read as one phrase, and a value long enough to wrap (the accessory list
   always is) dropped the link into the middle of a sentence.

   Three columns instead: the label in a fixed one so the values start on a
   line, the value free to wrap inside its own, and the link parked at the
   right where it is the same target on every row. Rules between rows, because
   this is a list somebody is checking item by item. */
.preview-facts{padding:var(--space-6) var(--space-7);margin-bottom:var(--space-6)}
.preview-facts h2{margin:0 0 var(--space-2)}
.preview-facts dl{display:grid;margin:0}
.pv-row{display:grid;grid-template-columns:minmax(0,10rem) 1fr;gap:var(--space-4);
  align-items:baseline;padding:var(--space-4) 0;font:var(--text-body-sm);
  border-top:1px solid var(--border-subtle)}
.preview-facts dt{color:var(--text-muted);text-wrap:pretty}
.preview-facts dd{margin:0;display:flex;align-items:baseline;gap:var(--space-4)}
.pv-val{min-width:0;font-weight:600;color:var(--text-strong);text-wrap:pretty}
/* Never in the text: always the last thing on the row, at a fixed size. */
.pv-edit{flex:none;margin-left:auto;display:inline-flex;align-items:center;gap:4px;
  font:var(--text-label-sm);color:var(--text-muted);border-bottom:none;white-space:nowrap}
.pv-edit:hover{color:var(--clay-600)}
.pv-edit .ic{color:var(--text-subtle)}
.pv-edit:hover .ic{color:var(--clay-600)}

@media (max-width:560px){
  /* The label stops being a column of its own before it starts hyphenating. */
  .pv-row{grid-template-columns:1fr;gap:2px}
  .preview-facts dd{gap:var(--space-3)}
}

/* Advice, never a gate: everything here can be ignored and the button below
   still publishes. */
.advice-card{padding:var(--space-6);margin-bottom:var(--space-6);background:var(--paper-050)}
.advice-list{list-style:none;margin:var(--space-4) 0;padding:0;display:grid;gap:var(--space-3)}
.advice-list li{display:flex;align-items:flex-start;gap:8px;font:var(--text-body-sm);color:var(--text-muted)}
.advice-list li .ic{flex:none;margin-top:3px;color:var(--clay-600)}

.done-card{padding:var(--space-8);text-align:center}
.done-ic{display:inline-grid;place-items:center;width:64px;height:64px;margin-bottom:var(--space-5);
  border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700)}
.done-media{max-width:280px;margin:var(--space-6) auto;border-radius:var(--radius-md);overflow:hidden}
.done-media img{width:100%;height:auto;display:block}
.done-next{list-style:none;margin:var(--space-6) 0;padding:0;display:grid;gap:var(--space-3);justify-items:center}
.done-next li{display:flex;align-items:center;gap:8px;font:var(--text-body-sm);color:var(--text-muted)}
.done-next li .ic{color:var(--status-success)}
.done-actions{display:grid;gap:var(--space-4);justify-items:center}

@media (max-width:640px){
  .pa-scale{gap:var(--space-2)}
  .pa-point strong{font:var(--text-body)}
  .preview-stage{max-width:none}
}

/* ── Mobile tab bar ───────────────────────────────────────────
   Four destinations in one tap, with listing a device as the one that is a
   button. It was two taps behind a hamburger, for the action a marketplace that
   needs supply depends on most. Phone only — the hamburger keeps the full menu;
   this is the short list, not a replacement for it.

   One accent on the bar. The active tab is ink, the three quiet ones subtle, and
   the only clay is the small filled plus — it used to be a raised 46px disc that
   poked into the page above, and the active tab used the same clay, so on the
   browse page two items glowed and neither read as "you are here". */
.tabbar{display:none}
@media (max-width:720px){
  .tabbar{position:fixed;left:0;right:0;bottom:0;z-index:50;
    display:grid;grid-template-columns:repeat(4,1fr);
    background:rgba(250,246,239,.96);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
    border-top:1px solid var(--border-subtle);
    padding:4px 0 calc(4px + env(safe-area-inset-bottom))}
  .tab{display:grid;justify-items:center;gap:2px;padding:6px 4px 4px;
    font:500 11px/1.2 var(--font-sans);letter-spacing:.01em;
    color:var(--text-subtle);text-align:center;min-width:0;border-bottom:none}
  .tab-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
  .tab-ic{position:relative;display:inline-grid;place-items:center;width:28px;height:28px}
  .tab.is-active{color:var(--ink-900)}
  .tab-badge{position:absolute;top:-2px;right:-6px;min-width:16px;height:16px;padding:0 4px;
    border-radius:var(--radius-pill);background:var(--clay-500);color:#fff;
    font:600 10px/16px var(--font-sans);text-align:center}
  /* The one item that is a button rather than a destination: icon-sized, in
     the row, filled. */
  .tab-cta .tab-ic{border-radius:var(--radius-pill);background:var(--clay-500);color:#fff}
  /* Room for the bar, so it never covers the last thing on a page. */
  body{padding-bottom:72px}
  /* Two calls to action stacked in the menu is one too many when the bar
     already carries this one. */
  .nav-cta{display:none}
}

/* ── Starting a listing ───────────────────────────────────────
   Two ways in, because people arrive holding two different things: a name they
   remember, or the device itself. The grid of every catalogue model is what is
   left when neither is true — it used to be the only option. */
.start-ways{display:grid;gap:var(--space-5);margin-bottom:var(--space-8)}
.start-search{display:flex;gap:var(--space-3);align-items:center}
.start-search .searchfield{flex:1;min-width:0}
.start-photo{display:grid;gap:var(--space-4)}
/* The button is for anyone whose browser did not submit on pick, and for
   keyboard use. It is not the primary way in. */
.pd-go{justify-self:start}

.identified{display:flex;gap:var(--space-6);align-items:center;padding:var(--space-6);margin-bottom:var(--space-5)}
.id-media{flex:none;width:132px;aspect-ratio:1;border-radius:var(--radius-md);overflow:hidden;background:var(--paper-100)}
.id-media img{width:100%;height:100%;object-fit:cover;display:block}
.id-body{min-width:0;display:grid;gap:var(--space-3)}
.id-label{font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;color:var(--text-subtle)}
/* The answer, in the size it is read at. It was briefly a permanently open text
   field, which made a yes/no question look like a form and pushed the reason
   the field existed into small print underneath. */
.id-said{display:grid;gap:var(--space-3)}
.id-name{margin:0;text-wrap:balance}
/* The correction, once asked for. It takes the heading's place rather than
   appearing beside it, so the card does not grow a second name. */
.id-edit{display:grid;gap:4px}
.id-edit-label{font:var(--text-label-sm);color:var(--text-body)}
.id-title{width:100%;height:var(--control-h-md);padding:0 12px;
  font:var(--text-body);color:var(--text-body);
  background:var(--surface-card);border:1px solid var(--border-default);border-radius:var(--radius-sm);
  outline:none;transition:border-color var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard)}
.id-title:focus{border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.id-edit .field-hint{margin-top:0}

@media (max-width:640px){
  .start-search{flex-wrap:wrap}
  .start-search input{flex-basis:100%}
  .identified{flex-direction:column;align-items:flex-start}
  .id-media{width:100%;aspect-ratio:16/10}
}

/* ── Dashboard: operating a listing, not just owning one ──────
   A row used to be a title, a price and a score out of 100. It says what the
   listing did, what is stopping it, and what to do about it — the score is
   gone from the surface entirely, because it was the one number a lender
   could read and not act on. */
.filter-tabs{display:flex;flex-wrap:wrap;gap:var(--space-3);margin-bottom:var(--space-6)}
.ftab{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border-radius:var(--radius-pill);
  border:1px solid var(--border-subtle);background:var(--surface-card);
  font:var(--text-body-sm);font-weight:600;color:var(--text-muted)}
.ftab:hover{border-color:var(--clay-400);color:var(--clay-600)}
.ftab.is-on{background:var(--ink-900);border-color:var(--ink-900);color:#fff}
.ftab-n{font-weight:500;opacity:.7}

.listing-perf{display:flex;flex-wrap:wrap;gap:var(--space-5);margin-top:var(--space-3);
  font:var(--text-body-sm);color:var(--text-muted)}
.listing-perf strong{color:var(--text-strong)}

.row-alert{display:flex;gap:10px;align-items:flex-start;margin-top:var(--space-4);
  padding:var(--space-4);border-radius:var(--radius-md);
  background:var(--red-100);border:1px solid var(--border-subtle)}
.row-alert .ic{flex:none;margin-top:2px;color:var(--red-600)}
.row-alert strong{display:block;font:var(--text-body-sm);font-weight:600;color:var(--text-strong)}
/* The freshness question is a question, not a fault. */
.row-alert-soft{background:var(--paper-050)}
.row-alert-soft .ic{color:var(--clay-600)}
.row-alert-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-4);margin-top:var(--space-3)}

.row-advice{margin-top:var(--space-3)}
.row-advice > summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:6px;
  font:var(--text-body-sm);font-weight:600;color:var(--clay-700)}
.row-advice > summary::-webkit-details-marker{display:none}
.row-advice > summary:hover{color:var(--clay-500)}
.row-advice ul{margin:var(--space-3) 0 0;padding-left:18px;display:grid;gap:6px;
  font:var(--text-body-sm);color:var(--text-muted)}

.listing-until{font:var(--text-body-sm);color:var(--text-muted)}
.pause-form{margin:0}
/* A summary that looks like plain text is a control nobody presses. */
.pause-when > summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:5px;
  padding:5px 12px;border:1px solid var(--border-subtle);border-radius:var(--radius-pill);
  font:var(--text-body-sm);font-weight:600;color:var(--text-muted);background:var(--surface-card)}
.pause-when > summary::after{content:"▾";font-size:10px;opacity:.7}
.pause-when[open] > summary::after{content:"▴"}
.pause-when > summary::-webkit-details-marker{display:none}
.pause-when > summary:hover{color:var(--clay-600);border-color:var(--clay-400)}
.pause-when[open]{display:grid;gap:6px;justify-items:end;margin-top:var(--space-3)}
.pause-when input[type=date]{font:var(--text-body-sm)}
.pause-when .field-hint{text-align:right;max-width:24ch}

/* ── Price tiers ──────────────────────────────────────────
   Three bands, three prices, and what they add up to. A section on the page
   now rather than a disclosure: the numbers arrive filled in, so there is
   something to read rather than something to go and find.

   The boxes were a bare number input with the unit floating loose beside it,
   at a width that left the browser's spinner sitting on top of the digits.
   The unit is inside the frame, the field owns its focus ring, and the row is
   a grid so the three line up whatever their labels are. */
.tier-block{margin:var(--space-6) 0 0}
.tier-title{margin:0 0 4px;font:var(--text-label);color:var(--text-strong)}
.tier-block .tier-grid{display:grid;gap:var(--space-3);margin:var(--space-5) 0}
.tier-row{display:grid;grid-template-columns:1fr auto;align-items:center;gap:var(--space-4)}
.tier-row label{font:var(--text-body-sm);font-weight:600;color:var(--text-strong)}
/* The frame lives on the wrapper so the unit sits inside it. */
.tier-input{display:flex;align-items:center;gap:2px;width:140px;padding:0 12px 0 0;
  background:var(--surface-card);border:1px solid var(--border-default);
  border-radius:var(--radius-sm);
  transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard)}
.tier-input:focus-within{border-color:var(--border-focus);box-shadow:var(--focus-ring)}
.tier-input input{width:100%;min-width:0;height:var(--control-h-md);padding:0 4px 0 12px;
  text-align:right;border:0;background:none;box-shadow:none;font:var(--text-body);color:var(--text-body)}
.tier-input input:focus{border:0;box-shadow:none;outline:none}
/* The spinner overlapped the digits at this width and offers nothing the
   number itself does not — these are prices, typed. */
.tier-input input::-webkit-outer-spin-button,
.tier-input input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.tier-input input[type=number]{-moz-appearance:textfield;appearance:textfield}
.tier-unit{flex:none;font:var(--text-body-sm);color:var(--text-muted);white-space:nowrap}
.tier-actions{display:flex;align-items:center;gap:var(--space-4);flex-wrap:wrap}
.tier-actions .field-hint{margin-top:0}

/* What the ladder costs and pays, for lengths people actually book. */
.tier-example{margin-top:var(--space-5);padding:var(--space-5);
  background:var(--surface-sunken);border-radius:var(--radius-md)}
.tier-table{width:100%;border-collapse:collapse;margin:var(--space-3) 0 6px}
.tier-table th,.tier-table td{padding:7px 0;text-align:right;font:var(--text-body-sm);color:var(--text-body)}
.tier-table thead th{font:var(--text-caption);color:var(--text-subtle);font-weight:600;
  border-bottom:1px solid var(--border-subtle)}
.tier-table th:first-child,.tier-table tbody th{text-align:left;font-weight:600;color:var(--text-strong)}
.tier-table tbody td:last-child{color:var(--ink-900);font-weight:600}
.tier-table tbody tr + tr th,.tier-table tbody tr + tr td{border-top:1px solid var(--border-subtle)}

@media (max-width:520px){
  .tier-row{grid-template-columns:1fr}
  .tier-input{width:100%}
}

/* The ladder on the listing page, where the weekend-or-week decision is made. */
/* The ladder in a 380px column. Every row said "pro Tag" after its price, so
   the headline's unit was repeated three times inside a rail with no room for
   it, and the band, price and discount ran together on one 23px line. The unit
   is stated once, above; the rows are a grid so the prices align. */
.pc-tiers{list-style:none;margin:var(--space-3) 0 0;padding:0;display:grid;gap:2px}
.pc-tiers li{display:grid;grid-template-columns:1fr auto auto;align-items:baseline;
  gap:var(--space-3);padding:5px 0;font:var(--text-body-sm);color:var(--text-muted)}
.pc-tiers li strong{color:var(--text-strong);font-variant-numeric:tabular-nums}
.pc-tiers-head{display:flex;justify-content:space-between;gap:var(--space-3);
  margin-top:var(--space-5);padding-bottom:6px;border-bottom:1px solid var(--border-subtle);
  font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;
  color:var(--text-subtle)}
.pc-off{flex:none;font:var(--text-label-sm);color:var(--clay-700);
  background:var(--clay-100);border-radius:var(--radius-pill);padding:2px 7px}

/* ── Handover hours ───────────────────────────────────────────
   Two rows, weekday and weekend, each a pair of times. */
.hours-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-3)}
.hours-label{font:var(--text-body-sm);font-weight:600;color:var(--text-strong)}
.hours-pair{display:flex;align-items:center;gap:8px}
.hours-pair input{width:120px}
.hours-dash{color:var(--text-subtle)}

/* ── Technical facts ──────────────────────────────────────────
   The same table wherever specs come from — the curated catalogue or a
   lender's own lines — so a free-entry device does not read as a lesser
   kind of listing than a catalogue one. */
.spec-table{display:grid;gap:0;margin:0}
.spec-table > div{display:flex;justify-content:space-between;gap:var(--space-4);
  padding:9px 0;border-bottom:1px solid var(--border-subtle);font:var(--text-body-sm)}
.spec-table > div:last-child{border-bottom:none}
.spec-table dt{color:var(--text-muted)}
.spec-table dd{margin:0;font-weight:600;color:var(--text-strong);text-align:right}
/* In the wizard it is something to read, not something to fill in. */
.spec-confirm{background:var(--paper-050);border-radius:var(--radius-md);padding:var(--space-5)}
.spec-confirm-head{display:inline-flex;align-items:center;gap:6px;margin-bottom:var(--space-3);
  font:var(--text-body-sm);font-weight:600;color:var(--clay-700)}

/* ── Following the plan, exactly ──────────────────────────────
   Example chips, a price stepper, a cover-photo picker, the pre-publish
   verification list and the row overflow menu. */
.start-examples{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.se-label{font:var(--text-body-sm);color:var(--text-subtle)}
.se-chip{padding:5px 12px;border-radius:var(--radius-pill);border:1px solid var(--border-subtle);
  background:var(--surface-card);font:var(--text-body-sm);color:var(--text-muted)}
.se-chip:hover{border-color:var(--clay-400);color:var(--clay-600)}

/* Nudging up or down from the anchor is the actual decision; a keypad is not. */
.price-stepper{display:flex;align-items:center;gap:6px}
.price-stepper input{width:110px;text-align:center;-moz-appearance:textfield}
.price-stepper input::-webkit-outer-spin-button,
.price-stepper input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.ps-btn{width:42px;height:42px;flex:none;border-radius:var(--radius-md);cursor:pointer;
  border:1px solid var(--border-default);background:var(--surface-card);
  font:600 20px/1 var(--font-sans);color:var(--ink-900)}
.ps-btn:hover{border-color:var(--clay-500);color:var(--clay-600)}

.photo-tile.is-cover{border-color:var(--clay-500);box-shadow:0 0 0 2px var(--clay-100)}
.photo-tools{position:absolute;top:6px;right:6px;display:flex;gap:4px}
.photo-tools form{margin:0}
.photo-tools button{width:26px;height:26px;border-radius:var(--radius-pill);border:none;cursor:pointer;
  background:rgba(43,39,34,.6);color:#fff;display:grid;place-items:center}
.photo-tools button:hover{background:var(--clay-600)}

.pv-empty{color:var(--text-subtle)}
.verify-card{padding:var(--space-6);margin-bottom:var(--space-6);background:var(--paper-050)}
.verify-list{list-style:none;margin:var(--space-4) 0;padding:0;display:grid;gap:var(--space-3)}
.verify-list li{display:flex;align-items:center;gap:10px;font:var(--text-body-sm);color:var(--text-strong)}
.v-todo,.v-done{display:inline-grid;place-items:center;width:20px;height:20px;flex:none;
  border-radius:var(--radius-pill);border:1px solid var(--border-default)}
.v-done{border-color:var(--status-success);background:var(--status-success);color:#fff}
.v-mins{margin-left:auto;font:var(--text-label-sm);color:var(--text-subtle)}

/* Everything rarer than the three shortcuts, including the delete. */
.row-more{position:relative}
.row-more > summary{cursor:pointer;list-style:none;padding:2px 8px;border-radius:var(--radius-sm);
  font:600 16px/1.2 var(--font-sans);color:var(--text-muted)}
.row-more > summary::-webkit-details-marker{display:none}
.row-more > summary:hover{background:var(--paper-100);color:var(--ink-900)}
.row-more-menu{position:absolute;right:0;top:100%;z-index:20;min-width:190px;display:grid;
  padding:6px;border-radius:var(--radius-md);border:1px solid var(--border-subtle);
  background:var(--surface-card);box-shadow:var(--shadow-sm)}
.row-more-menu form{margin:0}
.row-more-menu a,.row-more-menu button{display:flex;align-items:center;gap:8px;width:100%;
  padding:8px 10px;border:none;background:none;cursor:pointer;text-align:left;
  border-radius:var(--radius-sm);font:var(--text-body-sm);color:var(--text-body)}
.row-more-menu a:hover,.row-more-menu button:hover{background:var(--paper-100);color:var(--ink-900)}
.row-more-menu button.is-danger{color:var(--red-600)}

/* What a renter will actually see of the address, shown to the lender. */
.area-preview{display:grid;gap:4px;margin-top:var(--space-3);padding:var(--space-4);
  border-radius:var(--radius-md);background:var(--paper-050);border:1px solid var(--border-subtle)}
.ap-label{font:var(--text-overline);letter-spacing:var(--tracking-overline);text-transform:uppercase;color:var(--text-subtle)}
.ap-row{display:flex;align-items:center;gap:6px;font:var(--text-body-sm);color:var(--text-body)}
.ap-note{font:var(--text-body-sm);color:var(--text-muted)}

/* ── Picking a photo ──────────────────────────────────────────
   A native file input is the one control a stylesheet cannot reach — it
   renders as "Datei auswählen · keine ausgewählt" in the system font no matter
   what is asked of it. So it is clipped out of sight and its label becomes the
   control. Clipped rather than display:none, because a display-none input is
   not focusable and leaves the tab order. */
.filepick{position:relative;display:flex;align-items:center;gap:var(--space-4);cursor:pointer;
  padding:var(--space-6);text-align:left;
  border:1px dashed var(--border-default);border-radius:var(--radius-md);
  background:var(--paper-050);transition:border-color .12s ease,background .12s ease}
.filepick:hover{border-color:var(--clay-400);background:var(--clay-100)}
/* Keyboard users get the same ring the control would have had. */
.filepick:focus-within{border-color:var(--clay-500);box-shadow:0 0 0 3px var(--clay-100);border-style:solid}
.filepick-input{position:absolute;width:1px;height:1px;padding:0;margin:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}
.filepick-ic{display:inline-grid;place-items:center;width:44px;height:44px;flex:none;
  border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700)}
.filepick:hover .filepick-ic{background:var(--surface-card)}
.filepick-text{display:grid;gap:2px;min-width:0}
.filepick-label{font:var(--text-body);font-weight:600;color:var(--text-strong)}
.filepick-hint{font:var(--text-body-sm);color:var(--text-muted)}
/* What was actually picked, since the native readout went with the widget. */
.filepick-chosen{margin-left:auto;flex:none;padding:4px 10px;border-radius:var(--radius-pill);
  background:var(--status-success);color:#fff;font:var(--text-label-sm)}

/* Working. Picking the photo is itself the submit, and what follows is an
   upload plus — on the first wizard screen — a vision call, so it is seconds,
   not milliseconds. The camera becomes a spinner in place: the control that
   was pressed is the one that reports, rather than a button elsewhere on the
   page. Added by JS, so without it none of this applies and the form posts as
   it always did. */
.filepick.is-busy{pointer-events:none;cursor:progress;border-style:solid;
  border-color:var(--clay-400);background:var(--clay-100)}
.filepick.is-busy .filepick-ic svg{display:none}
.filepick.is-busy .filepick-ic::after{content:"";width:18px;height:18px;
  border:2px solid currentColor;border-top-color:transparent;border-radius:50%;
  animation:assist-spin .7s linear infinite}
.filepick.is-busy .filepick-hint{opacity:.6}
/* A static ring for anyone who asked for less motion: the point is that the
   control reads as occupied, and that survives without the spin. */
@media (prefers-reduced-motion:reduce){
  .filepick.is-busy .filepick-ic::after{animation:none;border-top-color:currentColor;opacity:.6}
}

/* A photo asked for beside something else does not need a dashed box the size
   of the field it belongs to. */
.filepick.is-compact{padding:var(--space-4) var(--space-5);gap:var(--space-3);border-style:solid}
.filepick.is-compact .filepick-ic{width:32px;height:32px}
.filepick.is-compact .filepick-label{font:var(--text-body-sm);font-weight:600}

@media (max-width:520px){
  .filepick{padding:var(--space-5)}
  .filepick-chosen{margin-left:0}
  .filepick-text{flex:1}
}

/* The add tile, sized to sit in the photo grid beside the pictures. */
.photo-add{position:relative;display:grid;align-content:center;justify-items:center;gap:8px;
  aspect-ratio:4/3;margin:0;padding:var(--space-4);text-align:center;
  border:1px dashed var(--border-default);border-radius:var(--radius-md);background:var(--paper-050)}
.photo-add:hover{border-color:var(--clay-400);background:var(--clay-100)}
.photo-add .filepick{border:none;background:none;padding:0;flex-direction:column;gap:8px;text-align:center}
.photo-add .filepick:hover{background:none}
.photo-add .filepick:focus-within{box-shadow:none}
.photo-add .filepick-label{font:var(--text-body-sm);font-weight:600}
.photo-add .filepick-chosen{position:absolute;top:8px;right:8px;margin:0}
/* Only pressed when JavaScript is not there to submit on pick. */
.photo-add-go{font:var(--text-label-sm);padding:4px 12px}

/* ── Search field ─────────────────────────────────────────────
   The browse bar's idiom, standing on its own. `type="search"` is the right
   element — phones give it a search key — but WebKit draws it as a rounded
   native pill with its own clear button unless the appearance is reset, which
   is why two of these looked like nothing else on the site. */
.searchfield{display:flex;align-items:center;gap:8px;padding:0 14px;min-width:0;
  background:var(--white);border:1px solid var(--border-subtle);border-radius:var(--radius-md)}
.searchfield:focus-within{border-color:var(--clay-500);box-shadow:0 0 0 3px var(--clay-100)}
.searchfield .ic{flex:none;display:flex;color:var(--text-subtle)}
.searchfield input{flex:1;min-width:0;height:44px;border:none;outline:none;background:transparent;
  font:400 16px/1.4 var(--font-sans);color:var(--text-body);
  -webkit-appearance:none;appearance:none}
.searchfield input::-webkit-search-decoration,
.searchfield input::-webkit-search-cancel-button,
.searchfield input::-webkit-search-results-button{-webkit-appearance:none;display:none}
.searchfield input::placeholder{color:var(--text-subtle)}

/* ── Describing a device we do not carry ──────────────────────
   A catalogue listing gets its description, uses and specs from the catalogue.
   An off-catalogue one has to say them itself, which was four stacked
   textareas — a wall of identical boxes with no indication which mattered.
   Its own block, its own heading, and each field shaped like what it holds. */
.own-details{padding:var(--space-6);margin-top:var(--space-2);
  border:1px solid var(--border-subtle);border-radius:var(--radius-md);background:var(--paper-050)}
.own-details > .field,.own-details > fieldset{margin-top:var(--space-5)}
.own-details-lead{margin-top:4px}

/* Each entry is a thing, so it is a pill you add and remove. The textarea is
   the field that posts and is what shows with the script absent. */
.pillfield textarea{min-height:76px}
.pill-box{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px;min-height:46px;cursor:text;
  background:var(--white);border:1px solid var(--border-default);border-radius:var(--radius-md)}
.pill-box:focus-within{border-color:var(--clay-500);box-shadow:0 0 0 3px var(--clay-100)}
.pill-list{display:contents}
.pill{display:inline-flex;align-items:center;gap:6px;padding:5px 6px 5px 11px;
  border-radius:var(--radius-pill);background:var(--clay-100);color:var(--clay-700);
  font:var(--text-body-sm);font-weight:600}
.pill-x{border:none;background:none;cursor:pointer;padding:0;line-height:1;
  font:600 16px/1 var(--font-sans);color:var(--clay-600);opacity:.75}
.pill-x:hover{opacity:1;color:var(--red-600)}
.pill-input{flex:1;min-width:140px;border:none;outline:none;background:transparent;
  font:var(--text-body);color:var(--text-body);padding:4px 2px}
.pill-input:disabled{cursor:not-allowed}

/* Pairs, because a pair is what a person has — not "Label: value" per line. */
.specrows{border:none;padding:0;margin:0}
.specrows-list{display:grid;gap:8px;margin:var(--space-3) 0}
.specrow{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px}
.specrows-add{justify-self:start;padding-left:0}

@media (max-width:520px){
  .own-details{padding:var(--space-5)}
  .specrow{grid-template-columns:1fr}
}
