@charset "UTF-8";
/* WPK Notary — v3 SHARED LAYER.

   Loaded on every v3 page, after assets/css/v2/styles.css and before that page's own
   file. The split is the one assets/css/v2/ already uses: this holds what more than one
   page needs, the page file holds its own bands.

   It exists because the certification chain now appears twice - TAUGHT on the home page
   as four stages, DETAILED on the services page - and copying ninety lines of track CSS
   into a second file is exactly the Role-Before-Component failure this project spent a
   whole pass removing. One device, one definition, two levels of detail.

   Like the page files, this defines NO colour, NO radius, NO shadow and - since
   --v3-type-hero was retired on 2 September 2026 - NO type size of its own.
   Everything else resolves to a v2 token.

   Two thresholds only, 1024px and 768px. */

:root {
  /* --- band density -------------------------------------------------------
     The v2 page gave all seven bands clamp(48px, 7vw, 96px), so the whole page
     read at one pace. Three roles instead. Normal stays on .v2-band. */
  --v3-pad-tight: clamp(28px, 3.5vw, 44px);
  --v3-pad-airy: clamp(64px, 9vw, 128px);

  /* --- hero scale: RETIRED, and the reasoning is worth keeping ---------------
     --v3-type-hero was clamp(30px, 5.6vw, 84px) and reached ~84px at 1440, against
     the 52px the rest of the site tops out at. The argument was that v2 topped out
     at 4% of the viewport so nothing was ever actually big.

     The owner's read, 2 September 2026, was "too big and too thick, in your face" -
     and measurement agreed: at 1440 the headline ran FOUR lines at 80.6px/700 while
     every other v3 page's H1 was two lines at 52px/600. One page in six was shouting,
     which is exactly what made the home page read as the odd one out.

     The H1 now takes --type-display-page, the declared role its five siblings use, so
     the v3 layer invents no type size at all. Two lines instead of four, and the
     certification chain fits above the fold - which is the page's actual proof.

     THE 30px FLOOR was the one part the system protected, and it lives on inside
     --type-display-page: "และบริการทางกฎหมาย" at 32px measures ~290px against the
     284px a 320px screen leaves, and overflowed by 6px. Keep any replacement clamp
     floored at 30px. */

  /* The rail's marks column. Was 232px, which left the rule and the eyebrow floating
     in a half-empty gutter that read as an accident rather than a device. At 152px
     the marks sit tight to the reading column and behave like a margin note, which is
     what they are. */
  --v3-rail-col: 152px;

  /* The rail's own gutter. Named because the article page computes its container
     width from it - rail column + this + the 820px reading column - and a literal
     copy there would drift the moment either number moves. */
  --v3-rail-gap: clamp(24px, 3vw, 40px);

  /* Named because the chain rule's width is computed from it - see .v3-chaintrack. */
  --v3-chain-gap: clamp(20px, 3vw, 32px);

  /* The station mark. 48px is the icon-plate size the design system already defines;
     the chain reuses it rather than inventing a diagram-only dimension. */
  --v3-plate: 48px;

  /* --- the reading role -----------------------------------------------------
     DESIGN.md declares Reading as "400, 17px Sarabun, 1.75, article body and FAQ
     answers only" - a documented role that was never tokenised, so both pages that
     use it set the family and the size as literals. Declared here because the FAQ
     and the article page both need it and neither should own it.

     Sarabun is absent from tokens/fonts.css on purpose: it is requested per page in
     index.php via $v2_page_font, so the four pages that show no long-form reading
     never download it. The fallback matters - if that request is missing, this must
     degrade to the body face rather than to a system serif. */
  --font-reading: 'Sarabun', var(--font-body);
  --type-reading: 17px;
}

/* ------------------------------------------------------------------ the rail */

.v3-rail {
  display: grid;
  grid-template-columns: var(--v3-rail-col) minmax(0, 1fr);
  gap: var(--v3-rail-gap);
  align-items: start;
}

/* The marks sit on the reading column's first baseline rather than the band's top
   edge, so the rule reads as attached to the heading it introduces. */
.v3-rail__mark {
  padding-top: 6px;
}

.v3-rail__mark .v2-eyebrow {
  margin-top: 12px;
}

.v3-rail__mark .v2-badgepill {
  margin-top: 12px;
}

/* ------------------------------------------- 6. the certification chain track

   The page's signature. Four stages of one certification chain on a SINGLE unbroken
   rule, with the nodes sitting on the rule rather than the rule being cut between
   them. That is the argument made visually: PRODUCT.md's first positioning claim is
   the whole chain under one roof, and a segmented track would draw three handoffs.

   The device survives both breakpoints, which the rail does not: the rule runs
   horizontally across four columns on desktop and vertically down the left edge on a
   phone, and the nodes stay on it either way. */

.v3-chain__title {
  margin: 0;
}

.v3-chain__lead {
  margin: 18px 0 0;
  max-width: var(--measure-lead);
}

.v3-chaintrack {
  list-style: none;
  margin: clamp(40px, 5vw, 64px) 0 0;
  padding: 0;
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--v3-chain-gap);
}

/* THE unbroken rule - one element, not four borders, so the picture never draws a
   handoff between stages.

   It STOPS AT THE LAST NODE instead of running to the container edge. As a plain
   border-top it spanned the full width, leaving a bare gold segment past
   สถานทูตปลายทาง that reads as a fifth, unnamed stage - in a chain diagram that is not
   a cosmetic issue, it is a false claim about the process.

   The width is exact rather than eyeballed. With four equal columns and gap g in a
   track of width W, each column is (W - 3g)/4 and the last node sits at W minus one
   column, which is 0.75W + 0.75g. */
.v3-chaintrack::before {
  content: "";
  position: absolute;
  /* Half the plate, so the rule passes through the centre of every station. */
  top: calc(var(--v3-plate) / 2);
  left: 0;
  width: calc(75% + 0.75 * var(--v3-chain-gap));
  border-top: var(--rule-gold-on-dark);
}

.v3-station {
  position: relative;
}

/* THE STATION MARK.

   This replaced an 8px dot. The dot was the correct idea at the wrong weight: a 2px
   rule carrying four 8px dots under a 40px heading made the band's heading larger than
   the thing it introduced, and the track - the page's whole argument - read as a
   divider. Asked where the chain had gone, a reader could not find it.

   The plate is opaque and sits ON the rule, so the line passes BEHIND it. Same reason
   the rule is one element and not four borders: nothing in the picture may suggest the
   document is handed between separate parties.

   It also does a second job. Both critiques found that the four stages were bare Thai
   nouns to a first-timer who does not know นิติกรณ์; a stamp, a government building and
   a language mark are readable before the words are. */
.v3-station__plate {
  display: grid;
  place-items: center;
  position: relative;
  z-index: 1;
  width: var(--v3-plate);
  height: var(--v3-plate);
  border-radius: var(--radius-full);
  background: var(--surface-dark);
  border: 2px solid var(--accent-gold-on-dark);
  color: var(--accent-gold-on-dark);
}

/* Stages 2 and 3 are the same kind of step; what separates them is whether it happens
   at all. Dashed says conditional without a legend, and ใช้เมื่อปลายทางกำหนด is printed
   as the stage's first note so the picture is never the only place that fact lives. */
.v3-station--conditional .v3-station__plate {
  border-style: dashed;
}

/* .v3-station__step held the ขั้นที่ N label. Removed with the numbers: those belong to
   the three certification stages on the services page, and translation is not one of
   them, so on a track that shows all four they put "ขั้นที่ 1" on the second station.
   The rule and the reading order carry the sequence without them. */

.v3-station__name {
  display: block;
  /* The ขั้นที่ label used to supply this gap. With the label gone the name sat hard
     under the plate, so the spacing is now stated rather than inherited from a
     deleted element. */
  margin-top: clamp(14px, 1.6vw, 18px);
  font-size: var(--type-title);
  line-height: var(--lh-title);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--thai-tracking);
  color: var(--text-on-dark);
  text-wrap: pretty;
}

.v3-station__note {
  display: block;
  margin-top: 8px;
  font-size: var(--type-meta);
  line-height: var(--lh-label);
  letter-spacing: var(--thai-tracking);
  color: var(--text-on-dark-soft);
  text-wrap: pretty;
}

/* The rule is navy, not gold: the band already spends its one gold rule above the
   heading, and three more would make gold the loudest thing on a quiet page. */
/* .v3-step, .v3-step__num and .v3-step__title were deleted with the client-process
   band. The chain track above replaced it. */
/* ------------------------------------------------------------------ links */

/* A text link that carries a button's job. Used where a second pill would make the
   reader choose between two equal-looking actions before reading anything. */
.v3-textlink {
  /* Works on <a> AND on <button>. It was written for anchors only, so the two buttons
     on the FAQ that carry this class rendered with the browser's own chrome: measured
     `border: 2px outset` and a #efefef background, on a control meant to read as a
     text link. A shared component has to survive both elements it is used on. */
  appearance: none;
  border: 0;
  background: transparent;
  padding: 0;
  font-family: var(--font-body);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  min-height: var(--control-height);
  font-size: var(--type-base);
  font-weight: var(--weight-semibold);
  line-height: var(--lh-label);
  letter-spacing: var(--thai-tracking);
  color: var(--text-link);
  text-decoration: underline;
  text-underline-offset: 4px;
  transition: color var(--motion-base) var(--motion-ease);
}

.v3-textlink:hover {
  color: var(--color-primary-active);
}

.v3-textlink--on-dark {
  color: var(--text-on-dark);
}

.v3-textlink--on-dark:hover {
  color: var(--text-on-dark);
  text-decoration-color: var(--accent-gold-on-dark);
}


/* ------------------------------------------------ the empty state, gold wash

   PROMOTED OUT OF faq.css with the rail and the search field: a filtered index needs a
   way to say "nothing matched", and there are now two of them.

   IT TAKES THE GOLD WASH ON PURPOSE, and it is the only thing on either page that does.
   The home page spends its wash on the registration number and the services page on the
   NDA; here it marks the one moment where the answer is not on the page and the reader
   is handed to LINE. A wash added anywhere else for symmetry would be the template
   thinking this direction exists to avoid. */
.v3-empty {
  margin-top: clamp(28px, 3.5vw, 40px);
  padding: clamp(24px, 3.5vw, 36px);
  border: var(--border-gold);
  border-radius: var(--radius-card);
  background: var(--surface-gold-wash);
  text-align: center;
}

.v3-empty__title {
  margin-top: 14px;
  font-size: var(--type-subtitle);
  line-height: var(--lh-title);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--thai-tracking);
  color: var(--text-ink);
}

.v3-empty__body {
  margin: 8px auto 0;
  max-width: var(--measure-copy);
}

.v3-empty__actions {
  margin-top: clamp(18px, 2.2vw, 24px);
  justify-content: center;
}

/* ------------------------------------------------ the search field, on navy

   PROMOTED OUT OF faq.css alongside the filter rail, and for the same reason: the FAQ
   searches seventeen questions in the browser and the article list searches 113 rows on
   the server, but the field is one component and it sits in the same place on both -
   the hero, because on an index the search IS the main way in, not a secondary control.

   It steps UP to --surface-dark-elevated rather than being a white box punched into the
   band. --input-height is the declared 52px control.

   __clear is optional. The FAQ shows it because its filtering is live and there is
   nothing else to undo a query with; the article list clears through its own
   "ล้างตัวกรอง" link, which is an ordinary URL and works with JavaScript off. */
.v3-search {
  display: flex;
  align-items: center;
  gap: 12px;
  /* A <form> on the article list, a <div> on the FAQ. Neither may inherit a UA margin. */
  margin: clamp(24px, 3vw, 32px) 0 0;
  padding: 0 16px;
  height: var(--input-height);
  max-width: var(--measure-lead);
  border: var(--border-on-dark);
  border-radius: var(--radius-input);
  background: var(--surface-dark-elevated);
  transition: border-color var(--motion-base) var(--motion-ease);
}

/* The field is focused by typing into the input, so the ring belongs on the wrapper -
   otherwise the visible box and the focused element are different objects. */
.v3-search:focus-within {
  border-color: var(--accent-gold-on-dark);
}

.v3-search__icon {
  display: flex;
  flex: none;
  color: var(--text-on-dark-soft);
}

.v3-search__input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  font-family: var(--font-body);
  /* 16px, not smaller: iOS Safari zooms the whole page on focus below 16px, and this
     field is the first thing a phone reader touches. */
  font-size: var(--type-base);
  line-height: var(--lh-label);
  letter-spacing: var(--thai-tracking);
  color: var(--text-on-dark);
}

.v3-search__input::placeholder {
  color: var(--text-on-dark-soft);
}

.v3-search__input:focus {
  outline: none;
}

/* Chrome draws its own clear button on type=search and it is invisible on navy. */
.v3-search__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.v3-search__clear {
  flex: none;
  min-height: var(--control-height);
  padding: 0 4px;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: var(--type-meta);
  color: var(--text-on-dark-soft);
  cursor: pointer;
  transition: color var(--motion-base) var(--motion-ease);
}

.v3-search__clear:hover {
  color: var(--text-on-dark);
}

/* ------------------------------------------------------- the filter rail

   PROMOTED OUT OF faq.css. Two pages now put a filtered index beside a rail - the FAQ
   filters seventeen questions by category, the article list filters 113 articles by
   topic - and copying forty lines of row CSS into a second file is the
   Role-Before-Component failure this project spent a pass removing.

   IT MUST WORK ON <button> AND ON <a>. The FAQ's filters are buttons because it
   filters in the browser; the article list's are links because it filters on the
   server, in the URL, with no JavaScript. Same role, two elements - exactly the trap
   .v3-textlink fell into, where an anchors-only rule left two buttons rendering with
   the browser's own 2px outset border. */

.v3-filterrail__head {
  margin-top: 12px;
  margin-bottom: 14px;
}

/* A row, not a pill. The pill is the site's mark of "this is a control you press to go
   somewhere"; these are filters over the list beside them, and a stack of hairline rows
   reads as a table of contents, which is what it is. */
.v3-filter {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: var(--control-height);
  padding: 0 2px;
  border: 0;
  border-bottom: var(--border-hairline);
  /* The four an <a> or a <button> needs to stop being one: no UA chrome, no underline,
     the page's own face rather than the control default. */
  appearance: none;
  background: transparent;
  text-decoration: none;
  font-family: var(--font-body);
  font-size: var(--type-base);
  line-height: var(--lh-label);
  letter-spacing: var(--thai-tracking);
  color: var(--text-body);
  text-align: left;
  cursor: pointer;
  transition: color var(--motion-base) var(--motion-ease);
}

.v3-filter:hover {
  color: var(--color-primary);
  text-decoration: none;
}

/* The selected filter is marked by weight and a gold rule, not by a navy fill. A filled
   row in a narrow column reads as a button that navigates; this one changes what is
   beside it. */
.v3-filter--on {
  font-weight: var(--weight-semibold);
  color: var(--text-ink);
  border-bottom: var(--rule-gold);
}

/* Mono, tabular, so the counts form a column that lines up rather than four numbers
   drifting against four different Thai label widths. Digits only. */
.v3-filter__count {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--type-micro);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.v3-filter--on .v3-filter__count {
  color: var(--accent-gold);
}

.v3-filterrail__foot {
  margin-top: clamp(24px, 3vw, 32px);
  padding-top: clamp(16px, 2vw, 20px);
  border-top: var(--border-hairline);
}

.v3-filterrail__foot .v2-note {
  max-width: none;
  margin-bottom: 8px;
}

/* ================================================================ 1024px */

@media (max-width: 1023px) {
  /* The rail folds. Its marks column becomes a row above the reading column, which
     keeps the rule-then-eyebrow-then-heading order a screen reader already hears. */
  .v3-rail {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(16px, 2.5vw, 24px);
  }

  .v3-rail__mark {
    padding-top: 0;
  }

  /* .v3-rail folds to one column at this width in app.css, so the category rail
     becomes a row above the list. A vertical stack of five full-width filter rows would
     push the first question off the screen, so they go horizontal and scroll. */
  .v3-filterrail {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    min-width: 0;
    max-width: 100%;
    padding-bottom: 4px;
  }

  /* The rule, the eyebrow and the LINE note are the rail's vertical furniture; in a
     scrolling row they would be three more things to swipe past. */
  .v3-filterrail .v2-rule,
  .v3-filterrail__head,
  .v3-filterrail__foot {
    display: none;
  }

  /* Back to a pill in this orientation: a bottom border on a horizontal item reads as
     an underline, not as a row in a list. */
  .v3-filter {
    width: auto;
    flex: none;
    padding: 0 16px;
    border: var(--border-hairline);
    border-radius: var(--radius-pill);
  }

  .v3-filter--on {
    border: 1px solid transparent;
    background: var(--color-primary);
    color: var(--text-on-primary);
  }

  .v3-filter--on .v3-filter__count {
    color: var(--text-on-dark-soft);
  }

  .v3-empty__actions {
    justify-content: stretch;
  }

  /* Four stages will not hold at this width; two rows of two keep the rule reading as
     one line per row rather than becoming a vertical track too early. */
  .v3-chaintrack {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: clamp(28px, 4vw, 40px);
  }

  /* Two columns per row now, so the last node of row 1 sits at 50% + half a gap. The
     rule marks the first row only; the second row's stages hang off the nodes. */
  .v3-chaintrack::before {
    width: calc(50% + 0.5 * var(--v3-chain-gap));
  }
}

/* ================================================================= 768px */

@media (max-width: 767px) {
  /* The track turns vertical. The device is not dropped at the width most of this
     audience reads on - it rotates, and the plates stay threaded on the rule. This is
     the answer to the rail's failure: the rail disappears below 1024px, the track
     does not.

     The rule becomes an absolute line at the plate's centre rather than a border on
     the list, so it threads through the plates exactly as it does horizontally. */
  .v3-chaintrack {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    padding-left: 0;
  }

  .v3-chaintrack::before {
    top: calc(var(--v3-plate) / 2);
    bottom: calc(var(--v3-plate) / 2);
    left: calc(var(--v3-plate) / 2 - 1px);
    width: 0;
    height: auto;
    border-top: 0;
    border-left: var(--rule-gold-on-dark);
  }

  /* Plate in column one, the words beside it, so the track reads as a route down the
     page rather than as four headings with decoration. */
  .v3-station {
    display: grid;
    grid-template-columns: var(--v3-plate) minmax(0, 1fr);
    column-gap: 16px;
    align-items: start;
    padding-bottom: clamp(26px, 5vw, 34px);
  }

  .v3-station:last-child {
    padding-bottom: 0;
  }

  .v3-station__plate {
    grid-row: 1 / span 4;
  }

  /* With no step label above it, the name is the first thing beside the plate and
     centres against it. */
  .v3-station__name {
    margin-top: 0;
    align-self: center;
  }

  /* Unless the stage carries notes, in which case the block starts at the plate's top
     and runs down past it. */
  .v3-station:has(.v3-station__note) .v3-station__name {
    align-self: start;
  }
}

/* ============================================================ on navy ground */

.v2-band--dark .v3-textlink,
.v2-band--photo .v3-textlink {
  color: var(--text-on-dark);
}

.v2-band--dark .v3-textlink:hover,
.v2-band--photo .v3-textlink:hover {
  color: var(--text-on-dark);
  text-decoration-color: var(--accent-gold-on-dark);
}

/* ---------------------------------------------- the schedule (rows, not cards)
   Used by the home page for the three services and by the services page for its
   section index. Same role both times: facets of one practice, listed. */

/* -------------------------------------------------- 4. services as a schedule */

.v3-band--airy {
  padding-top: var(--v3-pad-airy);
  padding-bottom: var(--v3-pad-airy);
}

.v3-sched__title {
  margin: 0;
  max-width: var(--measure-read);
}

.v3-sched__lead {
  margin: 18px 0 0;
  max-width: var(--measure-lead);
}

.v3-sched__list {
  margin-top: clamp(32px, 4vw, 48px);
  border-top: var(--border-hairline);
}

/* A row, not a card. Grey hairline between rows because this is a divider inside a
   list, not a card's own edge - the Border Rule. No shadow, no radius, no fill: what
   marks it as interactive is the hover ground and the arrow, and it is an <a>. */
.v3-schedrow {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(16px, 2.5vw, 32px);
  align-items: baseline;
  padding: clamp(20px, 2.5vw, 28px) clamp(8px, 1.5vw, 16px);
  border-bottom: var(--border-hairline);
  text-decoration: none;
  transition: background var(--motion-base) var(--motion-ease);
}

.v3-schedrow:hover {
  background: var(--surface-soft);
  text-decoration: none;
}

.v3-schedrow__idx {
  font-family: var(--font-mono);
  font-size: var(--type-subhead);
  line-height: var(--lh-subhead);
  font-variant-numeric: tabular-nums;
  color: var(--accent-gold);
}

/* ------------------------------------------------ an article's thumbnail frame

   NOT NAMED AFTER THE ROW, because it is no longer only a row's mark. Three consumers
   now: the article index uses it at the default width in .v3-schedrow's mark column,
   the article page's related block stretches it to a full 290px column, and both want
   the same frame - 16/9, hairline, the strong surface underneath, the picture cropped
   to fill. The width is the only thing a consumer overrides.

   align-self: start is load-bearing INSIDE A ROW. .v3-schedrow is align-items: baseline
   and a block with overflow:hidden reports its bottom margin edge as its baseline, so
   the figure hung below the text it belonged to instead of topping out with it.

   THE FRAME IS DRAWN EVEN WITH NO PICTURE (see --empty). An absent image must not shift
   the text column left on one row out of twelve, or collapse one of three columns to a
   different height. */
.v3-thumb {
  display: block;
  align-self: start;
  flex: none;
  width: clamp(96px, 13vw, 160px);
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--radius-md);
  border: var(--border-hairline);
  background: var(--surface-strong);
}

.v3-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.v3-thumb--empty {
  display: grid;
  place-items: center;
  color: var(--text-muted);
}

.v3-schedrow__main {
  display: block;
}

.v3-schedrow__title {
  display: block;
  /* It is a <span> on the home and services pages and an <h2> on the article index -
     a list of articles is a list of headings. Without this the UA heading margin
     pushes the row's own baseline grid apart. */
  margin: 0;
  font-size: var(--type-subhead);
  line-height: var(--lh-subhead);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--thai-tracking);
  color: var(--text-ink);
  text-wrap: balance;
}

.v3-schedrow__detail {
  display: block;
  margin-top: 8px;
  font-size: var(--type-base);
  line-height: var(--lh-read);
  letter-spacing: var(--thai-tracking);
  color: var(--text-muted);
  max-width: var(--measure-read);
}

.v3-schedrow__go {
  align-self: center;
  display: flex;
  color: var(--color-primary);
}


@media (max-width: 767px) {
  .v3-schedrow {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
  }

  /* The arrow STAYS. It was `display: none` here with a comment claiming it "moves
     under the title" - it did not move, it was deleted, which left three tappable
     rows with no affordance at all on the width where most of this audience reads.
     20px in a 296px column costs nothing. */
  .v3-schedrow__go {
    align-self: start;
    padding-top: 4px;
  }
}

/* --- the schedule, on navy --- */

.v2-band--dark .v3-sched__list ,
.v2-band--photo .v3-sched__list {
  border-top: var(--border-on-dark);
}

.v2-band--dark .v3-schedrow ,
.v2-band--photo .v3-schedrow {
  border-bottom: var(--border-on-dark);
}

/* Hover was --surface-soft, which is a light grey and would flash white on navy.
   The elevated navy step is the on-dark equivalent. */
.v2-band--dark .v3-schedrow:hover ,
.v2-band--photo .v3-schedrow:hover {
  background: var(--surface-dark-elevated);
}

.v2-band--dark .v3-schedrow__idx ,
.v2-band--photo .v3-schedrow__idx {
  color: var(--accent-gold-on-dark);
}

.v2-band--dark .v3-schedrow__title ,
.v2-band--photo .v3-schedrow__title {
  color: var(--text-on-dark);
}

.v2-band--dark .v3-schedrow__detail ,
.v2-band--photo .v3-schedrow__detail {
  color: var(--text-on-dark-soft);
}

.v2-band--dark .v3-schedrow__go ,
.v2-band--photo .v3-schedrow__go {
  color: var(--text-on-dark);
}


/* --------------------------------------------------- text on a navy ground

   THIS BELONGS IN THE SHARED LAYER, and it was in home.css only. The services page's
   certification band is navy and its lead paragraph carries .v2-body, so without this
   the copy rendered --text-body (#454e5c) on --surface-dark (#032141): measured
   1.92:1, against a 4.5 floor, at every width. An incomplete extraction, not a design
   decision - the rule is not home-specific and never was.

   --wash-navy is navy at 7%; on navy it is invisible, so the plate inverts to a white
   wash carrying a champagne glyph. */

/* --photo IS A DARK GROUND and the selector has to say so.
   
   This read `.v2-band--dark` only. A photograph band carries no --dark class - it is
   .v2-band--photo, and the JPEG is pre-duotoned to --surface-dark - so body copy inside
   one fell through to --text-body (#454e5c) on navy. Measured on the FAQ's closing CTA:
   1.92:1 against a 4.5 floor, at every width.
   
   The home and services pages escaped it by accident, not by design: both set
   `color: var(--text-on-dark-soft)` directly on their own CTA lead, so the missing
   override never showed. That is two pages carrying a workaround for a selector bug and
   a third page finding the bug. Fixed once, here, for every dark ground. */
.v2-band--dark .v2-body,
.v2-band--dark .v2-note,
.v2-band--photo .v2-body,
.v2-band--photo .v2-note {
  color: var(--text-on-dark-soft);
}

.v2-band--dark .v2-iconplate,
.v2-band--photo .v2-iconplate {
  background: rgba(255, 255, 255, 0.08);
  color: var(--accent-gold-on-dark);
}
