/* ===========================================================================
   PMA Ops — "JUNTA"                       backend/static/css/pages.css
   NUR das, was wirklich flächenspezifisch ist. Alles, was auf mehr als einer
   Fläche vorkommt, gehört nach components.css.
   Flächen werden über <html data-surface="site|portal|owner|ops"> gestempelt.
   =========================================================================== */

@layer pages {

  /* =========================================================================
     ÖFFENTLICHE WEBSITE  (data-surface="site", §9.8)
     Aufgabe: einen kleinen Contractor vertrauenswürdig aussehen lassen und
     einen Lead erzeugen. Indexierbar.
     ========================================================================= */

  .site-hero {
    display: grid;
    gap: 0;
    background: var(--tile);
    border-block-end: var(--joint) solid var(--grout);
  }
  /* Foto links vollflächig, Text-Panel überlappt von links an der Unterkante
     des Bildes — nicht „zentrierte Headline plus zwei Knöpfe“. */
  .site-hero__media { position: relative; display: grid; }
  .site-hero__media > :is(img, .shot-lqip) {
    grid-area: 1 / 1;
    inline-size: 100%;
    max-inline-size: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
  }
  .site-hero__body {
    display: grid;
    gap: var(--sp-4);
    justify-items: start;
    padding: var(--sp-5) var(--gutter) var(--sp-6);
  }
  .site-hero__h {
    font-family: var(--f-display);
    font-weight: 800;
    font-size: var(--step-4);
    line-height: var(--lh-display);
    letter-spacing: -0.025em;
    text-wrap: balance;
  }
  .site-hero__sub { font-size: var(--step-1); max-inline-size: 40ch; }
  @media (min-width: 56rem) {
    .site-hero { grid-template-columns: minmax(20rem, 34rem) 1fr; align-items: end; }
    .site-hero__media { grid-column: 2; grid-row: 1; }
    .site-hero__media > :is(img, .shot-lqip) { aspect-ratio: 16 / 11; block-size: 100%; }
    .site-hero__body {
      grid-column: 1;
      grid-row: 1;
      z-index: 1;
      margin-inline-end: calc(var(--sp-7) * -1);
      margin-block-end: var(--sp-6);
      background: var(--tile);
      border: var(--joint) solid var(--grout);
      box-shadow: var(--lift);
    }
  }

  /* Lizenz- und Versicherungsstreifen. Der einzige Mono-Block über der
     Falz — und genau der Block, der zum Nachprüfen einlädt: DBPR-Nummer,
     Klasse, Servicegebiet. Er ist deshalb das schwerste Element oben,
     nicht der CTA (Regel: EIN gefüllter Knopf pro Viewport). */
  .credentials {
    display: grid;
    gap: var(--joint);
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    background: var(--ink);
    border: var(--joint) solid var(--ink);
  }
  .credentials > div { background: var(--tile); padding: var(--sp-4); display: grid; gap: 2px; }
  .credentials dt {
    font-family: var(--f-body);
    font-weight: 600;
    font-size: var(--step--2);
    text-transform: uppercase;
    letter-spacing: var(--track-label);
    color: var(--ink-2);
  }
  .credentials dd {
    font-family: var(--f-data);
    font-weight: 600;
    font-size: var(--step-1);
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
  }

  /* Leistungen. Keine Karten — Zeilen mit Fuge, weil es eine Liste ist. */
  .services { display: grid; gap: var(--joint); background: var(--grout); border: var(--joint) solid var(--grout); }
  .services > li { background: var(--tile); padding: var(--sp-4); display: grid; gap: var(--sp-2); }
  .services h3 { font-size: var(--step-1); }

  /* Bewertungen: Freitext + Vorname aus content.yaml. Ein Zitat ist Prosa,
     also nie Mono; nur der Ort daneben ist prüfbar. */
  .reviews { display: grid; gap: var(--sp-5); }
  @media (min-width: 46rem) { .reviews { grid-template-columns: repeat(2, 1fr); } }
  .review {
    display: grid;
    gap: var(--sp-3);
    padding: var(--sp-4);
    background: var(--tile);
    border: var(--joint) solid var(--grout);
    border-inline-start: 6px solid var(--accent-line);
  }
  .review blockquote { margin: 0; font-size: var(--step-1); line-height: var(--lh-tight); }
  .review figcaption { font-weight: 600; color: var(--ink-2); font-size: var(--step--1); }

  /* Servicegebiet Miami-Dade. */
  .area { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
  .area li {
    padding: var(--sp-1) var(--sp-3);
    border: var(--joint) solid var(--grout);
    border-radius: var(--r-edge);
    font-size: var(--step--1);
    font-weight: 600;
    color: var(--ink-2);
  }

  .site-foot {
    padding-block: var(--sp-6) var(--sp-8);
    border-block-start: var(--joint) solid var(--grout);
  }

  /* =========================================================================
     KUNDENPORTAL  (data-surface="portal", /p/{token}, §9.6)
     Eine scrollbare Seite. Mobil zuerst, oft von einer 60-Jährigen geöffnet.
     ========================================================================= */

  /* „Ahora“ — eines der max. zwei Lift-Elemente auf dieser Fläche. */
  .ahora { display: grid; gap: var(--sp-4); }
  .ahora__phase {
    font-family: var(--f-display);
    font-weight: 800;
    font-size: var(--step-3);
    line-height: var(--lh-display);
    letter-spacing: -0.025em;
    text-wrap: balance;
  }
  /* Die Woche wird BESTIMMT genannt — „Semana del 6 de octubre“. Die
     Unsicherheit lebt im Chip daneben, nie im Satz. Eine Spanne wie
     „2–3 semanas“ und ein exaktes Tagesdatum werden nie gerendert. */
  .ahora__week {
    font-family: var(--f-data);
    font-weight: 600;
    font-size: var(--step-1);
    letter-spacing: -0.01em;
  }
  /* Der Chip trägt den Zustand zum Scannen; dieser Satz trägt ihn für sie.
     „estimado“ ist Fachsprache für eine 60-jährige Eigentümerin. */
  .ahora__plain { color: var(--ink-2); }
  .ahora__blocker {
    display: grid;
    gap: var(--sp-2);
    justify-items: start;
    padding-block-start: var(--sp-3);
    border-block-start: var(--joint) solid var(--grout);
  }

  /* „Tu parte“ — geordnete Liste mit Zähler in der Überschrift: sie muss
     wissen, WIE VIELE Dinge ihr gehören und in welcher Reihenfolge. */
  .parte { display: grid; gap: var(--sp-4); counter-reset: parte; }
  .parte > li {
    display: grid;
    gap: var(--sp-2);
    justify-items: start;
    padding-block-end: var(--sp-4);
    border-block-end: var(--joint) solid var(--accent);
    max-inline-size: none;
  }
  .parte > li:last-child { border-block-end: 0; padding-block-end: 0; }
  .parte__due { font-family: var(--f-data); font-weight: 600; font-size: var(--step--1); color: var(--ink-2); }

  /* Freigabe: Name + letzte 4 Ziffern der Telefonnummer (§9.6.5). */
  .approve { display: grid; gap: var(--sp-4); }
  .approve__pin { max-inline-size: 9ch; letter-spacing: 0.3em; text-align: center; }

  /* Lista final / Punch-Liste. */
  .punch > li {
    display: grid;
    gap: var(--sp-2);
    padding-block: var(--sp-3);
    border-block-end: var(--joint) solid var(--grout);
    border-inline-start: 4px solid var(--sev, var(--grout-deep));
    padding-inline-start: var(--sp-3);
    max-inline-size: none;
  }
  .punch > li[data-state="fixed"]    { --sev: var(--wait); }
  .punch > li[data-state="verified"] { --sev: var(--ok); }
  .punch > li[data-state="disputed"] { --sev: var(--crit); }

  /* Dokumente. */
  .docs > li {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-3);
    min-block-size: var(--tap);
    padding-block: var(--sp-2);
    border-block-end: var(--joint) solid var(--grout);
    max-inline-size: none;
  }

  /* =========================================================================
     OWNER-DASHBOARD  (data-surface="owner", /owner, §9.7)
     Im Truck, greller Sonne, einhändig, spanisch. Kein Gantt, kein DnD.
     ========================================================================= */

  /* „Esta semana“ ist sichtbar schwerer als alles andere, weil es der
     einzige Grund ist, aus dem er die App öffnet. Das ist das eine
     Lift-Element dieser Fläche. */
  .semana { display: grid; gap: var(--sp-4); }
  .semana__day {
    display: grid;
    gap: var(--sp-2);
    padding-block: var(--sp-3);
    border-block-start: var(--joint) solid var(--grout);
  }
  .semana__day:first-child { border-block-start: 0; padding-block-start: 0; }
  .semana__date {
    font-family: var(--f-data);
    font-weight: 600;
    font-size: var(--step--1);
    text-transform: uppercase;
    letter-spacing: var(--track-cap);
    color: var(--ink-2);
  }

  /* --- LA REGLA — der Zollstock als Informationsgerät ---------------------
     Ein Tick = ein Arbeitstag, jeder fünfte Tick = eine Woche. Die Marken
     werden NICHT in Prozent gesetzt, sondern in ganzen Ticks über --from /
     --span, damit Fensterkante und Tick immer auf derselben Linie liegen —
     sonst behauptet das Instrument eine Genauigkeit, die es nicht hat.
     Linien sind ≥2px in --ink-2 / --accent-line, nicht 1px-Haarlinien.

     BEDINGUNG FÜRS AUSLIEFERN: das Jinja2-Makro nimmt das Fenster als
     PFLICHT-Argument. Eine .regla ohne .regla__win aus echten
     Meilensteindaten ist Tapete und darf nicht gerendert werden.
     Markup: <div class="regla" style="--tick:10px" role="img" aria-label="…">
               <span class="regla__win" style="--from:2;--span:5"></span>
               <span class="regla__est" style="--from:7;--span:4"></span>
             </div>                                                        */
  .regla {
    --tick: 10px;
    position: relative;
    block-size: 16px;
    border-block-end: var(--joint) solid var(--ink-2);
    background-repeat: repeat-x;
    background-position: 0 100%, 0 100%;
    background-size: 100% 16px, 100% 9px;
    background-image:
      repeating-linear-gradient(90deg, var(--ink-2) 0 2px, transparent 2px calc(var(--tick) * 5)),
      repeating-linear-gradient(90deg, var(--grout-deep) 0 2px, transparent 2px var(--tick));
  }
  .regla__win,
  .regla__est {
    position: absolute;
    inset-block-end: -2px;
    inset-inline-start: calc(var(--tick) * var(--from, 0));
    inline-size: calc(var(--tick) * var(--span, 1));
  }
  .regla__win { block-size: 5px; background: var(--accent-line); }   /* publiziertes Fenster */
  .regla__est {                                                       /* geschätzter Ausläufer */
    block-size: 7px;
    border-block-end: var(--joint) solid var(--warn);
    background: repeating-linear-gradient(135deg, var(--warn) 0 2px, transparent 2px 6px);
  }

  /* Lead-Liste (§9.8). Gleiche .row-Grammatik, eigener Abschnitt. */
  .leads { display: grid; }
  .leads .row { border-inline-start-color: var(--accent-line); }
  .lead__source {
    font-family: var(--f-data);
    font-size: var(--step--2);
    text-transform: uppercase;
    letter-spacing: var(--track-cap);
    color: var(--ink-2);
  }

  /* Bestätigungsqueue / Abend-Digest: Karten mit genau einer Warnzeile. */
  .card-q { display: grid; gap: var(--sp-3); }
  .card-q__doubt {
    display: flex;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
    background: var(--warn-fill);
    color: var(--warn);
    border-inline-start: 4px solid var(--warn);
    font-weight: 600;
    font-size: var(--step--1);
  }
  .card-q__acts { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

  /* Foto-Grid mit Sichtbarkeits-Toggles (visible_to_customer / showcase). */
  .photo-admin figure { display: grid; gap: var(--sp-2); }
  .photo-admin .check { padding-inline: var(--sp-2); }

  /* Auf /owner steht in der Sonne nichts unter 600. */
  :root[data-mode="sol"] .shell :is(p, li, td, dd, span, label) { font-weight: 600; }

  /* =========================================================================
     OPS-KONSOLE  (data-surface="ops", /ops, §9.7)
     Svens Debug-Fenster: dicht, informationsorientiert, Desktop, System-
     Schrift, null Webfont-Bytes.
     ========================================================================= */

  .ops-layout { display: grid; gap: var(--sp-5); }
  @media (min-width: 64rem) {
    .ops-layout { grid-template-columns: 16rem 1fr; align-items: start; }
    .ops-side { position: sticky; top: calc(env(safe-area-inset-top, 0px) + var(--sp-5)); }
  }
  .ops-side { display: grid; gap: var(--sp-1); }
  .ops-side a {
    display: flex;
    align-items: center;
    min-block-size: var(--tap);
    padding-inline: var(--sp-3);
    color: var(--ink);
    text-decoration: none;
    border-inline-start: 4px solid transparent;
  }
  .ops-side a[aria-current] { border-inline-start-color: var(--accent); background: var(--tile); font-weight: 600; }

  /* Nachrichtenlog und Job-Queue: die einzige Stelle im System, an der
     15px-Mono-Zeilen richtig sind. */
  .ops-log { font-family: var(--f-data); font-size: var(--step--1); line-height: var(--lh-data); }
  .ops-log__line {
    display: grid;
    grid-template-columns: 11ch 8ch 1fr;
    gap: var(--sp-3);
    padding-block: var(--sp-1);
    border-block-end: 1px solid var(--grout);
    max-inline-size: none;
  }
  .ops-log__line[data-result="warning"] { color: var(--warn); }
  .ops-log__line[data-result="error"]   { color: var(--crit); }
  .ops-log__txt { overflow-wrap: anywhere; }

  /* Kennzahlenband der Konsole (required_taps, undo_rate, doubt_counts). */
  .ops-metrics { grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }

  /* Fehlgeschlagene Extraktionen: Review-Queue. Blockiert den Owner nie. */
  .ops-queue__params {
    font-family: var(--f-data);
    font-size: var(--step--2);
    color: var(--ink-2);
    overflow-wrap: anywhere;
    white-space: pre-wrap;
  }

  /* -------------------------------------------------------------------------
     Bausteine, die aus `app.css` hierher gezogen wurden (Konsolidierung).

     `app.css` war das zweite, parallel entstandene Vokabular der Ops-Konsole
     (`.field__l`, `.nav__i`, `.tablewrap`, `.wrap`, `.mono`, `.chip--<status>`).
     Entschieden ist zugunsten des Design-Systems: die Templates sprechen jetzt
     `.field__label`, `.nav__link`, `.table-scroll`, `.shell`, `.u-data` und die
     fuenf Chip-Modifier aus §6.3. Was in `components.css` fehlte und wirklich
     nur /ops braucht, steht hier — unter eigenen, praefixierten Namen, damit es
     keine zweite Bedeutung fuer einen Systemnamen gibt.

     Was /ops-spezifisch an einer bestehenden Systemklasse haengt, ist auf
     `:root[data-surface="ops"]` gestempelt und faellt damit nie auf Portal,
     Owner oder Website zurueck.
     ------------------------------------------------------------------------- */

  /* Beschriftete Werte: die Detailansicht einer Zeile. Label in Mono, weil es
     unmittelbar eine pruefbare Angabe betitelt (Invariante 4). */
  .kv { display: grid; grid-template-columns: max-content 1fr; gap: var(--sp-2) var(--sp-4); }
  .kv dt {
    font-family: var(--f-data);
    font-weight: 600;
    font-size: var(--step--2);
    text-transform: uppercase;
    letter-spacing: var(--track-label);
    color: var(--ink-2);
  }
  .kv dd { margin: 0; min-inline-size: 0; overflow-wrap: anywhere; max-inline-size: none; }

  /* Filterleiste ueber einer Tabelle. Bricht um, statt zu quetschen. */
  .filters { display: flex; flex-wrap: wrap; align-items: end; gap: var(--sp-3); }
  .filters .field { min-inline-size: 10rem; }
  .filters .btn { align-self: end; }

  /* Zwei Spalten ab 40rem — das Anlageformular der Personenliste. */
  .grid2 { display: grid; gap: var(--sp-4); }
  @media (min-width: 40rem) {
    .grid2 { grid-template-columns: 1fr 1fr; }
    .grid2 > .field--wide { grid-column: 1 / -1; }
  }

  /* Mehrere `.check` nebeneinander (Rollen-Auswahl). `.check` selbst steht im
     Design-System (§6.6); nur der Container fehlte. */
  .checks { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); }

  /* Blaetterleiste unter einer Liste. */
  .pager { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

  /* Seitenweite Meldung im Textfluss (Login-Fehler, „keine fehlgeschlagenen
     Jobs"). Bewusst KEIN `.toast`: ein Toast ist fluechtig und lebt in
     `.toasts` mit `role="status"`; das hier steht im Dokument.
     Farbe steht nie allein — die Meldung traegt immer ihren Satz. */
  .ops-note {
    padding: var(--sp-3) var(--sp-4);
    background: var(--tile);
    border: var(--joint) solid var(--grout);
    border-inline-start: 6px solid var(--grout-deep);
    border-radius: var(--r-edge);
    max-inline-size: none;
  }
  .ops-note--ok   { border-inline-start-color: var(--ok);   background: var(--ok-fill); }
  .ops-note--warn { border-inline-start-color: var(--warn); background: var(--warn-fill); }
  .ops-note--crit { border-inline-start-color: var(--crit); background: var(--crit-fill); }
  .ops-note--wait { border-inline-start-color: var(--wait); background: var(--wait-fill); }

  /* Roh-Payload, Transkript, Stacktrace. Die einzige Stelle mit `pre`. */
  .ops-pre {
    font-family: var(--f-data);
    font-size: var(--step--1);
    line-height: var(--lh-data);
    background: var(--tile-sunk);
    border: var(--joint) solid var(--grout);
    border-radius: var(--r-edge);
    padding: var(--sp-3);
    max-block-size: 28rem;
    overflow: auto;
    overscroll-behavior: contain;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    max-inline-size: none;
  }
  .ops-pre--json { tab-size: 2; }
  .ops-pre--crit { border-color: var(--crit); }

  /* `last_error` in einer Tabellenzelle. */
  .ops-err { color: var(--crit); overflow-wrap: anywhere; }

  /* Lange Freitextspalte in einer dichten Tabelle: begrenzen statt die Zeile
     auf Handyhoehe zu quetschen. */
  .ops-clip { min-inline-size: 14rem; max-inline-size: 28rem; overflow-wrap: anywhere; }

  /* Schmale, zentrierte Saeule fuer den Login. */
  .ops-narrow { max-inline-size: 28rem; margin-inline: auto; }

  /* Fusszeile der Konsole. */
  .ops-foot {
    border-block-start: var(--joint) solid var(--grout);
    padding: var(--sp-4) var(--gutter);
    color: var(--ink-2);
    font-size: var(--step--2);
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--sp-2);
  }

  /* Kennzahlkachel als Link + Zustandsstreifen. Der Streifen ist nie allein:
     die Kachel traegt ihr Label im Klartext daneben. */
  a.stat { color: inherit; text-decoration: none; }
  a.stat:hover { background: var(--tile-sunk); }
  .stat--crit { box-shadow: inset 4px 0 0 var(--crit); }
  .stat--crit .stat__v { color: var(--crit); }
  .stat--warn { box-shadow: inset 4px 0 0 var(--warn); }
  .stat--warn .stat__v { color: var(--warn); }

  /* Tabellendichte — /ops ist die einzige Flaeche mit waagerechtem Scrollen
     und 1px-Linien (§6.12). `min-inline-size` statt Umbruch: auf dem Telefon
     scrollt der Container, die Spalten behalten ihre Breite. */
  :root[data-surface="ops"] .table-scroll {
    background: var(--tile);
    border: var(--joint) solid var(--grout);
    border-radius: var(--r-edge);
  }
  :root[data-surface="ops"] .table { min-inline-size: 46rem; }
  :root[data-surface="ops"] .table th { background: var(--tile-sunk); }
  :root[data-surface="ops"] .table tbody tr:last-child td { border-block-end: 0; }
  /* Chips stehen in /ops zu mehreren in einer Zelle. */
  :root[data-surface="ops"] .table :is(.chip, .whose) + :is(.chip, .whose) {
    margin-inline-start: var(--sp-1);
  }
  /* Die Konsole ist Svens Desktop-Fenster: 40px sind dort erlaubt (§9 Touch). */
  :root[data-surface="ops"] .table .btn { min-block-size: 40px; }
}
