/* ===========================================================================
   Tropical Property, deck kit, edition 01.

   The brand's document primitives, ported into a deck scope from
   website/design-research/print/directions/volta/build.py (its CSS f-string
   and pages2.EXTRA_CSS) plus brand/tokens/tokens.css, with the geometry of
   BRAND-DNA section 6.

   NOTHING HERE IS INVENTED. Every selector below already exists in build.py or
   pages2.py, or is a token declared in tokens.css. If a direction needs a
   primitive that is not in this file and not in BRAND-DNA section 7, it does
   not exist; the answer is a different primitive, not a new one.

   REQUIRED IN EVERY TEMPLATE THAT USES THIS FILE:
       <meta name="viewport" content="width=794">
   That single line is what makes the A4 sheet scale to fit a phone instead of
   forcing a pinch. BRAND-DNA F8 and plan section 4.2. A deck without it is a
   defect, and render.mjs --mobile is the check.

   Fonts live in fonts.css, copied VERBATIM from volta/fonts-static.css (the
   static instances; a variable axis becomes Type3 in the PDF, trap 1). Load
   fonts.css BEFORE this file. fill.py inlines both into the built deck, so a
   shipped deck is one file with zero external requests.

   Not included, on purpose: charts. C1 to C6 are per-direction work and live
   in the direction that draws them. The band (P1) is retired.
   =========================================================================== */

/* --- tokens, verbatim from brand/tokens/tokens.css ----------------------- */
:root {
  --paper: #f3ede8;          /* Page ground. Every surface starts here. */
  --ink-body: #554744;       /* All running text, at every size. */
  --ink-display: #725f59;    /* Headings at 24px and above only. */
  --muted: #8c7772;          /* Eyebrows, captions, axis labels. */
  --accent: #1f607a;         /* The only chromatic value. Text and data, never an edge. */
  --rule: #cec8c4;           /* Every hairline, divider and cell edge. */
  --rule-soft: #e2deda;      /* Table row dividers and inner rules only. */
  --ground-dk: #2b2523;      /* Dark pages and plate scrims. */
  --on-dark: #e3dfdc;        /* Text on the dark ground. */
  --pale-on-light: #91837f;  /* The pale end of the light radiant ramp. */
  --pale-on-dark: #8d817e;   /* Secondary text on the dark ground. */
  --g-light-a: #796862;      /* Gradient display fill, light pages, first stop. */
  --g-light-b: #948a87;      /* Gradient display fill, light pages, last stop. */
  --g-dark-a: #e6dedc;       /* Gradient display fill, dark pages, first stop. */
  --g-dark-b: #786d6a;       /* Gradient display fill, dark pages, last stop. */
  --grad-flat: #857873;      /* Print-safe flat stand-in, light. */
  --grad-flat-dk: #ada4a1;   /* Print-safe flat stand-in, dark. */

  /* geometry, BRAND-DNA section 6, document A4 portrait */
  --pw: 794px;               /* sheet width, A4 at 96dpi */
  --ph: 1123px;              /* sheet height */
  --gut: 60.5px;             /* type gutter, 16mm */
  --gut-img: 22.7px;         /* image gutter, 6mm */
  --top: 56.7px;             /* top inset, 15mm */
  --bot: 52.9px;             /* bottom inset, 14mm */
  --meas: 673px;             /* text measure, 794 minus two type gutters */
  --ind: 18px;               /* left-rule indent */
  --gap-s: 7px;              /* eyebrow to a small statement */
  --gap-b: 17px;             /* eyebrow to a big statement */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* --- the sheet ----------------------------------------------------------- */
.page {
  width: var(--pw); height: var(--ph); position: relative; overflow: hidden;
  background: var(--paper); color: var(--ink-body);
  font-family: 'Instrument Sans', sans-serif; font-weight: 450;
  font-variant-numeric: tabular-nums lining-nums;
  -webkit-font-smoothing: antialiased;
}

/* P1, the page band. RETIRED. display:none keeps existing markup inert rather
   than forcing every call site to be edited. Do not silently re-enable it. */
.band { display: none; }

/* The frame stops clear of the folio band, so nothing can collide with it.
   render.mjs asserts the collision separately, on the real glyph run. */
.frame { position: absolute; left: var(--gut); right: var(--gut);
         top: var(--top); bottom: calc(var(--bot) + 30px); z-index: 2;
         /* The frame spans almost the whole sheet but on most sheets only
            holds content at the top, and at z-index 2 the empty rest of it sat
            over its siblings and ate their clicks. That is how the Google Maps
            link on sheet 3 shipped looking like a link and doing nothing:
            perfect markup, every gate green, elementFromPoint returning
            <div.frame>. The frame itself is a box, not a target; its children
            are. render.mjs now asserts this on every build. */
         pointer-events: none; }
.frame > * { pointer-events: auto; }

/* P2, the folio band: chapter tag left, page number right. */
.foot { position: absolute; left: var(--gut); right: var(--gut); bottom: var(--bot);
        display: flex; justify-content: space-between; align-items: baseline; z-index: 2; }

/* --- the ten type roles -------------------------------------------------- */
/* Crossover, never violated: serif at 17.5px and up, sans at 15.75px and down.
   Serif tracking is always negative. Uppercase sans is always +0.05em.
   A size outside these ten is a one-off, whoever typed it. */
.d  { font-family: 'Newsreader Disp', serif; font-weight: 340;
      font-size: 66px; line-height: 72px; letter-spacing: -0.055em;
      text-transform: uppercase; color: var(--ink-display);
      font-variant-numeric: proportional-nums lining-nums; }
      /* line-height was 62px, BELOW font-size, the only type role that broke
         that rule (every sibling role below is >= its own font-size). Measured
         2026-09-03: this font's real ascent+descent is 49+17=66px, exactly the
         font-size with zero slack, so a sub-font-size line-height gives the
         glyphs a NEGATIVE half-leading, pushing their tops above the line box.
         Invisible on solid ink, but .dgd/.dg fill this role with a
         background-clip:text gradient, and the gradient's paint box follows
         the line-height box: the ascender's tip lands outside it and renders
         as bare transparency against the dark photo behind, cutting the tops
         off numerals like "8", "1", "0" and the ascender of "d". 72px gives
         2px of top cushion and 3px of bottom cushion on top of .dgd's own
         .08em padding-bottom. Verified by canvas TextMetrics against the
         live HTTP-served page, not guessed. */
.h1 { font-family: 'Newsreader Disp', serif; font-weight: 400;
      font-size: 40px; line-height: 40px; letter-spacing: -0.03em; color: var(--ink-display); }
.h2 { font-family: 'Newsreader Disp', serif; font-weight: 400;
      font-size: 29px; line-height: 30.4px; letter-spacing: -0.02em; color: var(--ink-display); }
.h3 { font-family: 'Newsreader Sub', serif; font-weight: 400;
      font-size: 21px; line-height: 22.4px; letter-spacing: -0.02em; color: var(--ink-display); }
.h4 { font-family: 'Newsreader Cap', serif; font-weight: 400;
      font-size: 17.5px; line-height: 20.4px; letter-spacing: -0.02em; color: var(--ink-display); }
.lead { font-size: 15.75px; line-height: 21.9px; }
.b    { font-size: 14px; line-height: 19.25px; }
.s    { font-size: 12.25px; line-height: 17.5px; }
.eb   { font-size: 10.5px; line-height: 14px; font-weight: 530; letter-spacing: .05em;
        text-transform: uppercase; color: var(--muted); }
.eb-s { font-size: 8.75px; line-height: 10.5px; font-weight: 530; letter-spacing: .05em;
        text-transform: uppercase; color: var(--muted); }

/* The accent colours TEXT and DATA. Never an edge, a border, a rule or a thin
   strip, including a pseudo-element left rule. Fourth recurrence in this
   workspace; the sweep checks pseudo-element backgrounds, not only border-*. */
.accent { color: var(--accent); }
.note   { color: var(--muted); }
p + p   { margin-top: 9px; }
em      { font-style: italic; }   /* italic serif <em> is the only emphasis */

/* --- P3, the left-rule cell. THE device. --------------------------------- */
/* 1px --rule at the block's left edge, 18px indent, eyebrow above. Six
   visually different components are all this one pattern. */
.cell { position: relative; padding-left: var(--ind); }
.cell:before { content: ""; position: absolute; left: 0; top: 0;
               width: 1px; height: 100%; background: var(--rule); }
.cell .eb   { margin-bottom: var(--gap-s); }
.cell-b .eb { margin-bottom: var(--gap-b); }

/* --- P5, the two-column grid --------------------------------------------- */
.grid2 { display: grid; grid-template-columns: 1fr 1fr; column-gap: 38px; row-gap: 30px; }

/* --- P4, the rule-only table --------------------------------------------- */
/* Header separated by --rule, rows by --rule-soft. No fills, no zebra, no
   vertical borders. Column template is set per table by the direction, since
   a unit ladder and a distance list do not share a shape. */
.thead, .tr { display: grid; gap: 22px; padding: 9px 0;
              border-bottom: 1px solid var(--rule-soft); }
.thead { border-bottom: 1px solid var(--rule); padding-top: 16px; }
.thead .tc { font-size: 10.5px; font-weight: 530; letter-spacing: .05em;
             text-transform: uppercase; color: var(--muted); }
.tl { font-size: 10.5px; font-weight: 530; letter-spacing: .05em;
      text-transform: uppercase; color: var(--muted); }
.tr .tc { font-size: 12.25px; line-height: 17.5px;
          font-variant-numeric: tabular-nums lining-nums; }
.hr { height: 1px; background: var(--rule); width: 100%; }

/* --- the gradient display fill ------------------------------------------- */
/* One device, applied narrowly. At most ONE per page, never below 29px, and
   it never goes dark: it only recedes toward the paper.
   DIVERGENCE from build.py, stated: build.py puts the gradient on .h2 itself,
   which is right for a book with one h2 per page and wrong for a one-pager
   that may carry two. Here .h2 is solid and the gradient is opt in via .dg on
   light and .dgd on dark, so "one per page" stays a decision a direction makes
   rather than a side effect of a heading. No new primitive: .dg and .dgd are
   pages2.EXTRA_CSS verbatim. */
.dg  { background: linear-gradient(125.75deg, var(--g-light-a) 9.27%, var(--g-light-b) 95.35%);
       -webkit-background-clip: text; background-clip: text; color: transparent;
       -webkit-text-fill-color: transparent; padding-bottom: .08em; }
.dgd { background: linear-gradient(125.75deg, var(--g-dark-a) 9.27%, var(--g-dark-b) 95.35%);
       -webkit-background-clip: text; background-clip: text; color: transparent;
       -webkit-text-fill-color: transparent; padding-bottom: .08em; }

/* --- P6, the dark page, and the on-dark inks ----------------------------- */
.page.dark { background: var(--ground-dk); color: var(--on-dark); }
.radwrap { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.radwrap svg { display: block; width: 100%; height: 100%; }
.od { color: var(--muted); }
.page.dark .eb.od, .page.dark .eb-s.od { color: var(--muted); }
.page.dark .h1, .page.dark .h2, .page.dark .h3, .page.dark .h4 { color: var(--on-dark); }
.page.dark .note { color: var(--pale-on-dark); }
/* the cell's left rule on the dark ground: the same hairline, not the accent.
   The accent measures 2.1:1 there and fails every floor, so it never appears
   on a dark page at all. */
.od-cell:before { background: rgba(227, 223, 220, .30); }
.hr-od { height: 1px; width: 100%; background: rgba(227, 223, 220, .22); }

/* --- P8, the full-bleed plate, and its one permitted scrim --------------- */
.plate { position: absolute; inset: 0; width: 100%; height: 100%;
         object-fit: cover; z-index: 1; }
.platescrim { position: absolute; inset: 0; z-index: 2;
  /* The 62% stop used to be .55, which was enough on a plate whose lower third
     was dark and not enough on one that is not. Layan Verde's contact plate has
     sunlit terrace and pale cushions exactly where the headline sits, and
     "o Layan Verde" set white on near-white. Raised to .72 there, with a new
     .42 stop at 48% so the ramp stays smooth rather than banding, which also
     lifts the hero eyebrow on sheet 2 off whatever the photograph puts under
     it. Darkening a scrim can only help a plate that was already dark. */
  background: linear-gradient(179deg, rgba(18,13,11,0) 22%, rgba(18,13,11,.42) 48%,
              rgba(18,13,11,.72) 62%, rgba(18,13,11,.92) 86%, rgba(18,13,11,.96) 100%); }

/* --- P9, narrow text plus wide image ------------------------------------- */
/* Text stays at the type gutter, the image bleeds to the sheet edge at 330px.
   Working pages carry no photography; this archetype and the plate are the
   two places a photograph belongs. */
.bleed-r { position: absolute; right: 0; width: 330px; height: 470px; overflow: hidden; z-index: 1; }
.bleed-r img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --- a windowed image at the image gutter -------------------------------- */
/* Not a new primitive: an <img> in normal flow, capped by the image gutter,
   which is what build.py's image pages do outside the bleed archetype. */
.win { display: block; width: 100%; height: 100%; object-fit: cover; }
.winbox { position: relative; overflow: hidden; }

/* --- print ---------------------------------------------------------------
   background-clip:text writes the glyph run TWICE in the PDF, once as a clip
   and once as the shading; iOS PDFKit renders the pair as truncated, doubled
   text. In print the gradient collapses to a flat tone, and `color` and
   `-webkit-text-fill-color` are reset TOGETHER. Setting only `color` leaves
   the text transparent, which is invisible, which is worse.
   ------------------------------------------------------------------------ */
@media print {
  @page { size: 794px 1123px; margin: 0; }
  html, body { margin: 0 !important; padding: 0 !important; gap: 0 !important;
               display: block !important; background: #fff !important; }
  /* Chrome ships Ctrl+P with "Background graphics" OFF, which drops every CSS
     background. Measured 2026-09-03 by rendering with the rule cancelled: the
     CONTACT sheet loses its dark ground, its plate photograph and the portrait,
     and prints Max's name, phone, email and address in pale grey on white at a
     mean of 253 against 31 with the rule. That is the one sheet a buyer has any
     reason to print, so this is load-bearing, not cosmetic.
     The render gate could not have caught it: it passes printBackground:true,
     which is the flag a real reader never sets. */
  html, body, .page, .page * {
    -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
  .page { margin: 0 !important; break-after: page; page-break-after: always;
          break-inside: avoid; page-break-inside: avoid;
          box-shadow: none !important; }
  .page:last-child { break-after: auto; page-break-after: auto; }
  .dg, .dgd { background: none !important;
    -webkit-background-clip: border-box !important; background-clip: border-box !important; }
  .dg  { color: var(--grad-flat) !important; -webkit-text-fill-color: var(--grad-flat) !important; }
  .dgd { color: var(--grad-flat-dk) !important; -webkit-text-fill-color: var(--grad-flat-dk) !important; }
}

/* --- screen scaffold ------------------------------------------------------
   Stacks the sheets on a neutral ground for review. The print block above
   flattens all of it, so the PDF has no drift. Keep it last. */
body { background: #8b8b8b; display: flex; flex-direction: column;
       align-items: center; gap: 26px; padding: 26px 0; }
