/* ============================================================
   DB ENERGY — V3 refinement component set
   Built against db-energy-uniformisation-spec.md v1 (14 Sep 2026)
   and db-energy-button-system.md v1 (15 Sep 2026).
   Every value below is a token or a value on the spacing scale.
   ============================================================ */

:root{
  color-scheme: light;

  /* Colour — seven jobs, four supports, one error */
  --navy:#0E2A44;
  --deep:#071F33;
  --orange:#E8692A;
  --orange-hover:#F0803F;
  --sky:#3E8BA3;          /* charts, Estimate state, focus ring. Nothing else */
  --amber:#C9721A;        /* icons and graphic marks only, 3.56:1 on white    */
  --amber-tint:#FCF1E3;   /* icon tiles, row highlight, tinted cards, notes   */
  --amber-line:#EFDFCD;   /* the border that goes with amber-tint             */
  /* The footer hairline: amber-tint at 18%, so the rule keeps the old
     Navy rule's weight (1.69:1 on Deep against 1.47) while staying warm.
     Derived from a token, not a new colour. */
  --rule-footer:color-mix(in srgb, var(--amber-tint) 18%, transparent);
  --slate:#55626F;
  --mist:#FAF6EF;
  --white:#FFFFFF;

  /* Supports */
  --line:#E8E0D6;
  --line-dark:#1F3C58;
  --mist-text:#DAD3C8;
  --slate-on-dark:#A89E91;

  /* Validation only */
  --error-border:#B6463C;
  --error-text:#9E3A31;

  /* Radius family */
  --radius-pill:999px;
  --radius-card:14px;
  --radius-tile:10px;
  --radius-sm:6px;
  --radius-round:50%;

  /* Type */
  --font-display:'Bricolage Grotesque','Segoe UI',Arial,sans-serif;
  --font-body:'Atkinson Hyperlegible','Segoe UI',Arial,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  /* Layout */
  --db-max:87.5rem;
  --db-gutter:48px;
  --db-col-gap:32px;
  --db-inset:calc(max((100vw - var(--db-max)) / 2, 0px) + var(--db-gutter));
  --db-content:min(calc(100vw - 2*var(--db-gutter)), calc(var(--db-max) - 2*var(--db-gutter)));

  /* Motion */
  --motion-micro:160ms cubic-bezier(0.4,0,0.2,1);
  --motion-reveal:320ms cubic-bezier(0.16,1,0.3,1);
  --motion-button:450ms cubic-bezier(0.21,1,0.34,1);
  --motion-cross:150ms cubic-bezier(0.215,0.61,0.355,1);
  --motion-busy:800ms linear infinite;   /* fenced to .is-loading, §42b */

  /* Elevation */
  --shadow-soft:0 4px 14px rgba(14,42,68,0.08);
  --shadow-card:0 18px 50px rgba(14,42,68,0.16);

  /* Section padding, per breakpoint (§12) */
  --pad-standard:128px;
  --pad-compact:64px;
}
@media (max-width:1279px){ :root{ --db-gutter:40px; --pad-standard:96px; --pad-compact:48px; } }
@media (max-width:1023px){ :root{ --db-gutter:32px; } }
@media (max-width:767px){ :root{ --db-gutter:24px; --db-col-gap:16px; --pad-standard:64px; --pad-compact:32px; } }

*{ box-sizing:border-box; }
body{
  margin:0;
  background:var(--white);
  color:var(--navy);
  font:400 17px/1.60 var(--font-body);
  -webkit-font-smoothing:antialiased;
}
img{ max-width:100%; display:block; }
[hidden]{ display:none !important; }

/* ---------- Type: element defaults, so sections comply by deleting classes (§34) ---------- */
h1,h2,h3{ margin:0; font-family:var(--font-display); color:var(--navy); text-wrap:balance; }
h1{ font-weight:700; font-size:64px; line-height:1.05; letter-spacing:-0.02em; }
h2{ font-weight:700; font-size:44px; line-height:1.10; letter-spacing:-0.015em; }
h3{ font-weight:600; font-size:28px; line-height:1.25; letter-spacing:-0.01em; }
p{ margin:0; }
.lead{ font-size:20px; line-height:1.55; }
.body{ font-size:17px; line-height:1.60; }
.small{ font-size:14px; line-height:1.50; color:var(--slate); }
.label{
  font:500 12px/1 var(--font-mono);
  letter-spacing:0.08em; text-transform:uppercase; color:var(--slate);
}
.measure{ max-width:68ch; }
.sr{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }

@media (max-width:1279px){ h1{font-size:56px} h2{font-size:40px} h3{font-size:26px} }
@media (max-width:1023px){ h1{font-size:48px} h2{font-size:36px} h3{font-size:24px} .lead{font-size:19px} }
@media (max-width:767px){  h1{font-size:40px} h2{font-size:30px} h3{font-size:21px} .lead{font-size:18px} }

/* ---------- Grounds ---------- */
.g-white{ background:var(--white); }
.g-mist { background:var(--mist); }
.g-navy { background:var(--navy); }
.g-deep { background:var(--deep); }
[data-family="dark"]{ color:var(--mist-text); }
[data-family="dark"] h1,[data-family="dark"] h2,[data-family="dark"] h3{ color:var(--white); }
[data-family="dark"] .small,[data-family="dark"] .label{ color:var(--slate-on-dark); }
[data-family="dark"] .lead{ color:var(--mist-text); }

/* ---------- Container and sections ---------- */
.db-container{
  max-width:var(--db-max);
  margin-inline:auto;
  padding-inline:var(--db-gutter);
}
.sec{ padding-block:var(--pad-standard); }
.sec--compact{ padding-block:var(--pad-compact); }

/* Section header pattern (§32, §33) */
.sec-head{ display:flex; flex-direction:column; align-items:flex-start; }
.sec-head .label + h2{ margin-top:12px; }
.sec-head h2 + .lead{ margin-top:20px; }
/* Raised a step so a component's own `margin:0` reset cannot tie with this and
   win on source order, which is exactly what killed the gap above the area pills. */
.db-container .sec-head + *{ margin-top:48px; }
@media (max-width:767px){ .db-container .sec-head + *{ margin-top:32px; } }
.sec-head--centre{ align-items:center; text-align:center; }
.sec-head--centre .measure{ margin-inline:auto; }

/* 12-column grid (§14) */
.db-grid{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap); }
/* Grid items default to min-width:auto, so one wide child (a table, a long token
   name) floors the whole track and the page scrolls sideways. */
.db-grid > *{ min-width:0; }
.prose-6{ grid-column:span 6; }      /* §14a */
.aside-6{ grid-column:span 6; }
@media (max-width:1023px){ .prose-6{ grid-column:span 8; } .aside-6{ grid-column:span 12; } }
@media (max-width:767px){ .db-grid{ grid-template-columns:1fr; gap:16px; } .prose-6,.aside-6{ grid-column:auto; } }

/* ============================================================
   BUTTONS (db-energy-button-system.md §8, verbatim)
   ============================================================ */
.db-btn{
  position:relative; isolation:isolate; overflow:hidden;
  box-sizing:border-box;
  display:inline-flex; align-items:center; justify-content:center;
  height:52px; padding:0 28px;
  border:0; outline:0; box-shadow:none;
  border-radius:var(--radius-pill);
  /* 19px, not 17px. At 700 weight this crosses WCAG's 18.66px large-text
     threshold, the contrast floor drops from 4.5:1 to 3:1, and the White label
     on the Orange fill passes legitimately at 3.24 on every ground. Reverting
     to 17px reopens §53a as a real failure rather than a documented one. */
  font:700 19px/1 var(--font-body); letter-spacing:0; white-space:nowrap;
  text-decoration:none; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.db-btn:focus-visible{ outline:3px solid var(--sky); outline-offset:2px; }
.db-btn::before{
  content:""; position:absolute; inset:-1px; z-index:-1;
  background:var(--fill-hover);
  border-radius:var(--radius-pill);
  clip-path:inset(100% 13px 0 13px round var(--radius-pill));
  transition:clip-path var(--motion-button);
}
.roll{ display:block; overflow:hidden; height:24px; }
.stack{
  display:flex; flex-direction:column; transform:translateY(0);
  transition:transform var(--motion-button), color var(--motion-cross);
}
.stack > span{ height:24px; display:inline-flex; align-items:center; gap:10px; white-space:nowrap; }
.stack svg{ width:20px; height:20px; flex:none; }

@media (hover:hover){
  .db-btn:hover::before{ clip-path:inset(0 round var(--radius-pill)); }
  .db-btn:hover .stack { transform:translateY(-24px); color:var(--label-hover); }
}

[data-family="light"] .db-btn--primary  { --fill-hover:var(--navy);  --label-hover:var(--mist); }
[data-family="dark"]  .db-btn--primary  { --fill-hover:var(--white); --label-hover:var(--navy); }
/* Secondary on light grounds: Orange 1px outline (3.24:1 on White, 3.01:1 on
   Mist, both clear the 3:1 component floor), Navy label so it stays legible,
   and an Orange hover fill as instructed. The hover uses --orange-hover
   #F0803F rather than flat --orange, because a flat-orange hover would be
   pixel-identical to the Primary at rest; Navy on it measures 5.49:1. */
[data-family="light"] .db-btn--secondary{ color:var(--navy); --fill-hover:var(--orange-hover); --label-hover:var(--navy); }
[data-family="dark"]  .db-btn--secondary{ color:var(--mist); --fill-hover:var(--mist); --label-hover:var(--navy); }
[data-family="light"] .db-btn--tertiary { color:var(--navy); --label-hover:var(--navy); }
[data-family="dark"]  .db-btn--tertiary { color:var(--mist); --label-hover:var(--mist); }

/* CLOSED 15 Sep 2026, by the client: the Primary rest label and icon are White on
   ALL THREE ground families, not only on dark. Recorded in §53 as a named
   accessibility exception at a measured 3.2:1 against the 4.5:1 floor for 17px
   bold. One line closes it legitimately if wanted: 19px bold crosses into large
   text, where the floor drops to 3:1 and White passes on every ground. */
.db-btn--primary{
  background:var(--orange); color:var(--white);
  transition:background-color 0s var(--bg-delay,0s);
}
@media (hover:hover){
  .db-btn--primary:hover{ background:var(--fill-hover); --bg-delay:450ms; }
}
.db-btn--secondary{ background:transparent; border:1px solid currentColor; }
[data-family="light"] .db-btn--secondary{ border-color:var(--orange); }

.db-btn--tertiary{ height:auto; padding:0 0 6px; border:0; background:none; overflow:visible; }
.db-btn--tertiary::before{ content:none; }
.db-btn--tertiary .rule-rest{
  position:absolute; left:0; right:0; bottom:0; height:1px; background:var(--orange);
}
.db-btn--tertiary .rule-sweep{
  position:absolute; left:0; right:0; bottom:0; height:2px; background:var(--orange);
  transform:scaleX(0); transform-origin:right center;
  transition:transform var(--motion-button);
}
@media (hover:hover){
  .db-btn--tertiary:hover .rule-sweep{ transform:scaleX(1); transform-origin:left center; }
}

[data-family="light"] .db-btn:disabled,
[data-family="light"] .db-btn.is-disabled{ background:var(--mist); color:var(--slate); border:1px solid var(--line); cursor:not-allowed; }
[data-family="dark"]  .db-btn:disabled,
[data-family="dark"]  .db-btn.is-disabled{ background:var(--line-dark); color:var(--slate-on-dark); border:0; cursor:not-allowed; }
.db-btn:disabled::before,.db-btn.is-disabled::before{ content:none; }

/* A disabled button has no hover state at all. Without this the label rolls up to
   its duplicate row and crosses to --label-hover, which on a disabled button is the
   colour of the fill sitting behind it: the label rolls away and vanishes. */
.db-btn:disabled,.db-btn.is-disabled{ pointer-events:auto; }
@media (hover:hover){
  .db-btn:disabled:hover .stack,
  .db-btn.is-disabled:hover .stack{ transform:none; color:inherit; }
  .db-btn:disabled:hover::before,
  .db-btn.is-disabled:hover::before{ clip-path:inset(100% 13px 0 13px round var(--radius-pill)); }
  [data-family="light"] .db-btn--primary:disabled:hover,
  [data-family="light"] .db-btn--primary.is-disabled:hover{ background:var(--mist); }
  [data-family="dark"]  .db-btn--primary:disabled:hover,
  [data-family="dark"]  .db-btn--primary.is-disabled:hover{ background:var(--line-dark); }
}
.db-btn:disabled:active,.db-btn.is-disabled:active{ background:inherit; }
[data-family="light"] .db-btn:disabled:active,
[data-family="light"] .db-btn.is-disabled:active{ background:var(--mist); color:var(--slate); }
[data-family="dark"] .db-btn:disabled:active,
[data-family="dark"] .db-btn.is-disabled:active{ background:var(--line-dark); color:var(--slate-on-dark); }

[data-family="light"] .db-btn:active{ background:var(--deep); color:var(--mist); }
[data-family="dark"]  .db-btn:active{ background:var(--amber-tint); color:var(--navy); }

/* Button pairs (§37) */
.btn-pair{ display:flex; gap:16px; align-items:center; flex-wrap:wrap; }
@media (max-width:767px){
  .btn-pair{ flex-direction:column; align-items:stretch; gap:16px; }
  .btn-pair .db-btn{ width:100%; }
  .btn-pair .db-btn--tertiary{ width:auto; align-self:flex-start; }
}
@media (prefers-reduced-motion:reduce){
  .db-btn::before,.stack,.rule-sweep{ transition:none; }
}

/* ============================================================
   LINKS (§15)
   ============================================================ */
.db-link{
  color:var(--navy); text-decoration:underline;
  text-decoration-color:var(--orange); text-decoration-thickness:1px; text-underline-offset:2px;
  transition:text-decoration-thickness var(--motion-micro);
}
.db-link:hover{ text-decoration-thickness:2px; }
[data-family="dark"] .db-link{ color:var(--white); }

/* ============================================================
   STATE CHIPS, EYEBROW CHIPS, ICON TILES (§Numbers Law, §20, §21)
   ============================================================ */
.chip{
  display:inline-flex; align-items:center; height:24px; padding:0 10px;
  border-radius:var(--radius-pill);
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
  color:var(--slate); border:0; white-space:nowrap;
}
[data-family="dark"] .chip{ color:var(--slate-on-dark); }
/* The Sky signal moves to the border, which is a UI boundary judged at 3:1 and
   measures 3.87. The label was Sky at 12px, 3.86:1 against a 4.5 floor, so the
   Numbers Law's own chip was the site's worst contrast failure. Navy label. */
.chip--estimate{ border:1px solid var(--sky);  color:var(--navy); }
.chip--measured{ border:1px solid var(--navy); color:var(--navy); }
.chip--verified{ background:var(--navy); color:var(--mist); }
[data-family="dark"] .chip--estimate,
[data-family="dark"] .chip--measured{ border-color:var(--mist); color:var(--mist); }
[data-family="dark"] .chip--verified{ background:var(--mist); color:var(--navy); }

/* Icons sit bare. No tinted tile behind them: the tile was a container with
   nothing to contain, and it put a third ground inside a card that already has one.
   AMENDS SPEC §20. --amber-tint keeps its other two jobs (table rows, area fills). */
.db-icon{
  width:28px; height:28px; flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  color:var(--navy);
}
.db-icon svg{ width:28px; height:28px; }
.db-icon--info{ color:var(--amber); }
[data-family="dark"] .db-icon{ color:var(--mist); }

/* ============================================================
   CARDS — four-zone subgrid stack (§19, §19a)
   ============================================================ */
.db-card-row{ display:grid; grid-template-columns:repeat(3,1fr); gap:var(--db-col-gap); }
.db-card-row--2{ grid-template-columns:repeat(2,1fr); }
@media (max-width:1279px){ .db-card-row{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:767px){ .db-card-row,.db-card-row--2{ grid-template-columns:1fr; gap:16px; } }

.db-card{
  display:grid;
  grid-row:span 4;
  grid-template-rows:subgrid;
  row-gap:24px;
  padding:32px;
  background:var(--white);
  border:1px solid var(--line);
  border-radius:var(--radius-card);
}
.g-mist .db-card{ background:var(--white); }
.g-white .db-card{ background:var(--mist); }
[data-family="dark"] .db-card{ background:var(--navy); border-color:var(--line-dark); }
/* Measured vertical rhythm inside a card, revised 15 Sep: 32 icon to strip, 32
   strip to title, 32 title to body, 48 body to action. The row-gap was 16px
   against a comment describing 24px, so every step in the card was running 8px
   short of its own documented rhythm, which is what made it read as one block.
   The gap is back to 24 and the two steps that carry the reading, title to body
   and body to action, are lifted above it. All on the 8/16/24/32/48 scale. */
.db-card > .zone-strip{ margin-top:8px; }
.db-card > .zone-title{ margin-top:8px; }
.db-card > .zone-body{ margin-top:8px; }
.db-card > .zone-action{ align-self:end; margin-top:24px; }
.db-card--5{ grid-row:span 5; }                                /* icon · strip · title · body · action */

/* The strip holds an over-wide frame that pans on hover: you are looking further
   along the roof, not watching a card pop. Runs on --motion-reveal, no new token,
   and it is a transform on a child so nothing in the row reflows. */
.zone-strip .ph{
  aspect-ratio:20/7; border-radius:var(--radius-tile);
  overflow:hidden; position:relative;
}
.zone-strip .ph > .pan{
  position:absolute; inset:0; width:118%;
  background:repeating-linear-gradient(115deg,transparent 0 22px,rgba(14,42,68,0.05) 22px 44px);
  transform:translateX(0) scale(1);
  transition:transform 600ms cubic-bezier(0.16,1,0.3,1);
}
/* 15 Sep: the card has no hover state at all. The border no longer changes and the
   photograph no longer pans. The only thing that reacts to a pointer inside a card
   is the button, which has its own motion. Kept as a rule rather than deleted, so
   the pan is one line away if it is ever wanted back:
   .db-card:hover .zone-strip .ph > .pan{ transform:translateX(-15%) scale(1.06); } */
.db-card--navy .zone-strip .ph > .pan,
.db-card--tint .zone-strip .ph > .pan{ background:repeating-linear-gradient(115deg,transparent 0 22px,rgba(255,255,255,0.06) 22px 44px); }

/* Entrance, and it is meant to be seen. Three things land in sequence per card,
   staggered 90ms across the row: the card rises 28px and fades in, the strip
   wipes open from its bottom edge, and the icon draws its own stroke using the
   path's real measured length rather than a guessed dash array. Rest state is
   visible, so a card that is never observed is never hidden. */
@media (prefers-reduced-motion:no-preference){
  .db-card.card-in{ animation:dbCardIn 520ms cubic-bezier(0.16,1,0.3,1) both; animation-delay:calc(var(--i,0) * 90ms); }
  .db-card.card-in .zone-strip .ph{
    animation:dbWipe 640ms cubic-bezier(0.16,1,0.3,1) both;
    animation-delay:calc(160ms + var(--i,0) * 90ms);
  }
  .db-card .db-icon svg *{
    stroke-dasharray:var(--draw-len,120); stroke-dashoffset:var(--draw-len,120);
  }
  .db-card.card-in .db-icon svg *{
    animation:dbDraw 700ms cubic-bezier(0.16,1,0.3,1) forwards;
    animation-delay:calc(240ms + var(--i,0) * 90ms);
  }
}
@keyframes dbCardIn{ from{ opacity:0; transform:translateY(28px); } to{ opacity:1; transform:none; } }
@keyframes dbWipe{ from{ clip-path:inset(0 0 100% 0); } to{ clip-path:inset(0 0 0 0); } }
@keyframes dbDraw{ to{ stroke-dashoffset:0; } }

/* Colour variants. The ground changes; the geometry does not. */
.db-card--navy{ background:var(--navy); border-color:var(--line-dark); }
.g-white .db-card--navy,.g-mist .db-card--navy{ background:var(--navy); }
.db-card--navy h3{ color:var(--white); }
.db-card--navy .body{ color:var(--mist-text); }
.db-card--navy .db-icon{ color:var(--orange); }
.db-card--navy .ph{ background:var(--line-dark); border-color:var(--line-dark); color:var(--slate-on-dark); }

.db-card--amber{ background:var(--amber); border-color:var(--amber); }
.g-white .db-card--amber,.g-mist .db-card--amber{ background:var(--amber); }
.db-card--amber h3{ color:var(--deep); }
.db-card--amber .body{ color:var(--deep); }
.db-card--amber .db-icon{ color:var(--deep); }
.db-card--amber .ph{ background:rgba(255,255,255,0.18); border-color:rgba(7,31,51,0.28); color:var(--deep); }

.db-card--tint{ background:var(--amber-tint); border-color:var(--amber-line); }
.g-white .db-card--tint,.g-mist .db-card--tint{ background:var(--amber-tint); }
.db-card--tint h3,.db-card--tint .body{ color:var(--navy); }
.db-card--tint .db-icon{ color:var(--navy); }
.db-card--tint .ph{ background:var(--white); border-color:var(--amber-line); }
.db-card .zone-media img,.db-card .zone-media .ph{ border-radius:var(--radius-tile); }
.g-white .db-card .ph{ background:var(--white); }   /* §7a: no component shares its ground */
@supports not (grid-template-rows:subgrid){
  .db-card{ display:flex; flex-direction:column; gap:16px; }
  .db-card > .zone-body{ flex:1; }
}
@media (max-width:767px){ .db-card{ padding:24px; } }
@media (min-width:768px) and (max-width:1023px){ .db-card{ padding:28px; } }

/* ============================================================
   TABLES (§23 radius-sm, §9 borders, amber-tint row highlight)
   ============================================================ */
.table-wrap{ overflow-x:auto; }
.db-table{ width:100%; border-collapse:collapse; font-size:17px; min-width:640px; }
.db-table th{
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
  color:var(--slate); text-align:left; padding:16px; border-bottom:1px solid var(--line);
  white-space:nowrap;
}
.db-table td{
  padding:16px; border-bottom:1px solid var(--line); vertical-align:top;
  font-variant-numeric:tabular-nums;
}
.db-table tbody tr:last-child td{ border-bottom:0; }
/* The highlight follows the pointer rather than sitting on one pre-chosen row.
   A row highlighted in the markup is the designer's opinion about which system the
   reader wants; a row highlighted under the pointer is the reader's. focus-within
   carries it for keyboard, and :active gives touch the same feedback. */
.db-table tbody tr td{ transition:background-color var(--motion-micro); }
.db-table tbody tr:hover td,
.db-table tbody tr:focus-within td,
.db-table tbody tr:active td{ background:var(--amber-tint); }
.db-table tbody tr:hover td:first-child,
.db-table tbody tr:focus-within td:first-child{ border-radius:var(--radius-sm) 0 0 var(--radius-sm); }
.db-table tbody tr:hover td:last-child,
.db-table tbody tr:focus-within td:last-child{ border-radius:0 var(--radius-sm) var(--radius-sm) 0; }
.db-table tbody tr:hover td:first-child{ box-shadow:inset 3px 0 0 var(--amber); }
[data-family="dark"] .db-table th{ color:var(--slate-on-dark); border-bottom-color:var(--line-dark); }
[data-family="dark"] .db-table td{ border-bottom-color:var(--line-dark); color:var(--mist-text); }

/* ============================================================
   FORMS (§16, §17, §18)
   ============================================================ */
/* Every label sits 8px above its control, including the fieldset legend, which
   had 16px because the fieldset carried its own flex gap. */
.db-field{ display:flex; flex-direction:column; gap:8px; }
.db-fieldset{ border:0; padding:0; margin:0; display:flex; flex-direction:column; gap:8px; }
/* A <legend> is not a flex item: the fieldset's gap never applies to it, which is
   why this one label sat flush against its control. The margin is the only way. */
.db-legend{ margin-bottom:8px; }
.db-field label,.db-legend{ font:700 14px/1.5 var(--font-body); color:var(--navy); }
/* The fieldset legend is a field label like any other. It was set in the mono
   eyebrow style, which made the one question that routes the whole enquiry look
   like a section marker rather than a question. */
.db-legend{ padding:0; }
.db-input,.db-select,.db-textarea{
  height:52px; padding:0 16px;
  border:1px solid var(--line); border-radius:var(--radius-tile);
  background:var(--white); color:var(--navy);
  font:400 17px/1.5 var(--font-body);
  transition:border-color var(--motion-micro), box-shadow var(--motion-micro);
  width:100%;
}
.g-white .db-input,.g-white .db-select,.g-white .db-textarea{ background:var(--mist); }
.db-textarea{ height:auto; min-height:132px; padding:14px 16px; resize:vertical; }
.db-input::placeholder,.db-textarea::placeholder{ color:var(--slate); }
.db-input:focus,.db-select:focus,.db-textarea:focus{
  outline:0; border-color:var(--sky); box-shadow:0 0 0 3px rgba(62,139,163,0.25);
}
.db-field.is-error .db-input,.db-field.is-error .db-select{ border-color:var(--error-border); }
.db-error{
  display:flex; align-items:center; gap:8px;
  font-size:14px; line-height:1.5; color:var(--error-text);
}
.db-error svg{ width:16px; height:16px; flex:none; }
.db-success{ display:flex; align-items:center; gap:8px; color:var(--navy); font-size:17px; }
.db-success svg{ width:20px; height:20px; flex:none; color:var(--navy); }

/* Funnel split — radio cards (every page carries one, per the build brief) */
.funnel-split{ display:grid; grid-template-columns:repeat(3,1fr); gap:16px; }
@media (max-width:767px){ .funnel-split{ grid-template-columns:1fr; } }
.funnel-opt{ position:relative; }
.funnel-opt input{ position:absolute; inset:0; opacity:0; width:auto; height:auto; margin:0; cursor:pointer; }
.funnel-opt span{
  display:flex; align-items:center; justify-content:center; text-align:center;
  min-height:52px; padding:14px 16px;
  border:1px solid var(--line); border-radius:var(--radius-tile);
  background:var(--white); font-weight:700; font-size:17px; color:var(--navy);
  transition:border-color var(--motion-micro), background-color var(--motion-micro);
}
.g-white .funnel-opt span{ background:var(--mist); }
.funnel-opt input:checked + span{ border-color:var(--navy); background:var(--amber-tint); }
.funnel-opt input:focus-visible + span{ outline:3px solid var(--sky); outline-offset:2px; }

/* ============================================================
   FAQ ACCORDION (§25 borders, §42 motion — micro only)
   ============================================================ */
.db-faq{ border-top:1px solid var(--line); }
[data-family="dark"] .db-faq{ border-top-color:var(--line-dark); }
.db-faq details{ border-bottom:1px solid var(--line); }
[data-family="dark"] .db-faq details{ border-bottom-color:var(--line-dark); }
.db-faq summary{
  list-style:none; cursor:pointer;
  display:flex; align-items:center; justify-content:space-between; gap:24px;
  padding:24px 0; min-height:48px;
  font-family:var(--font-display); font-weight:600; font-size:21px; line-height:1.25; color:var(--navy);
  transition:color var(--motion-micro);
}
[data-family="dark"] .db-faq summary{ color:var(--white); }
.db-faq summary::-webkit-details-marker{ display:none; }
.db-faq summary:focus-visible{ outline:3px solid var(--sky); outline-offset:2px; border-radius:var(--radius-sm); }
.faq-sign{ position:relative; width:24px; height:24px; flex:none; color:var(--amber); }
[data-family="dark"] .faq-sign{ color:var(--mist); }
.faq-sign svg{ position:absolute; inset:0; width:24px; height:24px; transition:opacity var(--motion-micro); }
.faq-sign .minus{ opacity:0; }
details[open] .faq-sign .plus{ opacity:0; }
details[open] .faq-sign .minus{ opacity:1; }
.db-faq .answer{ padding:0 0 24px; max-width:68ch; }
.db-faq .answer p + p{ margin-top:16px; }

/* ============================================================
   TESTIMONIAL (§Compliance — attribution or it does not run)
   ============================================================ */
.db-quote{
  display:grid; gap:24px; padding:32px;
  border:1px solid var(--line); border-radius:var(--radius-card); background:var(--white);
}
.g-white .db-quote{ background:var(--mist); }
[data-family="dark"] .db-quote{ background:var(--navy); border-color:var(--line-dark); }
.db-quote blockquote{
  margin:0; font-family:var(--font-display); font-weight:600;
  font-size:28px; line-height:1.25; letter-spacing:-0.01em; color:var(--navy); max-width:24ch;
}
[data-family="dark"] .db-quote blockquote{ color:var(--white); }
.db-quote .attrib{ display:flex; align-items:center; gap:16px; }
.avatar{
  width:48px; height:48px; flex:none; border-radius:var(--radius-round);
  background:var(--mist); border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center;
  font:500 12px/1 var(--font-mono); color:var(--slate); text-align:center;
}
@media (max-width:767px){ .db-quote{ padding:24px; } .db-quote blockquote{ font-size:21px; } }

/* ============================================================
   MEDIA PLACEHOLDERS (§26 — a placeholder ships before a stock photo does)
   ============================================================ */
.ph{
  display:flex; align-items:flex-end; justify-content:flex-start;
  background:var(--mist);
  border:1px solid var(--line);
  border-radius:var(--radius-card);
  padding:16px;
  font:500 12px/1.4 var(--font-mono);
  letter-spacing:0.08em; text-transform:uppercase; color:var(--slate);
  width:100%;
}
.ph--16x9{ aspect-ratio:16/9; }
.ph--4x3{ aspect-ratio:4/3; }
.ph--1x1{ aspect-ratio:1/1; }
.ph--round{ border-radius:var(--radius-round); align-items:center; justify-content:center; text-align:center; padding:24px; }
.ph--bleed{ border-radius:0; border-left:0; border-right:0; }
[data-family="dark"] .ph{ background:var(--line-dark); border-color:var(--line-dark); color:var(--slate-on-dark); }


/* ============================================================
   EDITORIAL ROWS (§09) — not a card row. No box, no border, no
   radius: hairlines and the grid do the work, so a page can carry
   three ideas without carrying a third row of boxes.
   ============================================================ */
.db-rows{ display:flex; flex-direction:column; }
.db-rows .r{
  display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap);
  padding-block:48px; border-top:1px solid var(--line);
}
.db-rows .r:last-child{ border-bottom:1px solid var(--line); }
[data-family="dark"] .db-rows .r{ border-color:var(--line-dark); }
.db-rows .k{ grid-column:span 3; display:flex; align-items:flex-start; gap:16px; }
.db-rows .k .n{ font:500 14px/1 var(--font-mono); letter-spacing:0.08em; color:var(--navy); padding-top:6px; }
.db-rows .c{ grid-column:span 8; }
.db-rows .c .body{ margin-top:16px; max-width:68ch; }
@media (max-width:1023px){ .db-rows .k{ grid-column:span 4; } .db-rows .c{ grid-column:span 8; } }
@media (max-width:767px){
  .db-rows .r{ grid-template-columns:1fr; gap:16px; padding-block:32px; }
  .db-rows .k,.db-rows .c{ grid-column:auto; }
}

/* ============================================================
   LIFT ROWS (§09) — the Rapid Despatch "Why businesses use us"
   mechanic, rebuilt on DB Energy tokens.

   How it actually works, since it is easy to mis-describe: the LIST
   is the sticky element, not the cards. The cards sit in it in normal
   flow, and scroll progress drives each card's HEIGHT down from its
   open height to a floor. Because they are in flow, shrinking card 1
   pulls card 2 up over it. Nothing is absolutely positioned and no
   card is transformed. The track above is a tall empty runway that
   provides the scroll budget.

   AMENDS §44 and §Layout Exceptions, which ban pinned and
   scroll-driven behaviour outright.
   ============================================================ */
.lift{
  --lift-open:344px;      /* a row with its rule, spacer, heading, paragraph and visual */
  --lift-floor:128px;     /* what is left once it has collapsed: rule, spacer, heading  */
  --lift-n:3;             /* set by JS from the number of rows actually in the markup   */
  --lift-gap:24px;
  --lift-top:100px;       /* 6.25rem, as the reference */
  --lift-travel:302px;    /* the reference's single runway addition, not a per-row budget */
  --lift-drift:100px;     /* the list rises by this much across the whole fold */
}
/* The runway is the open list plus one flat 302px, exactly as the reference does
   it. The scroll distance the fold actually takes is NOT this number: it comes
   from where the scrub starts and ends (see the JS), which is what produces the
   reference's pacing. Deriving a per-row budget from this height is what made the
   previous version feel wrong. */
.lift-track{
  height:calc(var(--lift-n) * var(--lift-open)
              + (var(--lift-n) - 1) * var(--lift-gap)
              + var(--lift-travel));
  margin-bottom:calc(-1 * var(--lift-drift));
}
/* The header is NOT sticky: it scrolls away like any other section header and only
   the rows pin. The list is the sticky element, and its containing block is the
   track, which is tall enough to hold it there for the whole fold. */
.lift-list{ position:sticky; top:var(--lift-top); overflow:hidden; display:flex; flex-direction:column; gap:var(--lift-gap); will-change:transform; }
.lift-card{ position:relative; overflow:hidden; height:var(--lift-open); }
.lift-rule{ height:1px; background:var(--line); width:100%; }
[data-family="dark"] .lift-rule{ background:var(--line-dark); }
.lift-sp{ height:40px; }
.lift-grid{ display:grid; grid-template-columns:repeat(12,1fr); gap:24px var(--db-col-gap); }
.lift-head{ grid-column:1 / 5; }
.lift-head h3{ margin:0; }
.lift-body{ grid-column:5 / 10; }
.lift-body .body{ max-width:42ch; opacity:1; transition:opacity 200ms linear; }
/* Version A: an icon in a column of its own, then the heading, then the paragraph
   in the width the visual had. The icon is Amber rather than Navy so it reads as a
   marker beside the heading instead of a second piece of heading weight. */
.lift--text .lift-icon{ grid-column:1 / 2; }
.lift--text .lift-head{ grid-column:2 / 6; }
.lift--text .lift-body{ grid-column:6 / 12; }
.lift--text .lift-body .body{ max-width:58ch; }
.lift-icon .db-icon{ color:var(--amber); width:32px; height:32px; }
.lift-icon .db-icon svg{ width:32px; height:32px; }
/* Version B: a photograph in the third column. */
.lift-shot{ grid-column:10 / 13; }
.lift-shot .ph{ aspect-ratio:3/2; }
@media (max-width:1279px){
  .lift-head,.lift-body,.lift-shot,.lift-icon,
  .lift--text .lift-head,.lift--text .lift-body,.lift--text .lift-icon{ grid-column:span 12; }
  .lift-shot{ order:-1; }
  .lift{ --lift-open:520px; --lift-floor:120px; }
}
@media (max-width:767px){
  .lift-track{ height:auto !important; margin-bottom:0 !important; }
  .lift-list{ position:static; }
  .lift-list{ overflow:visible; }
  .lift-card{ height:auto !important; }
  .lift-body .body{ opacity:1 !important; }
  .lift-sp{ height:24px; }
}
/* No JS, or reduced motion: ordinary rows, open, in order. */
.lift:not(.is-live) .lift-track{ height:auto; margin-bottom:0; }
.lift:not(.is-live) .lift-list{ position:static; }
.lift:not(.is-live) .lift-list{ overflow:visible; }
.lift:not(.is-live) .lift-card{ height:auto; }
@media (prefers-reduced-motion:reduce){
  .lift-track{ height:auto !important; margin-bottom:0 !important; }
  .lift-list{ position:static; }
  .lift-list{ overflow:visible; }
  .lift-card{ height:auto !important; }
  .lift-body .body{ opacity:1 !important; }
}

/* ============================================================
   CASE CAROUSEL (§10) — one job on screen at a time, advancing
   itself every 5 seconds. Text on the left, one large frame on the
   right, dots beneath. Pauses on hover, on keyboard focus, and when
   the tab is in the background; does not run at all under reduced
   motion, where it becomes a plain list of all three.
   ============================================================ */
.cx-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:32px; flex-wrap:wrap; }
.cx-head .sec-head{ flex:1 1 auto; }
.cx-head .db-btn{ flex:none; margin-top:8px; }

.cx-stage{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap); align-items:start; }
.cx-track{ grid-column:1 / 13; display:grid; }
.cx-slide{
  grid-area:1 / 1; display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap);
  opacity:0; visibility:hidden;
  transition:opacity var(--motion-reveal), visibility var(--motion-reveal);
}
.cx-slide[data-on="true"]{ opacity:1; visibility:visible; }
.cx-text{ grid-column:1 / 5; }
.cx-text .date{ color:var(--slate); }
.cx-text h3{ margin:16px 0 0; font-size:36px; line-height:1.15; }
.cx-text .body{ margin-top:20px; max-width:34ch; }
.cx-text .db-btn--tertiary{ margin-top:32px; }
.cx-shot{ grid-column:5 / 13; position:relative; }
.cx-shot .ph{ aspect-ratio:16/10; overflow:hidden; }
.cx-shot .ph > .pan{
  position:absolute; inset:0;
  background:repeating-linear-gradient(115deg,transparent 0 22px,rgba(14,42,68,0.05) 22px 44px);
  transform:scale(1.05); transition:transform 1200ms cubic-bezier(0.16,1,0.3,1);
}
.cx-slide[data-on="true"] .cx-shot .ph > .pan{ transform:scale(1); }
/* Tags ride on a White pill over the photograph. White is a sanctioned ground and
   Navy on it is 14.65:1; a Slate chip straight onto an unoverlaid image is not
   readable and §21's chip styles all assume a known ground. */
.cx-tags{ position:absolute; top:24px; right:24px; display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }
.cx-tag{
  display:inline-flex; align-items:center; height:32px; padding:0 14px;
  background:var(--white); color:var(--navy); border-radius:var(--radius-pill);
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
}
/* Navigation is a row of progress bars, not dots: the active one fills over the
   five seconds so the advance is visible before it happens, and any bar can be
   clicked to jump. The bar is 4px tall with a 44px invisible hit area, so it is a
   real tap target at §38's floor without being a 44px slab on the page. */
.cx-nav{ display:flex; gap:16px; justify-content:center; margin-top:48px; }
.cx-bar{
  position:relative; width:clamp(72px,12vw,160px); height:4px;
  padding:0; border:0; border-radius:var(--radius-pill);
  background:var(--line); cursor:pointer; overflow:visible;
}
.cx-bar::before{ content:""; position:absolute; inset:-20px 0; }
.cx-bar i{
  position:absolute; inset:0; display:block; border-radius:var(--radius-pill);
  background:var(--navy); transform:scaleX(0); transform-origin:left center;
  will-change:transform; backface-visibility:hidden;
}
/* The fill is a compositor animation now, not a transform JS writes on every
   frame. The old loop repainted all three bars sixty times a second and advanced
   at elapsed >= DUR, so the active bar jumped from about 0.99 straight back to 0
   and never visibly landed. That is the stutter. One CSS animation runs on the
   selected bar and pauses, rather than restarting, when the pointer is held. */
.cx-bar[aria-selected="true"] i{ animation:cxFill var(--cx-dur,5000ms) linear forwards; }
.cx.is-held .cx-bar[aria-selected="true"] i{ animation-play-state:paused; }
.cx:not(.is-seen) .cx-bar[aria-selected="true"] i{ animation-play-state:paused; }
@keyframes cxFill{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }

.cx-bar:hover{ background:var(--slate-on-dark); }
.cx-bar[aria-selected="true"]{ background:var(--line); }
.cx-bar:focus-visible{ outline:3px solid var(--sky); outline-offset:8px; }
.cx-note{ margin-top:32px; text-align:center; }
@media (max-width:1023px){
  .cx-text{ grid-column:1 / 13; }
  .cx-shot{ grid-column:1 / 13; margin-top:32px; }
  .cx-text h3{ font-size:30px; }
}
@media (max-width:767px){
  .cx-slide{ grid-template-columns:1fr; gap:0; }
  .cx-text,.cx-shot{ grid-column:auto; }
  .cx-tags{ top:16px; right:16px; }
}
/* No JS or reduced motion: every job visible, in order, nothing moving. */
.cx:not(.is-live) .cx-track,
.cx:not(.is-live) .cx-slide{ display:block; }
.cx:not(.is-live) .cx-slide{ opacity:1; visibility:visible; margin-bottom:96px; }
.cx:not(.is-live) .cx-nav{ display:none; }
@media (prefers-reduced-motion:reduce){
  .cx-track{ display:block; }
  .cx-slide{ opacity:1 !important; visibility:visible !important; display:block; margin-bottom:96px; }
  .cx-slide .cx-shot .ph > .pan{ transform:scale(1); }
  .cx-nav{ display:none; }
}

/* ============================================================
   TRUST BAR (§11) — four columns, one row, hairline dividers.
   No cards: no ground, no border box, no radius. Just the four
   segments of the copy separated by a 1px rule, centred.
   ============================================================ */
.trust-4{ display:grid; grid-template-columns:repeat(4,1fr); }
.trust-cell{
  display:flex; flex-direction:column; align-items:center; text-align:center; gap:20px;
  padding:0 32px; border-left:1px solid var(--line);
}
.trust-cell:first-child{ border-left:0; }
.trust-cell .slot{ height:56px; display:flex; align-items:center; justify-content:center; }
.trust-cell .slot img.accr-logo{ display:block; }
.trust-cell .slot .db-icon{ width:28px; height:28px; }
.trust-cell .slot .db-icon svg{ width:28px; height:28px; }
.trust-cell p{ font-size:17px; line-height:1.6; color:var(--navy); max-width:28ch; }
.trust-cell .pending-ref{ color:var(--error-text); }
.trust-cell .ref{ font:500 12px/1.4 var(--font-mono); letter-spacing:0.08em; color:var(--slate); display:block; margin-top:8px; }
.trust-cell.is-pending p{ color:var(--slate); }
@media (max-width:1023px){
  .trust-4{ grid-template-columns:repeat(2,1fr); row-gap:48px; }
  .trust-cell:nth-child(odd){ border-left:0; }
}
@media (max-width:767px){
  .trust-4{ grid-template-columns:1fr; row-gap:40px; }
  .trust-cell{ border-left:0; padding:0; }
  .trust-cell + .trust-cell{ border-top:1px solid var(--line); padding-top:40px; }
}

/* ============================================================
   CASE ROWS (§10) — alternating full-width rows. The shoot is the
   most expensive asset on this build; a 4:3 thumbnail in a card
   wastes it, a 16:9 half-width frame does not.
   ============================================================ */
.case-rows{ display:flex; flex-direction:column; gap:96px; }
@media (max-width:767px){ .case-rows{ gap:48px; } }
.case-row{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap); align-items:center; }
.case-row .m{ grid-column:span 7; }
.case-row .t{ grid-column:span 5; }
.case-row:nth-child(even) .m{ grid-column:6 / span 7; grid-row:1; }
.case-row:nth-child(even) .t{ grid-column:1 / span 5; grid-row:1; }
.case-row .meta{ margin-bottom:16px; }
.case-row h3{ margin-bottom:16px; }
.case-row .db-btn--tertiary{ margin-top:24px; }
@media (max-width:1023px){ .case-row .m,.case-row .t{ grid-column:span 6; } .case-row:nth-child(even) .m{ grid-column:7 / span 6; } .case-row:nth-child(even) .t{ grid-column:1 / span 6; } }
@media (max-width:767px){
  .case-row{ grid-template-columns:1fr; gap:24px; }
  .case-row .m,.case-row .t,.case-row:nth-child(even) .m,.case-row:nth-child(even) .t{ grid-column:auto; grid-row:auto; }
}

/* ============================================================
   ACCREDITATION LOGOS (§11)
   ============================================================ */
.accred{ display:flex; flex-wrap:wrap; align-items:center; gap:24px 32px; }
.logo-slot{
  height:56px; min-width:120px; padding:0 16px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--white); border:1px solid var(--line); border-radius:var(--radius-tile);
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase; color:var(--slate);
}
.g-white .logo-slot{ background:var(--mist); }
[data-family="dark"] .logo-slot{ background:var(--line-dark); border-color:var(--line-dark); color:var(--slate-on-dark); }
.accred-copy{ margin-top:24px; max-width:68ch; }
.accred-copy a{ color:var(--navy); text-decoration:underline; text-decoration-color:var(--orange); text-underline-offset:2px; }
.pending{ color:var(--slate); }

/* ============================================================
   NAVBAR (§46) — singleton, sticky, static, hairline
   ============================================================ */
.db-nav{
  position:sticky; top:env(safe-area-inset-top,0px); z-index:100;
  background:var(--white); border-bottom:1px solid var(--line);
  transition:transform var(--motion-micro);
}
/* Hides on scroll down, returns on scroll up. AMENDS §45, which said the navbar
   does not move. The transform runs on --motion-micro rather than a new duration. */
.db-nav.is-hidden{ transform:translateY(calc(-100% - env(safe-area-inset-top,0px))); }
@media (prefers-reduced-motion:reduce){ .db-nav{ transition:none; } }
/* The logo leaves the 1400 container and sits 24px from the viewport edge, while
   the links and the CTA keep the container's right edge. This is a deliberate
   exception to §Three laws 3 and the only element on the site that starts outside
   the container: it buys the bar about 44px at 1440 and considerably more on a
   wide monitor, which is what stops six links and a 52px pill from crowding. */
.db-nav .db-container.inner{
  display:flex; align-items:center; gap:32px; height:88px;
  max-width:none; padding-left:24px; padding-right:var(--db-inset);
}
.db-nav .links .db-btn{ flex:none; }   /* a flex child shrinks by default; the pill must not */
.db-logo{ display:inline-flex; align-items:center; gap:10px; text-decoration:none; flex:none; }
.db-logo .mark{ width:32px; height:32px; flex:none; }
.db-logo .word{
  font-family:var(--font-display); font-weight:700; font-size:20px; line-height:1;
  color:var(--navy); letter-spacing:-0.01em; white-space:nowrap;
}
.db-nav .links{ display:flex; align-items:center; gap:32px; margin-left:auto; }
/* Direct children only. Left unscoped, this rule also matched every anchor inside
   a dropdown panel and beat the panel's own rule on specificity, which is why the
   live panel's rows lost their 12/16 padding while the pinned copy kept it. */
.db-nav .links > a:not(.db-btn){
  position:relative; font:700 17px/1 var(--font-body); color:var(--navy);
  text-decoration:none; padding:8px 0; transition:color var(--motion-micro);
}
.db-nav .links > a:not(.db-btn):hover{ color:var(--slate); }
.db-nav .links > a[aria-current="page"]::after{
  content:""; position:absolute; left:0; right:0; bottom:-2px; height:2px; background:var(--orange);
}
.db-nav .tel{ position:relative; }
.hamburger{
  display:none; width:48px; height:48px; margin-left:auto;
  align-items:center; justify-content:center;
  background:none; border:1px solid var(--line); border-radius:var(--radius-tile); color:var(--navy);
  cursor:pointer;
}
/* The sixth link moves the nav breakpoint. With five links the bar fitted down to
   1024; with About back in it overflows by 262px there and by 14px at 1280. Rather
   than invent a breakpoint, the full bar now starts at 1280 — the cut that already
   governs cards and type — and the hamburger covers everything below it. */
@media (max-width:1599px){ .db-nav .links{ gap:24px; } }
/* Restoring the CTA's 28px side padding costs 20px at the narrow end of the full
   bar, so the link gap takes one step down on the scale below 1360. */
@media (max-width:1359px){ .db-nav .links{ gap:16px; } }

@media (max-width:1279px){
  .db-nav .db-container.inner{ height:72px; }
  .db-nav .links{ display:none; }
  .hamburger{ display:inline-flex; }
}

/* Mobile nav panel (§40) — shown here as a static demo */
.db-mobile-panel{
  background:var(--navy); border-radius:var(--radius-card); padding:32px; max-width:480px;
}
.db-mobile-panel a.m-link{
  display:flex; align-items:center; height:52px;
  font-family:var(--font-display); font-weight:600; font-size:21px; color:var(--white);
  text-decoration:none; position:relative;
}
.db-mobile-panel a.m-link[aria-current="page"]::after{
  content:""; position:absolute; left:0; bottom:8px; width:2.5em; height:2px; background:var(--orange);
}
.db-mobile-panel .m-cta{ display:flex; flex-direction:column; gap:16px; margin-top:32px; }
.db-mobile-panel .m-cta .db-btn{ width:100%; }

/* ============================================================
   HERO
   ============================================================ */
.db-hero .db-grid{ align-items:center; row-gap:48px; }
.db-hero .descriptor{ margin-top:32px; }
.db-hero .lead{ margin-top:24px; }
.db-hero .btn-pair{ margin-top:32px; }

/* ============================================================
   TRUST / ACCREDITATION STRIP (§22)
   ============================================================ */
.trust-strip{ display:flex; flex-wrap:wrap; align-items:center; gap:16px 48px; }
.trust-strip .reg{
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
  color:var(--navy); text-decoration:underline; text-decoration-color:var(--orange);
  text-decoration-thickness:1px; text-underline-offset:4px;
  transition:text-decoration-thickness var(--motion-micro);
}
.trust-strip .reg:hover{ text-decoration-thickness:2px; }
[data-family="dark"] .trust-strip .reg{ color:var(--mist); }

/* ============================================================
   PROCESS STEPS — a real sequence, so it is numbered
   ============================================================ */
.db-steps{ display:grid; grid-template-columns:repeat(2,1fr); gap:48px var(--db-col-gap); counter-reset:step; }
@media (max-width:767px){ .db-steps{ grid-template-columns:1fr; gap:32px; } }
.db-step{ display:grid; grid-template-columns:48px 1fr; gap:24px; align-items:start; counter-increment:step; }
.db-step .n{
  width:48px; height:48px;
  display:flex; align-items:center; justify-content:flex-start;
  color:var(--navy); font:500 21px/1 var(--font-mono);
}
.db-step .n::before{ content:counter(step,decimal-leading-zero); }
[data-family="dark"] .db-step .n{ color:var(--mist); }
.db-step h3 + p{ margin-top:8px; }
.db-step .dur{ margin-top:8px; }

/* ============================================================
   PROCESS (§12) — horizontal. The section pins and the row of steps
   travels sideways as you scroll down. Below 1024, under reduced
   motion and with JS off it is a native horizontal scroll-snap rail
   instead, which is what a touch device wants anyway.
   AMENDS §44.
   ============================================================ */
.pr{ --pr-top:120px; --pr-travel:420px; --pr-hold:0.07; --pr-gap:96px; position:relative; }
.pr-head{ display:flex; align-items:flex-end; justify-content:space-between; gap:32px; flex-wrap:wrap; }
.pr-meter{ flex:none; min-width:220px; }
.pr-count{ display:flex; align-items:baseline; gap:8px; font-family:var(--font-mono); }
.pr-count .now{ font-size:44px; font-weight:500; line-height:1; color:var(--navy); font-variant-numeric:tabular-nums; }
.pr-count .of{ font-size:14px; letter-spacing:0.08em; color:var(--slate); }
.pr-rail{ margin-top:16px; height:4px; background:var(--line); border-radius:var(--radius-pill); overflow:hidden; }
.pr-rail i{ display:block; height:100%; background:var(--navy); border-radius:var(--radius-pill); transform-origin:left center; transform:scaleX(0); transition:transform 120ms linear; }

.pr-scene{ margin-top:48px; position:relative; }
.pr-pin{ padding-block:8px 0; }
.pr-view{ overflow:hidden; margin-top:48px; }
.pr-closing{ margin-top:40px; max-width:68ch; }
.pr-track{ display:flex; gap:var(--pr-gap); will-change:transform; }
/* Exactly three cards fill the viewport width, so the fourth is fully off the
   edge rather than half-showing. */
.pr-step{
  flex:0 0 calc((100% - 2 * var(--pr-gap)) / 3);
  border-top:1px solid var(--line); padding-top:28px;
  transition:opacity var(--motion-micro);
}
/* The icon shares a header row with the index rather than sitting immediately
   under it, which left them touching. */
.pr-top{ display:flex; align-items:center; justify-content:space-between; gap:16px; margin-bottom:28px; }
.pr-step .db-icon{ color:var(--navy); width:32px; height:32px; }
.pr-step .db-icon svg{ width:32px; height:32px; }
/* Reversed 15 Sep: Navy until the step is the active one, Amber while it is, and
   Navy again once passed. At most one Amber icon exists at a time, so the
   colour means "this is where you are" rather than "this is a step". */
.pr-step.is-on .db-icon{ color:var(--amber); }
.pr-step.is-done .db-icon{ color:var(--navy); }
.pr-step .n{
  display:flex; align-items:center; gap:12px; margin:0;
  font:500 14px/1 var(--font-mono); letter-spacing:0.08em; color:var(--slate);
  transition:color var(--motion-micro);
}
.pr-step .n::after{ content:""; width:8px; height:8px; border-radius:var(--radius-round); background:var(--line); transition:background-color var(--motion-micro), transform var(--motion-micro); }
.pr-step h3{ margin:0; color:var(--slate); transition:color var(--motion-micro); }
.pr-step .body{ margin-top:12px; }
.pr-step .dur{ margin-top:20px; display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.pr-step.is-on .n,.pr-step.is-done .n{ color:var(--navy); }
.pr-step.is-on .n::after{ background:var(--amber); transform:scale(1.5); }
.pr-step.is-done .n::after{ background:var(--navy); }
.pr-step.is-on h3,.pr-step.is-done h3{ color:var(--navy); }
/* Dimming by opacity put the whole inactive card below AA: Navy body at 55% on
   White measures 4.0. The step now dims by colour instead, which is the same
   hierarchy at a legible contrast: Slate 6.24 on White, 5.80 on Mist. */
.pr-step:not(.is-on):not(.is-done) .body{ color:var(--slate); }
.pr-step:not(.is-on):not(.is-done) .db-icon{ color:var(--slate); }

/* The fallback, and what touch always gets: a real horizontal scroller. */
.pr--rail .pr-scene{ height:auto !important; }
.pr--rail .pr-pin{ position:static !important; }
.pr--rail .pr-view{ overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:16px; }
.pr--rail .pr-track{ transform:none !important; }
.pr--rail .pr-step{ scroll-snap-align:start; opacity:1; }
.pr--rail .pr-step h3,.pr--rail .pr-step .n{ color:var(--navy); }
@media (max-width:1023px){
  .pr-scene{ height:auto !important; margin-top:32px; }
  .pr-pin{ position:static !important; }
  .pr-view{ overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:16px; margin-top:32px; }
  .pr-step{ flex:0 0 min(78vw, 360px); }
  .pr-track{ transform:none !important; }
  .pr-step{ scroll-snap-align:start; opacity:1 !important; }
  .pr-step h3,.pr-step .n{ color:var(--navy) !important; }
}
@media (prefers-reduced-motion:reduce){
  .pr-scene{ height:auto !important; }
  .pr-pin{ position:static !important; }
  .pr-view{ overflow-x:auto; scroll-snap-type:x mandatory; }
  .pr-track{ transform:none !important; }
  .pr-step{ opacity:1 !important; }
}

/* ============================================================
   FAQ LAYOUT (§14) — 40 / 60
   ============================================================ */
.faq-split{ display:grid; grid-template-columns:40fr 60fr; gap:var(--db-col-gap); align-items:start; }
.faq-split > *{ min-width:0; }
.faq-split .sec-head{ position:sticky; top:120px; }
@media (max-width:1023px){ .faq-split{ grid-template-columns:1fr; gap:48px; } .faq-split .sec-head{ position:static; } }

/* ============================================================
   FORM LAYOUT (§16) — 40 / 60, no photograph
   ============================================================ */
.form-split{ display:grid; grid-template-columns:40fr 60fr; gap:var(--db-col-gap); align-items:start; }
.form-split > *{ min-width:0; }
.form-split .intro{ position:sticky; top:120px; }
@media (max-width:1023px){ .form-split{ grid-template-columns:1fr; gap:48px; } .form-split .intro{ position:static; } }

/* ============================================================
   SERVICE AREAS
   ============================================================ */
.area-list{ display:flex; flex-wrap:wrap; gap:16px; list-style:none; margin:0; padding:0; }
.area-list a,.area-list .plain{
  display:inline-flex; align-items:center; min-height:48px; padding:0 24px;
  border:1px solid var(--line); border-radius:var(--radius-pill);
  background:var(--white); color:var(--navy); text-decoration:none;
  font:700 17px/1 var(--font-body);
  transition:border-color var(--motion-micro);
}
.g-white .area-list a,.area-list .plain{ background:var(--mist); }
.area-list a:hover{ border-color:var(--slate); }
.area-list .plain{ color:var(--slate); border-style:dashed; cursor:default; }

/* ============================================================
   BREADCRUMB
   ============================================================ */
.db-crumb{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.db-crumb a,.db-crumb span{ font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase; color:var(--slate); text-decoration:none; }
.db-crumb a:hover{ color:var(--navy); }
.db-crumb .sep{ color:var(--line); }
.db-crumb [aria-current="page"]{ color:var(--navy); }

/* ============================================================
   FULL-BLEED PHOTOGRAPH BAND (§Layout Exceptions — the only one)
   ============================================================ */
.db-bleed{ position:relative; }
.db-bleed .ph{ border-radius:0; border-left:0; border-right:0; aspect-ratio:16/9; }
@media (max-width:767px){ .db-bleed .ph{ aspect-ratio:4/3; } }
.db-bleed .overlay{
  position:absolute; inset:0; background:rgba(14,42,68,0.78);
  display:flex; align-items:center;
}
.db-bleed .col{
  width:calc(var(--db-content) * 0.5);
  margin-left:var(--db-inset);
}
@media (max-width:767px){ .db-bleed .col{ width:var(--db-content); } }

/* ============================================================
   FOOTER (§20) — laid out for THIS site's content, not borrowed.
   The reference footers balance because those companies have long
   service lists and short legal lines. Ours is the other way round:
   two, three and three service links, and a four-line registered
   company statement. So the tall content goes in a band of its own
   and the short link lists share one even row of five.
   ============================================================ */
/* 15 Sep: the footer's reading text is White, not warm grey. The warmth in this
   band is carried by the mono labels and by the three rules, which is where it
   reads as deliberate; on body copy and links it read as faded White. */
.db-footer{ background:var(--deep); color:var(--white); padding-block:80px 32px; }
.db-footer a{ color:var(--white); text-decoration:none; transition:color var(--motion-micro); }
.db-footer a:hover{ color:var(--amber); }
.db-footer h4{
  margin:0 0 16px; font:500 12px/1 var(--font-mono); letter-spacing:0.08em;
  text-transform:uppercase; color:var(--slate-on-dark);
}
.db-footer ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:12px; }

/* Band A — brand and the ways to reach us, side by side. */
.ft-lead{ display:grid; grid-template-columns:1.1fr 1fr; gap:48px var(--db-col-gap); align-items:start; }
.ft-lead > *{ min-width:0; }
.ft-lead .descriptor{ margin-top:24px; max-width:42ch; font-size:20px; line-height:1.55; color:var(--white); }
/* Stacked, not a wrapping row: three reach-outs one under the other read as a
   list of ways to get hold of us, where a flex row read as a toolbar and broke
   at an arbitrary point depending on how long the number was. */
.ft-reach{ display:flex; flex-direction:column; align-items:flex-start; gap:20px; }
.ft-reach .item{ display:flex; gap:12px; align-items:flex-start; }
.ft-reach .db-icon{ color:var(--white); width:20px; height:20px; flex:none; margin-top:3px; }
.ft-reach .db-icon svg{ width:20px; height:20px; }
.ft-reach .big{ font:700 20px/1.3 var(--font-body); color:var(--white); }
.ft-reach a.big:hover{ color:var(--white); text-decoration:underline; text-underline-offset:3px; }
@media (max-width:1023px){ .ft-lead{ grid-template-columns:1fr; gap:40px; } }

/* Band B — five even columns. Splitting the misc links into Company and
   Resources is what makes them even: 2, 3, 3, 3, 5 instead of 2, 3, 3, 8. */
.ft-cols{
  margin-top:64px; padding-top:48px; border-top:1px solid var(--rule-footer);
  display:grid; grid-template-columns:repeat(5,1fr); gap:48px var(--db-col-gap);
}
.ft-cols > *{ min-width:0; }
@media (max-width:1279px){ .ft-cols{ grid-template-columns:repeat(3,1fr); } }
@media (max-width:767px){ .ft-cols{ grid-template-columns:repeat(2,1fr); gap:40px 24px; } }

/* Band C — accreditations and socials. No tiles, no numbers, no outlines. */
.ft-marks{
  margin-top:64px; padding-top:40px; border-top:1px solid var(--rule-footer);
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:32px 48px;
}
.ft-accred{ display:flex; flex-wrap:wrap; align-items:center; gap:32px 40px; }
/* Reversed at build time, not filtered. A flat filter crushed every ink to one
   White and lost the overlaps — RECC's tick against its square, NICEIC's bar
   behind its letters, TrustMark's two interlocking sets. Each mark is instead
   separated into its own inks and each ink mapped to a different White: the ink
   that carries the mark at 100%, the secondary ink at 62%, alpha preserved. Two
   values, so an overlap still reads. These are still stand-ins for the official
   reversed assets from each brand pack. */
.ft-accred img{ height:40px; width:auto; display:block; }
.ft-social{ display:flex; gap:24px; }
.ft-social a{
  width:44px; height:44px; display:inline-flex; align-items:center; justify-content:center;
  color:var(--white); transition:color var(--motion-micro);
}
.ft-social a:hover{ color:var(--amber); }
.ft-social svg{ width:22px; height:22px; }

/* Band D — the legal statement, which is long here and short on the references. */
.ft-legal{
  margin-top:48px; padding-top:24px; border-top:1px solid var(--rule-footer);
  display:grid; grid-template-columns:1.6fr 1fr; gap:24px var(--db-col-gap); align-items:start;
}
.ft-legal p,.ft-legal a{ font-size:14px; line-height:1.6; color:var(--white); }
.ft-legal .links{ display:flex; flex-wrap:wrap; gap:8px 24px; justify-content:flex-end; }
.ft-legal .links a{ display:inline-flex; align-items:center; min-height:44px; }
/* The credit carries the highlight on the name alone: the sentence around it
   stays at legal weight, so it reads as a signature and not a second CTA.
   inline-block, not the row's inline-flex: as a flex item the <b> loses the
   space before it and the credit reads "built byWebWisp". */
.ft-legal a.ft-credit{ display:inline-block; line-height:44px; }
.ft-legal a.ft-credit b{ font-weight:inherit; color:var(--white); }
.ft-legal a.ft-credit:hover b{ color:var(--amber); }
@media (max-width:1023px){ .ft-legal{ grid-template-columns:1fr; } .ft-legal .links{ justify-content:flex-start; } }

/* ============================================================
   CONTENT SHAPES (§21–§26) — from the content-component audit.
   These four are the shapes the copy actually repeats, as opposed
   to the visual blocks set v1 catalogued. Labelled Blocks alone
   covers fifteen sections.
   ============================================================ */

/* 21 · Prose Block — three layouts, so a prose-heavy page does not run the
   same shape four times. All three keep the 68ch measure. -------------- */
.pb{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap); }
.pb > *{ min-width:0; }
.pb .col{ grid-column:1 / 7; }
.pb .col p + p{ margin-top:20px; }
.pb .db-btn--tertiary{ margin-top:24px; }

/* a · measure and pull: prose left, one lifted sentence facing it */
.pb--pull .pull{
  grid-column:8 / 13; align-self:start;
  font-family:var(--font-display); font-weight:600; font-size:28px; line-height:1.25;
  letter-spacing:-0.01em; color:var(--navy); max-width:22ch;
  padding-left:32px; border-left:1px solid var(--line);
}
[data-family="dark"] .pb--pull .pull{ color:var(--white); border-left-color:var(--line-dark); }

/* b · heading beside the text, not above it. The H2 holds the left rail and the
   paragraphs run down the right, which suits a section that argues one point. */
.pb--aside{ align-items:start; }
.pb--aside .head{ grid-column:1 / 5; }
.pb--aside .col{ grid-column:6 / 12; }
.pb--aside .head .label{ margin-bottom:12px; }

/* b, tail: a full-width band of photography closing the section. Static, so the
   left column no longer travels with the scroll. */
.pb-band{ margin-top:64px; }
.pb-band .ph{ height:400px; aspect-ratio:auto; }

/* c · heading left, the argument opening beside it, then a wide visual with one
   paragraph facing it. The heading column and the visual share a left edge. */
.pb--brief .head{ grid-column:1 / 5; }
.pb--brief .intro{ grid-column:6 / 13; }
.pb--brief .intro .lead-para{
  font-family:var(--font-display); font-weight:600; font-size:26px; line-height:1.3;
  letter-spacing:-0.01em; color:var(--navy); margin:0 0 20px; max-width:26ch;
}
[data-family="dark"] .pb--brief .intro .lead-para{ color:var(--white); }
.pb--brief .intro .body{ max-width:62ch; }
.pb--brief .media{ grid-column:1 / 8; margin-top:64px; }
.pb--brief .media .ph{ aspect-ratio:16/10; }
.pb--brief .aside{ grid-column:9 / 13; margin-top:64px; align-self:start; }

/* d · the same opening, then the long middle of the argument in a single narrow
   column with the visual holding the other half. */
.pb--column .head{ grid-column:1 / 5; }
.pb--column .intro{ grid-column:6 / 13; }
.pb--column .intro p + p{ margin-top:20px; }
.pb--column .run{ grid-column:1 / 7; margin-top:64px; }
.pb--column .run p + p{ margin-top:20px; }
.pb--column .run .nb{ margin-top:24px; }
.pb--column .media{ grid-column:8 / 13; margin-top:64px; align-self:start; }
.pb--column .media .ph{ aspect-ratio:4/5; }

/* e · centred. No columns at all: the heading and a short run of paragraphs
   centred on a narrow measure, with the whitespace doing the work. For the
   sections that are a statement rather than an explanation — three paragraphs
   at most, and never on a page that already uses it. */
.pb--centre{ display:block; text-align:center; }
.pb--centre .head h2{ max-width:16em; margin:12px auto 0; }
.pb--centre .head .label{ margin:0; }
.pb--centre .run{ max-width:60ch; margin:40px auto 0; }
.pb--centre .run p + p{ margin-top:24px; }

@media (max-width:1023px){
  .pb .col,.pb--aside .head,.pb--aside .col{ grid-column:1 / 9; }
  .pb--pull .pull{ grid-column:1 / 9; margin-top:32px; }
  .pb--brief .head,.pb--brief .intro,.pb--brief .media,.pb--brief .aside,
  .pb--column .head,.pb--column .intro,.pb--column .run,.pb--column .media{ grid-column:1 / 9; }
  .pb--brief .aside,.pb--column .media{ margin-top:32px; }
}
@media (max-width:767px){
  .pb{ grid-template-columns:1fr; }
  .pb--centre .head h2{ max-width:none; }
  .pb--centre .run{ margin-top:28px; }
  .pb .col,.pb--pull .pull,.pb--aside .head,.pb--aside .col,
  .pb--brief .head,.pb--brief .intro,.pb--brief .media,.pb--brief .aside,
  .pb--column .head,.pb--column .intro,.pb--column .run,.pb--column .media{ grid-column:auto; }
  .pb--pull .pull{ font-size:21px; padding-left:20px; }
  .pb--brief .intro .lead-para{ font-size:21px; }
  .pb-band .ph{ height:260px; }
}

/* 22 · Labelled Blocks — four content variants, three layouts -------- */
.lb{ display:flex; flex-direction:column; }
.lb .item{ padding:28px 0; border-top:1px solid var(--line); max-width:72ch; }
.lb .item:last-child{ border-bottom:1px solid var(--line); }
[data-family="dark"] .lb .item{ border-color:var(--line-dark); }
.lb .item p{ margin:0; }
.lb .item .lbl{ font-weight:700; color:var(--navy); }
[data-family="dark"] .lb .item .lbl{ color:var(--white); }
.lb .item .db-btn--tertiary{ margin-top:16px; }
.lb .closing,
.lb + .closing{ margin-top:32px; max-width:68ch; }

/* One icon per item, across every variant. Amber on a light ground, above the
   label, so the eye lands on the mark before the lead-in. */
.lb .item > .db-icon{ display:block; color:var(--amber); width:28px; height:28px; margin-bottom:16px; }
.lb .item > .db-icon svg{ width:28px; height:28px; }
[data-family="dark"] .lb .item > .db-icon{ color:var(--mist); }

/* Pair: exactly two, side by side, each with its own icon. */
.lb--pair{ display:grid; grid-template-columns:1fr 1fr; gap:var(--db-col-gap); margin-top:64px; }
.lb--pair .item{ border-top:1px solid var(--line); border-bottom:0; padding:32px 0 0; max-width:none; }
.lb--pair .item:last-child{ border-bottom:0; }
.lb--pair .item > .db-icon{ width:32px; height:32px; margin-bottom:24px; }
.lb--pair .item > .db-icon svg{ width:32px; height:32px; }
@media (max-width:767px){ .lb--pair{ grid-template-columns:1fr; gap:0; margin-top:40px; } .lb--pair .item{ padding:24px 0; } }

/* Pair, photographed: the icon's job given to a picture. The rule sits between
   the image and the text, not above the image, so the line separates the two
   halves of the item rather than fencing the item off from the heading. */
.lb--pair--photo .item{ border-top:0; padding:0; }
.lb--pair--photo .item .ph{ aspect-ratio:4/3; }
.lb--pair--photo .item .txt{ margin-top:32px; }
[data-family="dark"] .lb--pair--photo .item .txt{ border-top-color:var(--line-dark); }
.lb--pair--photo .item .txt p{ margin:0; }

/* Person: the label is a name, the body a role plus one line. */
.lb--person .item{ display:grid; grid-template-columns:96px 1fr; gap:var(--db-col-gap); max-width:none; align-items:start; }
.lb--person .item .ph--round{ width:96px; height:96px; padding:12px; font-size:10px; }
.lb--person .item .lbl{ font-family:var(--font-display); font-weight:600; font-size:21px; display:block; margin-bottom:4px; }
.lb--person .item .role{ display:block; font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase; color:var(--slate); margin-bottom:12px; }
@media (max-width:767px){ .lb--person .item{ grid-template-columns:1fr; gap:16px; } }

/* Accordion: the heading holds a left column, the run of items sits in the right
   one as a single-open accordion. This replaces the stacked and indexed variants
   — one long run of bold lead-in labels is a list to open, not a wall to read. */
.lb--acc{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap); align-items:start; }
.lb--acc > *{ min-width:0; }
.lb--acc .head{ grid-column:1 / 5; }
.lb--acc .list{ grid-column:6 / 13; }
.lb--acc details{ border-bottom:1px solid var(--line); }
.lb--acc details:first-of-type{ border-top:1px solid var(--line); }
[data-family="dark"] .lb--acc details{ border-color:var(--line-dark); }
.lb--acc summary{
  list-style:none; cursor:pointer; padding:24px 0;
  display:flex; align-items:center; justify-content:space-between; gap:24px;
  font-family:var(--font-display); font-weight:600; font-size:24px; line-height:1.25;
  letter-spacing:-0.01em; color:var(--amber);
  transition:color var(--motion-micro);
}
.lb--acc summary::-webkit-details-marker{ display:none; }
.lb--acc summary:hover{ color:var(--navy); }
[data-family="dark"] .lb--acc summary:hover{ color:var(--white); }
.lb--acc details[open] summary{ color:var(--navy); padding-bottom:12px; }
[data-family="dark"] .lb--acc details[open] summary{ color:var(--white); }
.lb--acc summary:focus-visible{ outline:3px solid var(--sky); outline-offset:2px; border-radius:var(--radius-sm); }
.lb--acc summary .db-icon{ flex:none; width:24px; height:24px; color:var(--slate); }
.lb--acc summary .db-icon svg{ width:24px; height:24px; }
.lb--acc details[open] summary .db-icon{ color:var(--amber); }
.lb--acc .panel{ padding:0 0 28px; max-width:64ch; }
.lb--acc .panel p + p{ margin-top:16px; }
.lb--acc .panel .db-btn--tertiary{ margin-top:16px; }
.lb--acc .closing{ grid-column:6 / 13; margin-top:32px; max-width:68ch; }
/* The head can carry a visual that answers whichever row is open. One frame, its
   caption swapped on toggle, so the picture is part of the reading rather than
   decoration parked beside it. */
.lb--acc .head .acc-media{ margin-top:40px; }
.lb--acc .head .acc-media .ph{ aspect-ratio:4/3; transition:opacity var(--motion-micro); }
.lb--acc .head .acc-media.is-swapping .ph{ opacity:0; }
@media (max-width:1023px){
  .lb--acc .head,.lb--acc .list,.lb--acc .closing{ grid-column:1 / 13; }
  .lb--acc .list{ margin-top:32px; }
}
@media (max-width:767px){
  .lb--acc{ grid-template-columns:1fr; }
  .lb--acc .head,.lb--acc .list,.lb--acc .closing{ grid-column:auto; }
  .lb--acc summary{ font-size:19px; padding:20px 0; }
}

/* Quartet: 2 x 2, for exactly four short items. Reads as a set rather than a
   list, and stops a four-item run eating a full screen of vertical space. */
.lb--quartet{ display:grid; grid-template-columns:1fr 1fr; gap:0 var(--db-col-gap); }
.lb--quartet .item{ max-width:none; border-bottom:0; }
.lb--quartet .item:last-child{ border-bottom:0; }
@media (max-width:767px){ .lb--quartet{ grid-template-columns:1fr; } }

/* 23 · Item List — a spine, an index per item, and the count as a figure ---- */
.il{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap); align-items:start; }
.il > *{ min-width:0; }
.il .il-side{ grid-column:1 / 4; position:sticky; top:120px; }
.il .il-side .count{ font:500 64px/1 var(--font-mono); color:var(--navy); font-variant-numeric:tabular-nums; }
.il .il-side .of{ display:block; margin-top:12px; font:500 12px/1.6 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase; color:var(--slate); }
.il .il-side .lede{ margin-top:24px; max-width:30ch; }
.il .il-body{ grid-column:5 / 13; }
.il ul{ list-style:none; margin:0; padding:0; display:grid; grid-template-columns:1fr 1fr; column-gap:var(--db-col-gap); }
.il li{
  display:grid; grid-template-columns:32px 1fr; gap:16px; align-items:start;
  padding:20px 0; border-top:1px solid var(--line);
}
.il li .no{ font:500 12px/1.7 var(--font-mono); letter-spacing:0.08em; color:var(--navy); }
.il li .db-icon{ display:block; width:24px; height:24px; color:var(--amber); margin-bottom:14px; }
.il li .db-icon svg{ width:24px; height:24px; }
.il li .lede-txt{ display:block; }
.il li b{ color:var(--navy); }
[data-family="dark"] .il li{ border-color:var(--line-dark); }
.il .closing{ grid-column:5 / 13; margin-top:32px; max-width:68ch; }
@media (max-width:1023px){
  .il .il-side{ grid-column:1 / 13; position:static; }
  .il .il-body,.il .closing{ grid-column:1 / 13; }
}
@media (max-width:767px){ .il ul{ grid-template-columns:1fr; } }

/* 24 · Note Band --------------------------------------------- */
.nb{
  border:1px solid var(--line); border-radius:var(--radius-card);
  background:var(--mist); padding:24px 28px; max-width:72ch;
  display:grid; grid-template-columns:auto 1fr; gap:16px; align-items:start;
}
.g-mist .nb{ background:var(--white); }
.nb .kind{
  font:500 12px/1.6 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
  color:var(--slate);
}
.nb p{ font-size:14px; line-height:1.6; color:var(--navy); margin:0; }
.nb .when{ display:block; margin-top:8px; font:500 12px/1 var(--font-mono); letter-spacing:0.08em; color:var(--slate); }
.nb--illustrative{ background:var(--amber-tint); border-color:var(--amber-line); }
.g-mist .nb--illustrative{ background:var(--amber-tint); }
.nb--illustrative .kind{ color:var(--navy); }
.nb--pending{ border-color:var(--error-border); background:var(--white); }
.nb--pending .kind{ color:var(--error-text); }
.nb--pending p{ color:var(--error-text); }
@media (max-width:767px){ .nb{ grid-template-columns:1fr; gap:8px; padding:20px; } }


/* 26 · Credential Block, expanded ---------------------------- */
.cred{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--db-col-gap); }
.cred > *{ min-width:0; }
.cred .list{ grid-column:1 / 8; }
.cred .item{ padding:28px 0; border-top:1px solid var(--line); }
.cred .item:last-child{ border-bottom:1px solid var(--line); }
.cred .item .name{ font-weight:700; }
.cred .item .num{ display:block; margin-top:8px; font:500 12px/1 var(--font-mono); letter-spacing:0.08em; color:var(--slate); }
.cred .warranties{ grid-column:9 / 13; }
.cred .warranties dl{ margin:16px 0 0; display:grid; grid-template-columns:1fr auto; gap:0; }
.cred .warranties dt,.cred .warranties dd{ padding:16px 0; border-top:1px solid var(--line); margin:0; font-size:17px; }
.cred .warranties dd{ text-align:right; font-variant-numeric:tabular-nums; color:var(--slate); }
@media (max-width:1023px){ .cred .list{ grid-column:1 / 13; } .cred .warranties{ grid-column:1 / 13; margin-top:32px; } }

/* ============================================================
   SCROLL REVEAL (§43) — the fade-up, defined but never used to hide anything.
   Nothing on this page is parked at opacity 0 waiting for an observer:
   a component set has to be legible in a screenshot and with JS off.
   Wire .db-reveal to an IntersectionObserver at build time.
   ============================================================ */
@media (prefers-reduced-motion:no-preference){
  .db-reveal.is-in{ animation:dbFadeUp 320ms cubic-bezier(0.16,1,0.3,1) both; }
  @keyframes dbFadeUp{ from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
}

/* ============================================================
   LIBRARY CHROME — not part of the site. Mono, Mist, hairline.
   ============================================================ */
.lib-top{
  background:var(--navy); color:var(--mist-text);
  padding-block:64px 48px;
}
.lib-top h1{ color:var(--white); font-size:56px; }
@media (max-width:767px){ .lib-top h1{ font-size:36px; } }
.lib-top .lead{ color:var(--mist-text); margin-top:24px; }
.lib-toc{ display:flex; flex-wrap:wrap; gap:8px 16px; margin-top:32px; list-style:none; padding:0; }
.lib-toc a{
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
  color:var(--mist); text-decoration:none; border:1px solid var(--line-dark);
  border-radius:var(--radius-pill); padding:8px 16px; display:inline-block;
  transition:border-color var(--motion-micro), background-color var(--motion-micro);
}
.lib-toc a:hover{ border-color:var(--mist); background:var(--line-dark); }
.lib-head{
  background:var(--mist); border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  padding-block:24px;
}
.lib-head .row{ display:flex; flex-wrap:wrap; align-items:baseline; gap:8px 24px; }
.lib-head .n{ font:500 12px/1 var(--font-mono); letter-spacing:0.08em; color:var(--navy); }
.lib-head .t{ font-family:var(--font-display); font-weight:700; font-size:21px; color:var(--navy); line-height:1.25; }
.lib-head .r{ font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase; color:var(--slate); margin-left:auto; }
.lib-note{ margin-top:8px; font-size:14px; line-height:1.5; color:var(--slate); max-width:68ch; }
.lib-note code{ font:400 13px/1 var(--font-mono); background:var(--white); border:1px solid var(--line); border-radius:var(--radius-sm); padding:2px 6px; }
.lib-open{ color:var(--error-text); font-weight:700; }
.lib-demo-rows{ display:flex; flex-direction:column; gap:48px; }
.lib-swatches{ display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:16px; }
.sw{ border:1px solid var(--line); border-radius:var(--radius-tile); overflow:hidden; background:var(--white); }
.sw .chipbox{ height:72px; }
.sw .meta{ padding:12px 16px 16px; display:flex; flex-direction:column; gap:4px; }
.sw .nm{ font:500 12px/1.2 var(--font-mono); letter-spacing:0.06em; text-transform:uppercase; color:var(--navy); }
.sw .hx{ font:400 12px/1.2 var(--font-mono); color:var(--slate); }
.sw .jb{ font-size:14px; line-height:1.4; color:var(--slate); }

/* mobile nav overlay, live */
#mobilePanel{
  position:fixed; inset:0; z-index:1000; background:var(--navy);
  display:flex; flex-direction:column; padding:24px;
  padding-top:calc(24px + env(safe-area-inset-top,0px));
  padding-bottom:calc(24px + env(safe-area-inset-bottom,0px));
  overflow-y:auto;
}
#mobilePanel .top{ display:flex; align-items:center; justify-content:space-between; }
#mobilePanel .closeb{
  width:48px; height:48px; display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--line-dark); border-radius:var(--radius-tile); background:none; color:var(--white); cursor:pointer;
}
#mobilePanel nav{ display:flex; flex-direction:column; margin-top:32px; }
#mobilePanel .m-cta{ display:flex; flex-direction:column; gap:16px; margin-top:auto; padding-top:48px; }
#mobilePanel .m-cta .db-btn{ width:100%; }

/* ============================================================
   NAVBAR v2 — logo lock-up, dropdowns, one CTA
   ============================================================ */
.db-logo img.lockup-mark{ height:44px; width:auto; display:block; }
.db-logo .wordblock{ display:flex; flex-direction:column; gap:2px; }
.db-logo .w1{
  font-family:var(--font-display); font-weight:700; font-size:21px; line-height:1;
  letter-spacing:-0.01em; color:var(--navy); white-space:nowrap;
}
.db-logo .w2{
  font:500 11px/1 var(--font-mono); letter-spacing:0.18em; text-transform:uppercase; color:var(--slate);
}
[data-family="dark"] .db-logo .w1{ color:var(--white); }
[data-family="dark"] .db-logo .w2{ color:var(--slate-on-dark); }
@media (max-width:1023px){ .db-logo img.lockup-mark{ height:36px; } .db-logo .w1{ font-size:19px; } }

.db-nav .links{ display:flex; align-items:center; gap:32px; margin-left:auto; }
.db-nav .links > a{ white-space:nowrap; }
.nav-item{ position:relative; }
.nav-trigger{
  display:inline-flex; align-items:center; gap:6px; white-space:nowrap; position:relative;
  font:700 17px/1 var(--font-body); color:var(--navy);
  background:none; border:0; padding:8px 0; cursor:pointer;
  transition:color var(--motion-micro);
}
.nav-trigger:hover{ color:var(--slate); }
.nav-trigger:focus-visible{ outline:3px solid var(--sky); outline-offset:4px; border-radius:var(--radius-sm); }
.nav-trigger .caret{ width:16px; height:16px; opacity:0.55; transition:opacity var(--motion-micro); }
.nav-item.is-open .nav-trigger{ color:var(--navy); }
.nav-item.is-open .nav-trigger .caret{ opacity:1; }
.nav-item.is-open > .nav-trigger::after,
.db-nav .links > a[aria-current="page"]::after{
  content:""; position:absolute; left:0; right:0; bottom:-2px; height:2px; background:var(--orange);
}

/* One panel geometry, used by the live navbar and by the pinned reference copy:
   24px padding, 8px between rows, a 24px icon column at 16px gap, 12/16 row
   padding, 1px Line, 14px radius, --shadow-soft, z-index 200. */
.nav-dd{
  position:absolute; top:calc(100% + 18px); left:-24px; z-index:200;
  background:var(--white); border:1px solid var(--line); border-radius:var(--radius-card);
  box-shadow:var(--shadow-soft);
  padding:8px; width:max-content; max-width:min(92vw,460px);
  display:none; grid-template-columns:1fr; gap:16px;
}
/* The panel's 8px of padding plus each row's 16px is the 24px inset. It is built
   this way, rather than 24px of panel padding with rows pulled back by a negative
   margin, because a negative margin inside a width:max-content box feeds back into
   the intrinsic width: the floating panel and the pinned copy then resolved to two
   different left edges from identical markup. No negative margins here. */
.nav-dd--2col{ max-width:min(94vw,820px); grid-template-columns:repeat(2,minmax(320px,1fr)); }
.nav-item.is-open > .nav-dd{ display:grid; animation:ddIn var(--motion-micro) both; }
@keyframes ddIn{ from{ opacity:0 } to{ opacity:1 } }
@media (prefers-reduced-motion:reduce){ .nav-item.is-open > .nav-dd{ animation:none; } }
.nav-dd .col{ min-width:0; }
.nav-dd .col h5{
  margin:0; padding:16px 16px 12px; font:500 12px/1 var(--font-mono); letter-spacing:0.08em;
  text-transform:uppercase; color:var(--slate);
}
.nav-dd ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:4px; }
.nav-dd ul a{
  display:grid; grid-template-columns:24px 1fr; gap:16px; align-items:start;
  padding:12px 16px; border-radius:var(--radius-tile);
  color:var(--navy); text-decoration:none;
  transition:background-color var(--motion-micro);
}
.nav-dd ul a:hover{ background:var(--mist); }
.nav-dd ul a .ic{ color:var(--amber); width:24px; height:24px; margin-top:2px; }
.nav-dd ul a .ic svg{ width:24px; height:24px; display:block; }
.nav-dd ul a:hover .ic{ color:var(--navy); }
.nav-dd ul a .t{ display:block; font:700 17px/1.3 var(--font-body); }
.nav-dd ul a .d{ display:block; font:400 14px/1.4 var(--font-body); color:var(--slate); margin-top:4px; }
.nav-dd ul a > span{ min-width:0; }
.nav-dd.is-pinned{ position:static; display:grid; animation:none; left:auto; top:auto; max-width:100%; }
/* Only the pinned reference copy needs this: it sits in a 6-column aside rather
   than floating over the page, so its two columns fold when the aside is narrow.
   The live panel is unaffected — it flips to the right edge instead. */
.nav-dd--2col.is-pinned{ grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); }

/* Mobile panel sub-nav */
#mobilePanel details{ border-bottom:1px solid var(--line-dark); }
#mobilePanel details summary{
  list-style:none; display:flex; align-items:center; justify-content:space-between;
  height:52px; cursor:pointer;
  font-family:var(--font-display); font-weight:600; font-size:21px; color:var(--white);
}
#mobilePanel details summary::-webkit-details-marker{ display:none; }
#mobilePanel details ul{ list-style:none; margin:0; padding:0 0 16px; display:flex; flex-direction:column; }
#mobilePanel details ul a{
  display:flex; align-items:center; min-height:48px;
  color:var(--mist-text); text-decoration:none; font-size:17px;
}
#mobilePanel .m-link{ border-bottom:1px solid var(--line-dark); }

/* ============================================================
   HERO v2 — full-bleed, media behind, text and buttons over it.
   AMENDS SPEC §Layout Exceptions: the exception list goes from one
   element to two, the hero and the photograph band. Both start their
   text on --db-inset, so every left edge on the page still aligns.
   ============================================================ */
.hero-full{
  position:relative; display:flex; align-items:center;
  min-height:clamp(560px, calc(100svh - 88px), 880px);
  overflow:hidden; isolation:isolate;
}
.hero-full .media{ position:absolute; inset:0; z-index:-2; }
.hero-full .media .ph,
.hero-full .media video,
.hero-full .media img{
  width:100%; height:100%; border-radius:0; border:0; object-fit:cover;
  align-items:flex-end; justify-content:flex-start;
}
.hero-full .scrim{ position:absolute; inset:0; z-index:-1; background:rgba(14,42,68,0.78); }
.hero-full .db-container{ width:100%; padding-block:64px; }
.hero-full .col{ max-width:calc(var(--db-content) * 0.58); }
@media (max-width:1023px){ .hero-full .col{ max-width:100%; } }
.hero-full h1{ color:var(--white); }
.hero-full .lead{ color:var(--mist-text); }
.hero-full .descriptor{ color:var(--slate-on-dark); }

.hero-scroll{
  position:absolute; left:var(--db-inset); bottom:32px; z-index:1;
  display:inline-flex; align-items:center; gap:10px;
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
  color:var(--slate-on-dark);
}
.hero-scroll svg{ width:16px; height:16px; }

/* ============================================================
   H2 HIGHLIGHT — Amber, one hex on all four grounds, and only on H1 and H2
   ============================================================ */
.hl{ color:var(--amber); }
.hl-demo{ display:grid; gap:0; }
.hl-demo > div{ padding:48px var(--db-gutter); }
@media (max-width:767px){ .hl-demo > div{ padding:32px var(--db-gutter); } }
/* Responsive nav rules live here, AFTER the v2 navbar block above. Declared any
   earlier they lose to `.db-nav .links{display:flex}` at equal specificity and the
   bar never collapses. */
@media (max-width:1599px){ .db-nav .links{ gap:24px; } }
/* Restoring the CTA's 28px side padding costs 20px at the narrow end of the full
   bar, so the link gap takes one step down on the scale below 1360. */
@media (max-width:1359px){ .db-nav .links{ gap:16px; } }
/* 1280 is the narrowest full bar, and six links plus the phone plus the CTA
   overflow it by 65px. Between 1280 and 1439 the phone Tertiary comes out of the
   bar: it is the item with the most other homes on the site (every hero, the
   mobile panel, the footer, the contact page), so it is the cheapest to drop. */
@media (max-width:1439px){ .db-nav .links .tel{ display:none; } }
@media (max-width:1279px){
  .db-nav .db-container.inner{ height:72px; }
  .db-nav .links{ display:none; }
  .hamburger{ display:inline-flex; }
}


/* ============================================================
   §54 INTERACTIVE STATES — the floor every interactive thing meets
   Audited 15 September 2026 against the eight-state list: default,
   hover, focus, active, disabled, error, loading, empty. Six
   components carried their own focus ring and the rest carried
   none, so the ring is now a floor with those six as overrides.
   Nothing here introduces a colour: every value is a token.
   ============================================================ */

/* FOCUS — one ring, every focusable thing, no exceptions.
   Inputs keep :focus rather than :focus-visible, because a text field
   that has been clicked into must show it. */
/* Solid Sky, not Sky at 60%. The ring was 60% everywhere in the previous draft,
   inherited from the button spec. Blended against its ground that is 1.9:1 on
   White and 2.4:1 on Navy, both under the 3:1 floor WCAG 1.4.11 sets for a focus
   indicator, so the ring was failing the test it exists to pass. Solid Sky
   measures 3.87 on White, 3.57 on Mist, 3.79 on Navy and 4.33 on Deep: the only
   value in the palette that clears 3:1 on all four grounds. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible{
  outline:3px solid var(--sky);
  outline-offset:3px;
  border-radius:var(--radius-sm);
}
/* The ring is the same 60% on both families: at 25% Sky is invisible on Navy,
   and at 60% it is still legible on White. One value, four grounds. */

/* ACTIVE — plain links, which had no pressed state at all. Buttons keep
   their own :active from §Buttons. */
.db-nav .links > a:not(.db-btn):active,
.nav-dd ul a:active,
.db-crumb a:active,
.area-list a:active{ color:var(--slate); }
.db-footer a:active,
.ft-social a:active{ color:var(--mist-text); }

/* DISABLED — beyond the button. Any control that is off is off the tab
   order's business end: it takes the same Mist/Slate pair, never a ghost. */
/* A disabled field keeps its ground and changes its border to dashed, which is
   already the file's mark for "there but not interactive" (.area-list .plain).
   Filling it Mist was the first attempt and it collided: on a White section an
   enabled field is Mist, so a Mist disabled field looked identical to a live one.
   §7a again, in a control rather than a card. */
.db-input:disabled,.db-select:disabled,.db-textarea:disabled,
.funnel-opt input:disabled + span{
  border-style:dashed; border-color:var(--line);
  color:var(--slate); cursor:not-allowed;
}
.db-input:disabled::placeholder,.db-textarea:disabled::placeholder{ color:var(--slate); }
a[aria-disabled="true"],.is-disabled-link{ color:var(--slate); pointer-events:none; text-decoration:none; }

/* ERROR — the field-level pair already existed. These three did not:
   the textarea, the funnel radio group, and the form-level summary. */
.db-field.is-error .db-textarea{ border-color:var(--error-border); }
.db-fieldset.is-error .funnel-opt span{ border-color:var(--error-border); }
.nb--error{ border-color:var(--error-border); background:var(--white); }
.g-mist .nb--error{ background:var(--white); }
.nb--error .kind{ color:var(--error-text); }
.nb--error ul{ margin:8px 0 0; padding-left:18px; }
.nb--error a{ color:var(--error-text); }

/* LOADING — nothing on the site had one. A submit with no busy state either
   double-fires or looks dead. The ring is the one rotation on the site and it
   is fenced to .is-loading, declared as a named exception in §42b. */
.is-loading{ pointer-events:none; cursor:progress; }
.db-btn.is-loading .stack{ opacity:0; }
.db-btn.is-loading::after{
  content:""; position:absolute; width:20px; height:20px;
  border:2px solid currentColor; border-top-color:transparent;
  border-radius:var(--radius-round);
  animation:dbBusy var(--motion-busy);
}
.db-btn.is-loading::before{ content:none; }        /* no hover panel while busy */
.db-form.is-loading{ opacity:0.72; }
@keyframes dbBusy{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce){
  .db-btn.is-loading::after{ animation:none; border-top-color:currentColor; opacity:0.5; }
}

/* EMPTY — the state this project actually needs, because there are no case
   studies, no attributable review and no counter basis yet. A slot with
   nothing in it says so, in the same voice as the rest of the site, rather
   than collapsing to zero height or shipping a placeholder that reads as
   content. Dashed border, because a solid one claims a card exists. */
.db-empty{
  border:1px dashed var(--line); border-radius:var(--radius-card);
  background:var(--mist); padding:32px;
  display:flex; flex-direction:column; align-items:flex-start; gap:12px;
}
.g-mist .db-empty{ background:var(--white); }
.db-empty .kind{
  font:500 12px/1 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase;
  color:var(--slate);
}
.db-empty p{ margin:0; font-size:17px; line-height:1.55; color:var(--navy); max-width:56ch; }
.db-empty .db-btn--tertiary{ margin-top:4px; }
[data-family="dark"] .db-empty{ background:transparent; border-color:var(--line-dark); }
[data-family="dark"] .db-empty p{ color:var(--mist-text); }
[data-family="dark"] .db-empty .kind{ color:var(--slate-on-dark); }
/* A table cell with no figure yet: same idea, one line. */
.db-table td.is-empty{ color:var(--slate); font-family:var(--font-mono); font-size:14px; }

/* The state gallery below is documentation, not a site component. */
.st-grid{ display:grid; grid-template-columns:140px 1fr; gap:24px var(--db-col-gap); align-items:center; }
.st-grid > .k{ font:500 12px/1.4 var(--font-mono); letter-spacing:0.08em; text-transform:uppercase; color:var(--slate); }
.st-row{ display:flex; flex-wrap:wrap; gap:16px; align-items:center; }
@media (max-width:767px){ .st-grid{ grid-template-columns:1fr; gap:8px; } }
