/* ==========================================================================
   BEST OF — PROFILE SPINE AND PANELS

   MOBILE FIRST, AT 390. Every rule below is the 390 cut; the media queries
   only widen it. Built that way because the reference build for this surface
   is "Service Profile - v9 Mobile 390.dc.html" and because the narrow case is
   the one that breaks — a desktop-first sheet gets its mobile cut by
   subtraction, and subtraction is how horizontal overflow gets in.

   NO NEW COLOURS. Every value is a token from tokens.css, which already
   matches the reference build's palette exactly (#10213A ink, #5F6878 soft,
   #EDE9E0 border, #B45309 gold ink, #2F6B45 green). If a colour is needed that
   is not here, it is a token change, not a local literal.

   14px gutter, from the reference build's own `padding:0 14px`.

   ⚠ NOT CONFIRMED ON A REAL DEVICE. Emulation has lied about width on this
   project before (§ mobile rule) — innerWidth reported 348 at 320 and 402 at
   390. Everything here is measured against clientWidth in a synthetic check
   only. Mark confirms on a phone before this is claimed.
   ========================================================================== */

.bog-profile {
  --bog-gutter: 14px;

  display: block;
  max-width: 100%;
  /* The page background, not white: panels are the surfaces, and a white page
     under white panels loses every edge. */
  background: var(--bo-page-bg);
  color: var(--bo-ink);
  font-family: var(--bo-font-ui);
}

/* ==========================================================================
   THE EMPTY SLOTS

   The spine renders fifteen slots and most are structural containers the
   design has not filled yet. AN EMPTY SECTION MUST OCCUPY NOTHING. Without
   this the profile is thirteen invisible boxes contributing padding, and the
   two real ones float in the middle of it.

   :empty rather than a class, so a slot disappears and reappears purely on
   whether it has content — nothing has to remember to toggle anything.
   ========================================================================== */
.bog-profile__slot:empty { display: none; }

/* ==========================================================================
   PANELS
   ========================================================================== */
.bog-profile__panels {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0 var(--bog-gutter);
  /* A flex child will not shrink below its content unless told to, and one
     long unbroken URL is all it takes to push the whole page sideways. This is
     the fix that was missed the first time on mobile. */
  min-width: 0;
}

.bog-panel {
  background: var(--bo-surface);
  border: 1px solid var(--bo-border);
  border-radius: 6px;
  padding: 18px 14px 16px;
  min-width: 0;
}

.bog-panel__head {
  font-family: var(--bo-font-display);
  font-size: 15px;
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--bo-ink);
  margin: 0 0 12px;
}

/* ==========================================================================
   ROWS

   A definition list, because that is what this is: a field name and its value.
   The default dl margins are removed rather than overridden per browser.
   ========================================================================== */
.bog-panel__rows { margin: 0; }

.bog-row {
  display: block;
  padding: 12px 0;
  border-top: 1px solid var(--bo-border-soft);
  min-width: 0;
}
.bog-row:first-child { border-top: 0; padding-top: 0; }

.bog-row__label {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bo-ink-soft);
  margin: 0 0 4px;
}

.bog-row__value {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--bo-ink);
  /* Long values wrap INSIDE the panel rather than widening it. `anywhere`
     rather than `break-word` because the offender is a URL with no spaces at
     all, which break-word leaves intact. */
  overflow-wrap: anywhere;
  min-width: 0;
}

.bog-row__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.bog-row__list li {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 3px 0;
  min-width: 0;
}
.bog-row__k { color: var(--bo-ink-soft); }
.bog-row__v { color: var(--bo-ink); font-weight: 600; }

.bog-row__link {
  color: var(--bo-gold-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  /* A link is a tap target before it is text. 44px is the floor. */
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
}

/* ==========================================================================
   PROVENANCE — the line that is the whole proposition

   Small, but never hidden and never behind a tap. If the source is not on the
   page beside the fact, the page is a directory.
   ========================================================================== */
.bog-field__source {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--bo-ink-faint);
  overflow-wrap: anywhere;
}

.bog-field__read-at { color: var(--bo-ink-faint); }

.bog-field__contested {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 3px;
  background: var(--bo-amber-tint);
  border: 1px solid var(--bo-amber-border);
  color: var(--bo-amber-ink);
  font-weight: 700;
  font-size: 11px;
}

/* ==========================================================================
   WHAT CHANGED — 4.3 → 4.6

   The one thing on the page a competitor cannot show without having watched,
   so it is given its own line rather than tucked into the provenance run.
   ========================================================================== */
.bog-row__change {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  color: var(--bo-ink-muted);
}
.bog-row__change-from {
  color: var(--bo-ink-faint);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
.bog-row__change-to { font-weight: 700; color: var(--bo-ink); }
.bog-row__change-when { color: var(--bo-ink-faint); }

/* ==========================================================================
   LICENCES — the expiry date IS the panel

   AN EXPIRED LICENCE MUST NOT LOOK LIKE A CURRENT ONE AT A GLANCE. This is the
   most consequential thing a trades profile publishes: somebody is deciding
   whether to let a stranger into their house. So the three states are three
   visibly different things, and `unknown` reads as unknown rather than as
   quietly fine.

   Colour is not the only carrier — each state has its own word — so this still
   works for a reader who cannot distinguish the tints.
   ========================================================================== */
.bog-row__list--licences li {
  display: block;
  padding: 8px 10px;
  border-radius: 4px;
  border: 1px solid var(--bo-border);
  margin-bottom: 6px;
}

.bog-licence--current {
  background: var(--bo-green-tint);
  border-color: var(--bo-green-border);
}
.bog-licence--current .bog-licence__expiry { color: var(--bo-green-ink); }

.bog-licence--expired {
  background: var(--bo-red-tint);
  border-color: var(--bo-red-border);
}
.bog-licence--expired .bog-licence__expiry {
  color: var(--bo-red-ink);
  font-weight: 800;
  letter-spacing: 0.02em;
}

.bog-licence--unknown {
  background: var(--bo-neutral-tint);
  border-color: var(--bo-neutral-border);
}
.bog-licence--unknown .bog-licence__expiry { color: var(--bo-ink-soft); font-style: italic; }

.bog-licence__no {
  font-family: var(--bo-font-mono, 'JetBrains Mono', ui-monospace, monospace);
  font-size: 12.5px;
  color: var(--bo-ink-soft);
}
.bog-licence__expiry { display: block; margin-top: 2px; font-size: 12.5px; }

/* ==========================================================================
   RATINGS — each on its own scale, never averaged
   ========================================================================== */
.bog-rating__scale { color: var(--bo-ink-faint); font-weight: 400; }
.bog-rating__count { color: var(--bo-ink-soft); font-size: 13px; }

/* ==========================================================================
   ABSENCES INSIDE A PANEL — "not published" is a finding, not a blank
   ========================================================================== */
.bog-panel__absences {
  list-style: none;
  margin: 12px 0 0;
  padding: 12px 0 0;
  border-top: 1px dashed var(--bo-border-strong);
}

/* Two columns, not a wrapping flex run. Flowing label, state and button as one
   line let the button land wherever the text happened to stop, so a column of
   absences read as ragged rather than as a list. The button now has its own
   column and every row lines up. */
.bog-panel__absent {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 4px 10px;
  padding: 8px 0;
  font-size: 13.5px;
  border-top: 1px solid var(--bo-border-soft);
}
.bog-panel__absent:first-child { border-top: 0; }

/* Label and state share the first column and wrap together; the button holds
   the second across both rows. */
.bog-panel__absent-label,
.bog-panel__absent-state,
.bog-panel__absent-when { grid-column: 1; }
.bog-panel__absent-label { grid-row: 1; }
.bog-panel__absent-state { grid-row: 2; }
.bog-panel__absent-when  { grid-row: 3; }
.bog-panel__absent-ask   { grid-column: 2; grid-row: 1 / -1; align-self: center; }

.bog-panel__absent-label { color: var(--bo-ink-soft); font-weight: 600; }

.bog-panel__absent-state {
  color: var(--bo-ink-faint);
  font-style: italic;
  overflow-wrap: anywhere;
}

/* A gap we have actually searched for reads as a finding, not as silence. */
.bog-panel__absent[data-bog-gap-checked] .bog-panel__absent-state { font-style: normal; }
.bog-panel__absent-when { color: var(--bo-ink-faint); font-size: 12px; }

.bog-panel__absent-ask {
  /* An unanswered question is an entry point, not a hole — so it is a real
     control at a real tap size, not a hint. */
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--bo-action-gold-light);
  border-radius: 4px;
  background: var(--bo-gold-tint);
  color: var(--bo-gold-tint-ink);
  font-family: var(--bo-font-ui);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}

/* ==========================================================================
   THE GAP LIST — "we publish our gaps, because a record that hides them is
   just a brochure"

   Given the same visual weight as a panel. It IS content, not an apology, and
   styling it as a footnote would contradict the sentence it exists to make.
   ========================================================================== */
.bog-profile__gaps {
  background: var(--bo-surface-warm);
  border: 1px solid var(--bo-border-warm);
  border-radius: 6px;
  padding: 18px 14px 16px;
  min-width: 0;
}

.bog-profile__gaps-head {
  font-family: var(--bo-font-display);
  font-size: 15px;
  font-weight: 800;
  color: var(--bo-ink);
  margin: 0 0 10px;
}

.bog-profile__gap-list { list-style: none; margin: 0; padding: 0; }

.bog-profile__gap {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 7px 0;
  border-top: 1px solid var(--bo-border-soft);
  font-size: 13.5px;
  min-width: 0;
}
.bog-profile__gap:first-child { border-top: 0; }
.bog-profile__gap-label { font-weight: 700; color: var(--bo-ink); }
.bog-profile__gap-why { color: var(--bo-ink-soft); overflow-wrap: anywhere; }

/* ==========================================================================
   LEAD SURFACE — the enquiry

   THE SURFACE IS DECLARED, NOT ASSUMED. `leadProminence` gives each treatment
   a surface, a slot and whether it carries an inline form. The renderer emits
   those as classes and data attributes, and this file styles them. Navy used
   to be hardcoded on .bog-lead itself, which is why a category declaring any
   other surface could never have been given one.
   ========================================================================== */
.bog-lead {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px var(--bog-gutter);
  padding: 16px 14px;
  border-radius: 6px;
}

/* ⚠ THE PANEL SET A NAVY GROUND AND NEVER SET A TEXT COLOUR.
   Every child inherited --bo-ink (#10213A) onto --bo-navy (#0B1F3A) — a
   contrast ratio of about 1.02:1. The purposes line, the channel values and
   the sentence promising we do not pass messages on were all present in the
   markup, all styled, and all invisible. Only links showed, because links set
   their own colour. Nine of ten categories render this panel.
   Every colour on this surface is now stated rather than inherited. */
.bog-lead--surface-navy {
  background: var(--bo-navy);
  color: var(--bo-surface);
}
.bog-lead--surface-navy a { color: var(--bo-action-gold); }
.bog-lead--surface-navy .bog-lead__note,
.bog-lead--surface-navy .bog-lead__none { color: rgba(255, 255, 255, 0.82); }

/* Declared as no surface: the hero button IS the lead. render_lead_surface()
   already returns nothing for it, so this is the second lock, not the first. */
.bog-lead--surface-none,
.bog-lead--heroOnly { display: none; }

.bog-lead__purposes {
  margin: 0;
  font-family: var(--bo-font-ui);
  font-weight: 700;
}

.bog-lead__channels {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.bog-lead__note,
.bog-lead__none {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
}

/* FULL MASTHEAD — "the enquiry is the product", so it is given room, the
   purposes lead at display size and the channels sit open on the page. */
.bog-lead--masthead { padding: 22px 18px; gap: 12px; }
.bog-lead--masthead .bog-lead__purposes { font-size: 18px; line-height: 1.3; }
.bog-lead--masthead .bog-lead__channels { gap: 10px; }

/* ONE STRIP, ONE ACTION — booking is usually done elsewhere, so this states a
   single purpose and keeps the channels behind one native disclosure. */
.bog-lead--strip { padding: 12px 14px; gap: 6px; }

.bog-lead__ask > summary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 20px;
  border-radius: 4px;
  background: var(--bo-action-gold);
  color: var(--bo-gold-ink-darkest);
  border: 1px solid var(--bo-action-gold);
  font-family: var(--bo-font-ui);
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
}
.bog-lead__ask > summary::-webkit-details-marker { display: none; }
.bog-lead__ask[open] > summary { margin-bottom: 10px; }

/* The disclosure's own contents keep the surface's text colour rather than
   restating it, so the strip and the masthead cannot drift apart. */
.bog-lead__ask > .bog-lead__channels { margin-top: 0; }

/* ==========================================================================
   WIDER

   Only from here up does anything get two columns. The label/value split is
   the single change worth making — at 390 a side-by-side label eats the width
   the value needs.
   ========================================================================== */
@media (min-width: 700px) {
  .bog-profile { --bog-gutter: 24px; }

  .bog-profile__panels { gap: 16px; }

  .bog-panel,
  .bog-profile__gaps { padding: 22px 20px 20px; }

  .bog-row {
    display: grid;
    grid-template-columns: 190px minmax(0, 1fr);
    gap: 16px;
    align-items: baseline;
  }
  .bog-row__label { margin: 0; }

  /* Absences take the SAME 190px label column as the rows above them. At 390
     the state has to wrap under its label; at this width it does not, and
     leaving it wrapped opens a gulf between the label and the button that
     reads as a mistake. Same grid, so a panel's absences line up with its
     facts rather than sitting in a second layout. */
  .bog-panel__absent {
    grid-template-columns: 190px minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 2px 16px;
  }
  .bog-panel__absent-label { grid-column: 1; grid-row: 1; }
  .bog-panel__absent-state { grid-column: 2; grid-row: 1; }
  .bog-panel__absent-when  { grid-column: 2; grid-row: 2; }
  .bog-panel__absent-ask   { grid-column: 3; grid-row: 1 / -1; }

  /* The STRIP lays out as one row: purpose and action on a single line.
     The MASTHEAD deliberately does not — its purposes lead and its channels
     sit beneath them, which is the difference between a strip and a
     masthead. .bog-lead__secondary was removed here: no element has carried
     that class since the per-verb panel was replaced. */
  .bog-lead--strip {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
  }
  .bog-lead__ask > summary { min-width: 220px; padding: 0 24px; }
}

@media (min-width: 1000px) {
  .bog-profile__panels,
  .bog-lead { max-width: var(--bo-content-width); margin-inline: auto; }
}

/* ==========================================================================
   REDUCED MOTION / PRINT
   ========================================================================== */
@media print {
  /* The provenance is the reason a printed profile is worth anything. */
  .bog-field__source { color: #000; }
  .bog-panel__absent-ask { display: none; }
}

/* ==========================================================================
   HERO — slot 1, identity

   The one slot that can never be empty, so it is the one that does not need
   the :empty guard. `canonical_name` is Tier 0 and tagged `block`: a profile
   without a name does not render at all.
   ========================================================================== */
.bog-hero {
  padding: 20px var(--bog-gutter) 4px;
  background: var(--bo-page-bg);
}

.bog-hero__name {
  font-family: var(--bo-font-display);
  font-size: 26px;
  font-weight: 800;
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--bo-ink);
  margin: 0;
  overflow-wrap: anywhere;
}

.bog-hero__kind {
  font-size: 13px;
  line-height: 1.4;
  color: var(--bo-ink-soft);
  margin: 6px 0 0;
}

@media (min-width: 700px) {
  .bog-hero { padding: 28px var(--bog-gutter) 6px; }
  .bog-hero__name { font-size: 34px; }
}

@media (min-width: 1000px) {
  .bog-hero { max-width: var(--bo-content-width); margin-inline: auto; }
}
