/* ==========================================================================
   MAIN  —  D&J GROUP LLC  ·  NAIL SALON TEMPLATE 05  ·  "ONYX & GOLD"
   --------------------------------------------------------------------------
   Layout and components. THIS FILE CONTAINS NO COLOUR VALUES — every colour,
   font, size and duration comes from a custom property in tokens.css. If you
   find yourself typing a "#" in here, the value belongs in tokens.css.

   The design in one paragraph: an obsidian page, everything centred, one
   antique brass. Gold is used the way a printer uses foil — a hairline, an
   eyebrow, a price — and never as a fill behind copy. Nothing is rounded.
   Nothing casts a shadow; depth comes from black-on-black. The home page is
   six full-height chapters that scroll-snap; every other page is ordinary
   flow, because a scroll-snapped price list is a hostile price list.

   Section map
     01 reset + base            08 hero
     02 focus + skip link       09 photographs
     03 layout helpers          10 the carte  (service list)
     04 typography              11 the plates (pricing)
     05 rules + dividers        12 the stage  (one-at-a-time lookbook)
     06 the foil (D&J mark)     13 voices, ledger, facts, forms
     07 header + navigation     14 footer, call bar, reveal, print
   ========================================================================== */


/* ═══════════════════════════════════════════════ 01 · RESET + BASE ═════ */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--head-h);
  /* Tells the browser to render its own furniture dark: the date picker, the
     <select> popup, the scrollbar. Without it a native calendar opens as a
     white rectangle in the middle of an obsidian page. */
  color-scheme: dark;
}

/* The home page, and only the home page, snaps. `proximity` rather than
   `mandatory` on purpose: mandatory hijacks a deliberate small scroll and
   makes long chapters unreadable on a short screen. */
html.snap { scroll-snap-type: y proximity; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  html.snap { scroll-snap-type: none; }
}

body {
  margin: 0;
  background: var(--c-canvas);
  color: var(--c-ink);
  font-family: var(--font-display);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; border: 0; }

a { color: inherit; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
}
button { cursor: pointer; }

h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

hr { border: 0; }

::selection {
  background: var(--c-brass);
  color: var(--c-on-brass);
}


/* ══════════════════════════════════════════ 02 · FOCUS + SKIP LINK ═════ */

/* One focus treatment for the whole site: a champagne hairline box, offset so
   it never sits on top of the thing it is marking. Visible on a black page at
   13.4:1, which is the point. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 1px solid var(--c-edge-lit);
  outline-offset: 4px;
}

.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -120%);
  z-index: 200;
  padding: .85rem 1.6rem;
  background: var(--c-surface);
  border: 1px solid var(--c-edge);
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ══════════════════════════════════════════════ 03 · LAYOUT HELPERS ════ */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--mid    { max-width: var(--wrap-mid); }
.wrap--narrow { max-width: var(--wrap-narrow); }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: calc(var(--section-y) * .6); }

/* Everything in this design is centred. This is not a utility that gets used
   occasionally — it is the layout. */
.centre { text-align: center; }

.stack > * + * { margin-top: var(--gap, 1.4rem); }

/* Telephone numbers and addresses break in ugly places — "(571) 527-" on one
   line and "8120." on the next. This is for those. */
.nowrap { white-space: nowrap; }

/* Vertical rhythm. Four steps, and four is all there is — every gap on the
   site is one of these, which is most of why the pages feel measured. */
.gap-s  { margin-top: 1.35rem; }
.gap-m  { margin-top: 2.25rem; }
.gap-l  { margin-top: 3rem; }
.gap-xl { margin-top: 4rem; }

/* A column that holds text at a comfortable measure, centred in its parent.
   Cormorant at 19px runs about 68 characters at this width. */
.measure {
  max-width: 38rem;
  margin-inline: auto;
}


/* ═════════════════════════════════════════════════ 04 · TYPOGRAPHY ═════ */

/* --- the eyebrow ------------------------------------------------------
   Montserrat 500, uppercase, tracked to .22em. It appears above every
   heading on the site and is the only place brass is allowed to be small. */
.label {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: var(--lh-ui);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-brass);
}
.label--mute { color: var(--c-mute); }
.label--ink  { color: var(--c-ink-soft); }

/* --- display + headings ---------------------------------------------- */
.display,
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 300;
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-display);
  color: var(--c-ink);
}

.display {
  font-size: var(--fs-wordmark);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-wordmark);
  text-transform: uppercase;
}

h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); font-weight: 400; }

/* Cormorant's italic is the reason this typeface was chosen. It carries the
   accent in headings, in the carte and in every pull quote. */
.ital { font-style: italic; font-weight: 300; }

.lede {
  font-size: var(--fs-lede);
  line-height: 1.65;
  color: var(--c-ink-soft);
}

p { margin: 0; }
p + p { margin-top: 1.15em; }

.fine {
  font-family: var(--font-ui);
  font-size: var(--fs-fine);
  line-height: 1.7;
  color: var(--c-mute);
  letter-spacing: 0;
}

.meta {
  font-family: var(--font-ui);
  font-size: var(--fs-meta);
  font-weight: 500;
  line-height: var(--lh-ui);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--c-mute);
}
.meta--brass { color: var(--c-brass); }

/* Prose links: a brass underline that lifts to champagne. No colour change on
   the text itself, so a paragraph does not turn into a row of gold words.

   text-decoration rather than border-bottom, deliberately. A link that wraps
   onto two lines — every street address on this site does — gets one rule per
   line from text-decoration and one rule the width of its whole box from a
   border, which on a centred layout looks like a mistake. */
.prose a,
a.link {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: .3em;
  transition: text-decoration-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.prose a:hover,
a.link:hover {
  color: var(--c-champagne);
  text-decoration-color: var(--c-champagne);
}


/* ══════════════════════════════════════════ 05 · RULES + DIVIDERS ══════ */

/* THE RULE. A short brass hairline, centred, that draws itself left to right
   when its chapter comes into view. It is the only decoration in the design,
   so it earns its animation. */
.rule {
  display: block;
  width: 68px;
  height: 1px;
  margin-inline: auto;
  background: var(--c-brass);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1s var(--ease-out) .1s;
}
.rule--wide  { width: 120px; }
.rule--full  { width: 100%; }
.rule--foil  { background: var(--foil); }

.is-in .rule,
.rule.is-in { transform: scaleX(1); }

/* THE DOUBLE RULE. Two hairlines four pixels apart — the section divider,
   borrowed from a letterpress title page. Built from a border plus ::after so
   it stays one element in the markup. */
.dbl {
  position: relative;
  border-top: 1px solid var(--c-rule);
  height: var(--rule-gap);
}
.dbl::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  bottom: 0;
  height: 1px;
  background: var(--c-rule);
}

/* The same device wrapped around a block, for the pricing plates. */
.dbl-box {
  border: 1px solid var(--c-rule);
  padding: clamp(1.75rem, 3vw, 2.75rem);
  position: relative;
}
.dbl-box::before {
  content: "";
  position: absolute;
  inset: var(--rule-gap);
  border: 1px solid var(--c-rule);
  pointer-events: none;
}

/* A numeral, foil-stamped. Used for the chapter marks and the carte. */
.numeral {
  display: inline-block;
  font-family: var(--font-ui);
  font-size: var(--fs-numeral);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  background: var(--foil);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}
/* If background-clip:text is unavailable the text would vanish. Paint it
   brass first and only go transparent where the clip is supported. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .numeral { background: none; color: var(--c-brass); }
}


/* ═══════════════════════════════════════ 06 · THE FOIL (D&J MARK) ══════ */

/* The D&J logo is gold-stamped on this site: the brass gradient painted on a
   box and clipped to the shape of the mark.

   The <img> inside is the fallback. logo-mask.png is WHITE artwork on
   transparent, so a browser without mask-image support shows a clean white
   mark rather than a gold rectangle or nothing at all. Where masking works,
   the image is hidden and ::after paints the foil in its place. */
.foil {
  position: relative;
  display: inline-block;
  width: var(--foil-w, 78px);
  line-height: 0;
}
.foil img { width: 100%; height: auto; }

@supports ((-webkit-mask-image: url("")) or (mask-image: url(""))) {
  .foil img { visibility: hidden; }
  .foil::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--foil);
    -webkit-mask: var(--mark-mask) center / contain no-repeat;
            mask: var(--mark-mask) center / contain no-repeat;
  }
}

/* The footer treatment: the mark inside a 1px brass keyline plate. */
.foil-plate {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 1.35rem 1.75rem;
  border: 1px solid var(--c-rule);
  transition: border-color var(--dur-fast) var(--ease);
}
a:hover > .foil-plate,
.foil-plate:hover { border-color: var(--c-brass); }


/* ═══════════════════════════════════════════════════ 07 · BUTTONS ═════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  padding: 1rem 2.15rem;
  border: 1px solid var(--c-edge);
  border-radius: var(--r);
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--c-ink);
  background: transparent;
  transition: color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease);
}
.btn:hover {
  color: var(--c-champagne);
  border-color: var(--c-champagne);
}

/* The one filled control on the site. Obsidian type on brass measures 6.4:1,
   so it is a real button, not a decoration. */
.btn--brass {
  background: var(--c-brass);
  border-color: var(--c-brass);
  color: var(--c-on-brass);
}
.btn--brass:hover {
  background: var(--c-champagne);
  border-color: var(--c-champagne);
  color: var(--c-on-brass);
}

.btn--sm { padding: .7rem 1.3rem; font-size: var(--fs-numeral); }
.btn--lg { padding: 1.15rem 2.6rem; }

/* A text button: no box at all, just tracked caps over a brass hairline. */
.btn--bare {
  padding: .35rem 0;
  border: 0;
  border-bottom: 1px solid var(--c-rule);
  color: var(--c-brass);
}
.btn--bare:hover { border-bottom-color: var(--c-champagne); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: center;
}


/* ═══════════════════════════════════ 08 · HEADER + NAVIGATION ═════════ */

.head {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  height: var(--head-h);
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              backdrop-filter var(--dur-fast) var(--ease);
}

/* Over the hero the bar is invisible; the moment it lifts off, it becomes a
   slim pane of smoked glass with a brass hairline under it. */
.head.is-stuck,
.head.is-solid {
  background: var(--glass);
  border-bottom-color: var(--c-rule);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
}
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .head.is-stuck, .head.is-solid { background: var(--c-canvas); }
}

.head__in {
  height: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  /* minmax(0, 1fr), not 1fr. A plain 1fr track has an `auto` minimum, so the
     wider of the two navs pushes its column past its share and the wordmark
     drifts off centre — which, on a design whose entire premise is symmetry,
     is the one bug that is actually fatal. Zero minimum keeps the side
     columns exactly equal and the wordmark exactly in the middle. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 1.5rem;
}

/* On a wide screen the panel is not a box at all — `display: contents` lets
   the two navs sit directly in the header grid, so the wordmark can be dead
   centre with three items either side. On a narrow screen the same element
   becomes the drop-down panel. One wrapper, two completely different jobs. */
.head__panel { display: contents; }

/* Three links left, three right, the wordmark dead centre. */
.head__nav {
  display: flex;
  align-items: center;
  gap: clamp(1.1rem, 2.2vw, 2.1rem);
}
/* Explicit placement, because `display: contents` hands the grid three items
   in the order toggle / wordmark / navs — which is the right tab order and
   the wrong visual one. */
.head__nav--l { grid-column: 1; grid-row: 1; justify-content: flex-start; }
.head__nav--r { grid-column: 3; grid-row: 1; justify-content: flex-end; }
.wordmark     { grid-column: 2; grid-row: 1; }

.navlink {
  position: relative;
  padding-block: .5rem;
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  color: var(--c-ink-soft);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease);
}
.navlink:hover { color: var(--c-champagne); }

/* The current page is marked with a brass hairline under it, not a colour
   change — colour is reserved for hover so the two never read as the same. */
.navlink::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  bottom: 0;
  height: 1px;
  background: var(--c-brass);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-fast) var(--ease);
}
.navlink[aria-current="page"]::after { transform: scaleX(1); }

.head__phone {
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-meta);
  text-decoration: none;
  color: var(--c-brass);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease);
}
.head__phone:hover { color: var(--c-champagne); }

/* --- the wordmark ----------------------------------------------------- */
.wordmark {
  display: block;
  text-align: center;
  text-decoration: none;
  line-height: 1;
}
.wordmark__name {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.9vw, 1.5rem);
  font-weight: 400;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--c-ink);
  transition: color var(--dur-fast) var(--ease);
}
.wordmark__sub {
  display: block;
  margin-top: .35rem;
  font-family: var(--font-ui);
  font-size: .5625rem;
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-brass);
}
.wordmark:hover .wordmark__name { color: var(--c-champagne); }

/* --- live open / closed pill ------------------------------------------
   Hidden until main.js has a real answer, so it never flashes a guess. */
.status {
  display: none;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-ui);
  font-size: var(--fs-numeral);
  font-weight: 500;
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--c-mute);
  white-space: nowrap;
}
.status.is-ready { display: inline-flex; }
.status__dot {
  width: 5px; height: 5px;
  background: var(--c-mute);
}
.status.is-open  .status__dot { background: var(--c-open); }
.status.is-open  .status__text { color: var(--c-open); }
.status.is-closed .status__dot { background: var(--c-closed); }

/* --- mobile ----------------------------------------------------------- */
/* Three hairlines that fold into a cross. They are positioned absolutely
   rather than stacked in normal flow: in flow, each line's own margin lives
   inside its box, so "translateY(5px) rotate(45deg)" rotates about a
   different point for each line and the cross comes out as a chevron. From
   dead centre, a plain rotate is all it takes. */
.navtoggle {
  position: relative;
  display: none;
  width: 40px; height: 40px;
  padding: 0;
  border: 1px solid var(--c-edge);
  transition: border-color var(--dur-fast) var(--ease);
}
.navtoggle:hover { border-color: var(--c-champagne); }
.navtoggle span {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px; height: 1px;
  margin: -1px 0 0 -8px;
  background: var(--c-ink);
  transition: transform var(--dur-fast) var(--ease),
              opacity var(--dur-fast) var(--ease);
}
.navtoggle span:nth-child(1) { transform: translateY(-5px); }
.navtoggle span:nth-child(3) { transform: translateY(5px); }
.navtoggle[aria-expanded="true"] span:nth-child(1) { transform: rotate(45deg); }
.navtoggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.navtoggle[aria-expanded="true"] span:nth-child(3) { transform: rotate(-45deg); }

@media (max-width: 1000px) {
  /* Toggle left, wordmark centre, an equal empty column right — the header
     stays symmetric at every width, which is the whole design. */
  .head__in { grid-template-columns: 40px 1fr 40px; }
  .navtoggle { display: block; grid-column: 1; grid-row: 1; }
  .wordmark  { grid-column: 2; }

  .head__panel {
    position: fixed;
    inset: var(--head-h) 0 auto;
    /* flex, deliberately. The two navs carry grid-column/grid-row from the
       desktop rules, and those are more specific than anything set here — in
       a grid container they would both land in row 1 and overlap. A flex
       container ignores them outright. */
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 1.75rem var(--gutter) 2.25rem;
    background: var(--c-canvas);
    border-bottom: 1px solid var(--c-rule);
    max-height: calc(100dvh - var(--head-h));
    overflow-y: auto;
    transform: translateY(-14px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur-fast) var(--ease),
                transform var(--dur-fast) var(--ease),
                visibility var(--dur-fast) var(--ease);
  }
  .head__panel.is-open { opacity: 1; visibility: visible; transform: none; }

  .head__nav {
    flex-direction: column;
    align-items: center;
    gap: 0;
    width: 100%;
  }
  .head__nav--l { padding-bottom: 1.4rem; border-bottom: 1px solid var(--c-rule-soft); }
  .head__nav--r { padding-top: 1.6rem; gap: 1.4rem; }

  .navlink { font-size: .8125rem; padding-block: .9rem; }
  /* Centred links want a centred underline, but the current-page rule still
     draws left-to-right. Collapse it to the middle when idle. */
  .navlink::after { left: 25%; right: 25%; }

  .head__phone { font-size: 1.0625rem; }
}


/* ══════════════════════════════════════════════════ 09 · CHAPTERS ═════ */

/* Each chapter is a full viewport, centred both ways. `svh` so the mobile
   browser chrome collapsing does not shove the content around mid-scroll. */
.chapter {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding: calc(var(--head-h) + var(--chapter-y)) 0 var(--chapter-y);
  scroll-snap-align: center;
  scroll-snap-stop: normal;
}

/* Chapters that can outgrow a short viewport align to their top instead, so
   the reader always starts at the heading rather than in the middle of it. */
.chapter--tall {
  align-content: start;
  scroll-snap-align: start;
}

.chapter + .chapter { border-top: 1px solid var(--c-rule-soft); }

/* The small foil numeral and title that opens each chapter. */
.chapter__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-bottom: 1.6rem;
}
.chapter__mark .rule { width: 42px; }
/* The pair draws outward from the numeral rather than both left-to-right,
   so the mark opens symmetrically. */
.chapter__mark .rule:first-child { transform-origin: right center; }


/* ══════════════════════════════════════════════════════ 10 · HERO ═════ */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: calc(var(--head-h) + 3rem) 0 4rem;
  scroll-snap-align: center;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--photo-grade);
}
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-hero), var(--vignette);
}

.hero__body {
  position: relative;
  z-index: 1;
  text-align: center;
  padding-inline: var(--gutter);
  max-width: 46rem;
}

.hero__name {
  margin: 1.6rem 0 0;
  font-size: var(--fs-wordmark);
  font-weight: 300;
  line-height: var(--lh-display);
  letter-spacing: var(--ls-wordmark);
  text-transform: uppercase;
  /* Uppercase Cormorant tracked this wide leaves a hole after the last
     letter; pull it back so the word stays optically centred. */
  text-indent: var(--ls-wordmark);
}
.hero__tag {
  margin-top: 1.5rem;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--fs-lede);
  color: var(--c-ink-soft);
}
.hero__rule { margin: 2.1rem auto 2.2rem; }
.hero__cta  { margin-top: 2.6rem; }

/* A hairline arrow at the foot of the hero. It is a link, not decoration —
   it jumps to the second chapter. */
.hero__scroll {
  position: absolute;
  left: 50%;
  bottom: 2rem;
  transform: translateX(-50%);
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: .75rem;
  text-decoration: none;
  color: var(--c-mute);
  transition: color var(--dur-fast) var(--ease);
}
.hero__scroll:hover { color: var(--c-champagne); }
.hero__scroll span {
  font-family: var(--font-ui);
  font-size: .5625rem;
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
.hero__scroll i {
  display: block;
  width: 1px;
  height: 46px;
  background: linear-gradient(180deg, var(--c-brass), transparent);
}

@media (max-width: 640px) {
  .hero__scroll { display: none; }
}


/* ═══════════════════════════════════════════════ 11 · PHOTOGRAPHS ═════ */

/* Every photograph on the site goes through .ph. It applies the grade, lays
   the vignette over the top and draws a brass hairline round the frame — the
   picture is mounted, not pasted. */
.ph {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--c-well);
}
.ph::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--vignette);
  pointer-events: none;
}
.ph img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--photo-grade);
  transition: transform 1.2s var(--ease-out);
}
.ph--keyline { border: 1px solid var(--c-rule); }
.ph--zoom:hover img { transform: scale(1.03); }

.ph--portrait { aspect-ratio: 3 / 4; }
.ph--square   { aspect-ratio: 1 / 1; }
.ph--wide     { aspect-ratio: 16 / 9; }
.ph--band     { aspect-ratio: 21 / 9; }

/* A small centred photograph, sized like a plate in a book rather than a
   hero. Used once per chapter at most. */
.ph--plate {
  width: min(200px, 54vw);
  margin-inline: auto;
}
.ph--card { width: min(320px, 74vw); margin-inline: auto; }

@media (prefers-reduced-motion: reduce) {
  .ph--zoom:hover img { transform: none; }
}

/* A full-bleed band of photography with type over it. */
.band {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  min-height: 46vh;
  padding: clamp(3.5rem, 7vw, 6rem) 0;
  overflow: hidden;
}
.band__media { position: absolute; inset: 0; z-index: -1; }
.band__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: var(--photo-grade);
}
.band__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-band), var(--vignette);
}

/* The page head on the three inner pages: a thin band of photography under
   the fixed nav, with the title centred on it. */
.pagehead {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  text-align: center;
  padding: calc(var(--head-h) + clamp(4.5rem, 9vw, 8rem)) 0 clamp(4rem, 7vw, 6.5rem);
  overflow: hidden;
  border-bottom: 1px solid var(--c-rule-soft);
}
.pagehead__media { position: absolute; inset: 0; z-index: -1; }
.pagehead__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: var(--photo-grade);
}
.pagehead__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-hero), var(--vignette);
}


/* ═════════════════════════════════════════════════ 12 · THE CARTE ═════ */

/* The service list. No cards, no photographs, no columns of dots — a printed
   carte: a foil numeral, the name in Cormorant italic, one tracked line of
   description, and the price in brass. Centred, with a hairline between
   courses. */
.carte {
  display: grid;
  gap: clamp(1.5rem, 2.6vw, 2.1rem);
  text-align: center;
}
.carte__item {
  display: grid;
  justify-items: center;
  gap: .55rem;
}
.carte__item + .carte__item {
  padding-top: clamp(1.5rem, 2.6vw, 2.1rem);
  border-top: 1px solid var(--c-rule-soft);
}
.carte__name {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-carte);
  line-height: 1.2;
  color: var(--c-ink);
}
.carte__note {
  font-family: var(--font-ui);
  font-size: var(--fs-meta);
  font-weight: 400;
  line-height: 1.7;
  letter-spacing: .12em;
  color: var(--c-mute);
  max-width: 34rem;
  /* Two lines' worth, whether the description needs one or two. Without it
     the prices in the left column sit a line higher than the right and the
     carte stops looking set and starts looking typed. */
  min-height: 3.4em;
}
.carte__price {
  font-family: var(--font-ui);
  font-size: var(--fs-numeral);
  font-weight: 600;
  letter-spacing: var(--ls-meta);
  color: var(--c-brass);
}
.carte__price s {
  color: var(--c-mute);
  text-decoration-thickness: 1px;
  margin-right: .5ch;
}

/* Two symmetric columns once there is room. Still centred, still a carte —
   a menu that runs six courses down a phone should not run six courses down
   a 27-inch monitor. */
@media (min-width: 900px) {
  .carte--two {
    grid-template-columns: 1fr 1px 1fr;
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
    align-items: start;
  }
  .carte--two::before {
    content: "";
    grid-row: 1 / -1;
    grid-column: 2;
    width: 1px;
    /* align-self, not height:100% — the container is align-items:start, which
       sizes every item to its content, and a pseudo-element with no content
       is then one pixel tall. */
    align-self: stretch;
    background: var(--c-rule-soft);
  }
  .carte--two .carte__item:nth-child(odd)  { grid-column: 1; }
  .carte--two .carte__item:nth-child(even) { grid-column: 3; }
  /* The first item in each column has nothing above it to be divided from. */
  .carte--two .carte__item:nth-child(1),
  .carte--two .carte__item:nth-child(2) { padding-top: 0; border-top: 0; }
}


/* ════════════════════════════════════════════════ 13 · THE PLATES ═════ */

/* Three pricing tiers, each a brass-hairline plate. Double-ruled, because a
   single line around a black box looks like a table cell and a double line
   looks like an engraved plate. */
.plates {
  display: grid;
  gap: clamp(1.25rem, 2.5vw, 2rem);
  grid-template-columns: 1fr;
}
@media (min-width: 860px) {
  .plates { grid-template-columns: repeat(3, 1fr); }
}

.plate {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 1rem;
  text-align: center;
  background: var(--c-surface);
  transition: border-color var(--dur-fast) var(--ease);
}
.plate:hover { border-color: var(--c-brass); }

.plate__name {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 400;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.plate__price {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 5vw, 3.6rem);
  font-weight: 300;
  line-height: 1;
  color: var(--c-ink);
  /* Cormorant defaults to old-style figures, which are lovely in running text
     and wrong at 3.6rem: "185" comes out with three different heights and
     reads as a typo rather than a price. */
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1;
}
.plate__price sup {
  font-family: var(--font-ui);
  font-size: .95rem;
  font-weight: 500;
  vertical-align: super;
  color: var(--c-brass);
  margin-right: .1ch;
}
.plate__list {
  display: grid;
  gap: .6rem;
  font-family: var(--font-ui);
  font-size: var(--fs-meta);
  letter-spacing: .1em;
  line-height: 1.6;
  color: var(--c-ink-soft);
  text-transform: none;
}
.plate__list li { padding-top: .6rem; border-top: 1px solid var(--c-rule-soft); }
.plate__list li:first-child { padding-top: 0; border-top: 0; }

/* The middle plate is the recommended one. It is marked with a foil rule
   above the name — not a colour swap, not a badge, not a scale transform. */
.plate--feature { background: var(--c-surface-2); }
.plate__flag {
  font-family: var(--font-ui);
  font-size: .5625rem;
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-brass);
}


/* ═══════════════════════════════════════════════ 14 · THE STAGE ══════ */

/* The lookbook: one photograph at a time, crossfading, with brass numeric
   pagination reading 01 / 12. No grid, no thumbnails, no lightbox.

   Weight note: twelve full-size photographs is a megabyte, so only the first
   is in the markup with a src. main.js assigns the rest from data-src as you
   reach them, one ahead and one behind. Without JavaScript the stage is a
   single mounted photograph and the controls are hidden — nothing breaks,
   there is simply less of it. */
.stage {
  display: grid;
  justify-items: center;
  gap: 1.5rem;
  width: 100%;
}

.stage__frame {
  position: relative;
  width: 100%;
  max-width: 640px;
  aspect-ratio: 4 / 5;
  background: var(--c-well);
  border: 1px solid var(--c-rule);
  overflow: hidden;
}
@media (min-width: 900px) {
  .stage__frame { max-width: 520px; }
  /* The home page shows the lookbook inside a chapter that also has to hold a
     heading, a caption and the controls within one viewport. */
  .stage--compact .stage__frame { max-width: 350px; }
}

.stage__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .85s var(--ease-out);
}
.stage__slide.is-on { opacity: 1; }
.stage__slide img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: var(--photo-grade);
}
.stage__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--vignette);
  pointer-events: none;
}

/* Controls appear only when the script that drives them is alive. */
.stage__bar { display: none; }
.js-ready .stage__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
}

.stage__btn {
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--c-edge);
  color: var(--c-ink);
  transition: color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.stage__btn svg { width: 15px; height: 15px; }
.stage__btn:hover:not(:disabled) {
  color: var(--c-champagne);
  border-color: var(--c-champagne);
}
.stage__btn:disabled { opacity: .35; cursor: default; }

.stage__count {
  font-family: var(--font-ui);
  font-size: var(--fs-numeral);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  color: var(--c-brass);
  min-width: 6ch;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.stage__count b { font-weight: 600; color: var(--c-brass); }
.stage__count i { font-style: normal; color: var(--c-mute); }

.stage__caption {
  min-height: 3.2em;
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--fs-lede);
  color: var(--c-ink-soft);
  max-width: 32rem;
}
.stage__caption em { font-style: normal; }


/* ═══════════════════════════════════════════════════ 15 · VOICES ═════ */

/* One pull quote per chapter turn, set enormous in Cormorant italic. The
   quotation marks are set as decoration and hidden from assistive tech. */
.quote {
  text-align: center;
  max-width: 44rem;
  margin-inline: auto;
}
.quote__text {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-quote);
  line-height: 1.24;
  color: var(--c-ink);
}
.quote__mark {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(3rem, 7vw, 5rem);
  line-height: .5;
  color: var(--c-brass);
  opacity: .55;
  margin-bottom: .6rem;
}
.quote__by {
  margin-top: 2rem;
  font-family: var(--font-ui);
  font-size: var(--fs-numeral);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-mute);
}

/* Several quotes stacked, only one shown, advanced by main.js. Without JS
   they simply all show, one under the other. */
.js-ready .voices__item { display: none; }
.js-ready .voices__item.is-on { display: block; }
.voices__item + .voices__item { margin-top: 3rem; }
.js-ready .voices__item + .voices__item { margin-top: 0; }

.voices__dots {
  display: none;
  justify-content: center;
  gap: .6rem;
  margin-top: 2.5rem;
}
.js-ready .voices__dots { display: flex; }
.voices__dot {
  width: 26px; height: 1px;
  padding: 0;
  background: var(--c-edge);
  transition: background-color var(--dur-fast) var(--ease);
}
.voices__dot[aria-selected="true"] { background: var(--c-champagne); }
/* A 1px target is impossible to hit — give it an invisible 44px box. */
.voices__dot { position: relative; }
.voices__dot::after {
  content: "";
  position: absolute;
  inset: -22px -6px;
}


/* ═══════════════════════════════════════════ 16 · LEDGER + FACTS ═════ */

/* The hours table and the address block. Hairlines only, no fills, no zebra
   striping — a printed opening-hours card. */
.ledger {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-ui);
  font-size: var(--fs-meta);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.ledger caption {
  padding-bottom: 1.25rem;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  color: var(--c-brass);
  text-align: center;
}
.ledger th,
.ledger td {
  padding: .95rem .5rem;
  border-bottom: 1px solid var(--c-rule-soft);
  font-weight: 400;
  color: var(--c-ink-soft);
}
.ledger th { text-align: left; color: var(--c-mute); }
.ledger td { text-align: right; }
.ledger tr:last-child th,
.ledger tr:last-child td { border-bottom: 0; }
.ledger tr.is-today th,
.ledger tr.is-today td { color: var(--c-champagne); }
.ledger tr.is-today th::after {
  content: " · today";
  color: var(--c-brass);
}

/* Address / phone / email, centred, each with a tracked label above it. */
.facts {
  display: grid;
  gap: 2.25rem;
  text-align: center;
}
@media (min-width: 780px) {
  .facts--row { grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
}
.facts dt {
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-brass);
  margin-bottom: .75rem;
}
.facts dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--fs-body);
  line-height: 1.62;
  color: var(--c-ink);
}
.facts dd a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: .3em;
  transition: color var(--dur-fast) var(--ease),
              text-decoration-color var(--dur-fast) var(--ease);
}
.facts dd a:hover { color: var(--c-champagne); text-decoration-color: var(--c-champagne); }

/* Numbered notes — the care card and the studio policies. */
.notes { display: grid; gap: 1.6rem; }
.notes__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.1rem;
  align-items: baseline;
  text-align: left;
  padding-top: 1.6rem;
  border-top: 1px solid var(--c-rule-soft);
}
.notes__item:first-child { padding-top: 0; border-top: 0; }
.notes__item p { color: var(--c-ink-soft); font-size: var(--fs-body); }
.notes__item h3 { margin-bottom: .35rem; }


/* ════════════════════════════════════════════════════ 17 · FORMS ═════ */

.form { display: grid; gap: 1.5rem; text-align: left; }
@media (min-width: 700px) {
  .form--two { grid-template-columns: 1fr 1fr; }
  .form .full { grid-column: 1 / -1; }
}

.field { display: grid; gap: .55rem; }
.field > span {
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-mute);
}
.field > span em {
  font-style: normal;
  color: var(--c-brass);
  margin-left: .4ch;
}

.input {
  width: 100%;
  padding: .95rem 1rem;
  background: var(--c-surface);
  border: 1px solid var(--c-edge);
  border-radius: var(--r);
  font-family: var(--font-ui);
  font-size: .9375rem;
  letter-spacing: .02em;
  color: var(--c-ink);
  transition: border-color var(--dur-fast) var(--ease);
}
/* Pinned so a date, a select and a text field on the same row are the same
   box — they are not by default. See --field-h in tokens.css. */
input.input,
select.input { height: var(--field-h); }
.input::placeholder { color: var(--c-mute); }
.input:hover { border-color: var(--c-brass); }
.input:focus { border-color: var(--c-champagne); }
textarea.input { min-height: 8rem; resize: vertical; line-height: 1.6; }

select.input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.5rem;
  /* The chevron is drawn with two borders rather than a background image so
     it inherits the brass token instead of being baked into a data URI. */
}
.select {
  position: relative;
  display: block;
}
.select::after {
  content: "";
  position: absolute;
  right: 1.1rem;
  top: 50%;
  width: 6px; height: 6px;
  margin-top: -5px;
  border-right: 1px solid var(--c-brass);
  border-bottom: 1px solid var(--c-brass);
  transform: rotate(45deg);
  pointer-events: none;
}

/* The composed request, printed on the page as well as handed to mailto:. */
.receipt {
  display: none;
  margin-top: 2rem;
  padding: 1.5rem;
  border: 1px solid var(--c-rule);
  text-align: left;
}
.receipt.is-shown { display: block; }
.receipt pre {
  margin: 1rem 0 1.25rem;
  padding: 1rem;
  background: var(--c-well);
  border: 1px solid var(--c-rule-soft);
  overflow-x: auto;
  font-family: var(--font-ui);
  font-size: .8125rem;
  line-height: 1.7;
  letter-spacing: 0;
  color: var(--c-ink-soft);
  white-space: pre-wrap;
}


/* ═══════════════════════════════════════════════════ 18 · FOOTER ═════ */

.foot {
  border-top: 1px solid var(--c-rule);
  padding: clamp(3.5rem, 7vw, 6rem) 0 2.5rem;
  text-align: center;
}

.foot__mark { margin-bottom: 2.25rem; }
.foot__mark .foil { --foil-w: 86px; }

.foot__name {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: uppercase;
}
.foot__tag {
  margin-top: .7rem;
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-brass);
}

.foot__cols {
  display: grid;
  gap: 2.75rem;
  margin-top: 3.25rem;
  text-align: center;
}
@media (min-width: 780px) {
  .foot__cols { grid-template-columns: repeat(2, 1fr); gap: 3.5rem; }
}
.foot__cols h3 {
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-mute);
  margin-bottom: 1.1rem;
}

.foot__links {
  display: grid;
  justify-items: center;
  gap: .7rem;
  font-family: var(--font-ui);
  font-size: var(--fs-fine);
  letter-spacing: .06em;
}
.foot__links a {
  color: var(--c-ink-soft);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease);
}
.foot__links a:hover { color: var(--c-champagne); }

.foot__hours {
  display: grid;
  justify-items: center;
  gap: .55rem;
  font-family: var(--font-ui);
  font-size: var(--fs-fine);
  letter-spacing: .06em;
  color: var(--c-ink-soft);
}
.foot__hours span { color: var(--c-mute); }

.foot__social {
  display: flex;
  justify-content: center;
  gap: 1.25rem;
  margin-top: 2.5rem;
}
.foot__social a {
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  border: 1px solid var(--c-rule);
  color: var(--c-ink-soft);
  transition: color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.foot__social a:hover { color: var(--c-champagne); border-color: var(--c-champagne); }
.foot__social svg { width: 16px; height: 16px; }

.foot__base {
  margin-top: 3rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--c-rule-soft);
  display: grid;
  gap: .6rem;
  font-family: var(--font-ui);
  font-size: .75rem;
  letter-spacing: .06em;
  color: var(--c-mute);
}
.foot__base a {
  color: var(--c-ink-soft);
  text-decoration: underline;
  text-decoration-color: var(--c-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: .28em;
}
.foot__base a:hover { color: var(--c-champagne); text-decoration-color: var(--c-champagne); }
@media (min-width: 780px) {
  .foot__base {
    grid-auto-flow: column;
    justify-content: space-between;
    align-items: center;
  }
}


/* ═════════════════════════════════════════════════ 19 · CALL BAR ═════ */

/* Phones are most of a salon's traffic and phone calls are most of its
   bookings, so the two actions never scroll away on a small screen. One
   hairline, two tracked labels, no colour: it announces itself by being the
   only fixed thing on the page. */
.callbar { display: none; }

@media (max-width: 780px) {
  .callbar {
    position: fixed;
    inset: auto 0 0;
    z-index: 90;
    display: grid;
    grid-template-columns: 1fr 1fr;
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
            backdrop-filter: var(--glass-blur);
    border-top: 1px solid var(--c-rule);
  }
  .callbar a {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    padding: 1.05rem .5rem;
    font-family: var(--font-ui);
    font-size: var(--fs-label);
    font-weight: 600;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    text-decoration: none;
    color: var(--c-ink);
  }
  .callbar a + a { border-left: 1px solid var(--c-rule); }
  .callbar a.is-primary { color: var(--c-brass); }
  .callbar svg { width: 14px; height: 14px; }

  /* Keep the last of the footer clear of the bar. */
  .foot { padding-bottom: 6rem; }
}


/* ═══════════════════════════════════════════ 20 · REVEAL ON SCROLL ═══ */

/* Opacity plus a 12px rise over 700ms, exactly as specified. Applied only
   once JavaScript has confirmed it is alive — otherwise the content is
   simply visible, which is the correct fallback. */
.js-ready .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out);
}
.js-ready .reveal.is-in,
.reveal-fallback .reveal {
  opacity: 1;
  transform: none;
}

/* Children of a revealed block come in a beat apart. Four steps is the whole
   ladder; beyond that it starts to feel like a slideshow. */
.js-ready .reveal [data-step] { transition-delay: 0ms; }
.js-ready .reveal.is-in [data-step="1"] { transition-delay: 90ms; }
.js-ready .reveal.is-in [data-step="2"] { transition-delay: 180ms; }
.js-ready .reveal.is-in [data-step="3"] { transition-delay: 270ms; }
.js-ready .reveal.is-in [data-step="4"] { transition-delay: 360ms; }

@media (prefers-reduced-motion: reduce) {
  .js-ready .reveal { opacity: 1; transform: none; transition: none; }
  .rule { transition: none; transform: scaleX(1); }
  .stage__slide { transition: none; }
  .ph img { transition: none; }
}


/* ══════════════════════════════════════════════════════ 21 · PRINT ═══ */

/* A client will print the price list. Do not make them print a black page. */
@media print {
  html.snap { scroll-snap-type: none; }
  body {
    background: var(--print-paper);
    color: var(--print-ink);
    font-size: 11pt;
  }
  .head, .callbar, .foot__social, .stage__bar, .hero__scroll,
  .band__media, .pagehead__media, .hero__media { display: none !important; }
  .chapter, .hero { min-height: 0; padding: 1.5rem 0; page-break-inside: avoid; }
  .label, .carte__price, .carte__note, .facts dt, .meta, .fine {
    color: var(--print-mute) !important;
  }
  .numeral { background: none; color: var(--print-mute) !important; }
  .carte__name, .plate__price, .plate__list, .lede, .facts dd,
  h1, h2, h3, .quote__text { color: var(--print-ink) !important; }
  .plate, .plate--feature { background: var(--print-paper); }
  a { text-decoration: underline; }
  .ph, .plate, .dbl-box, .dbl, .carte__item, .ledger th, .ledger td {
    border-color: var(--print-rule) !important;
  }
}
