/* =============================================================================
   ra.css -- PBS Rural Assets
   Built from assets/pbs.css + the landing and property <style> blocks.
   Do not edit the preview and this file separately; rebuild from the preview.

   Enqueued ONLY on Rural Assets pages. Loading it site-wide restyles the whole
   site: it defines --ra-* tokens on :root and sets bare-element rules for
   input, textarea, select and label, and GeneratePress binds its own global
   colour slugs to the body, nav, buttons and every form field.

   The preview's own header, nav, burger and footer rules have been STRIPPED
   from this file by the build -- WordPress supplies that chrome. In particular
   .site-header{height:72px;background:#000} and .site-header img{width:330px}
   are gone: generate_header_classes() puts .site-header on GeneratePress's real
   header, so those two would have blacked it out and blown the live logo up to
   330px on every Rural Assets page.

       is_singular( 'rural_asset' ) || is_page( 'rural-assets' )

   NOT is_page_template( 'page-rural-assets.php' ) -- that reads
   _wp_page_template, which is 'default' for a hierarchy-selected
   page-{slug}.php, so it is always false.

   Sections 2 and 3 are scoped by body class where, and only where, they would
   otherwise conflict. Add the classes with:

       add_filter( 'body_class', function ( $c ) {
           if ( is_singular( 'rural_asset' ) ) { $c[] = 'ra-property'; }
           if ( is_page( 'rural-assets' ) )    { $c[] = 'ra-landing'; }
           return $c;
       } );
   ============================================================================= */

/* ---------- 0. FONTS ------------------------------------------------------ */
/* Be Vietnam Pro ITALIC, self-hosted.

   GeneratePress already self-hosts Outfit and Be Vietnam Pro site-wide
   (uploads/generatepress/fonts/fonts.css, gp_font_library_settings
   google_gdpr:true, so nothing is fetched from Google at runtime). But every
   face it generated is font-style:normal -- there is no italic anywhere on the
   site.

   The approved design uses 300 italic in five places, including the hero
   subtitle and John's endorsement quote, and 400 italic for the <em> in the
   PBS View lede. Without these the browser synthesises an oblique by shearing
   the upright, which is visibly wrong at display sizes.

   Declared HERE rather than added to the GP font library, for two reasons: a
   font-library resave regenerates fonts.css and would drop them, and these
   faces are only used on Rural Assets pages so they should only load there.

   Paths are relative to this stylesheet, so one file works in both locations:
       preview   /assets/ra.css   + /assets/fonts/
       theme     ra/ra.css        + ra/fonts/
   ------------------------------------------------------------------------- */
@font-face {
  font-family: 'Be Vietnam Pro'; font-style: italic; font-weight: 300; font-display: swap;
  src: url('fonts/be-vietnam-pro-italic-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Be Vietnam Pro'; font-style: italic; font-weight: 300; font-display: swap;
  src: url('fonts/be-vietnam-pro-italic-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Be Vietnam Pro'; font-style: italic; font-weight: 400; font-display: swap;
  src: url('fonts/be-vietnam-pro-italic-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Be Vietnam Pro'; font-style: italic; font-weight: 400; font-display: swap;
  src: url('fonts/be-vietnam-pro-italic-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ---------- 0b. GENERATEPRESS CONTAINER OVERRIDES ------------------------ */
/* Without this the section renders as a stack of squeezed columns.

   GeneratePress wraps page content in:

       #page.site.grid-container.container   max-width: 1200px
       #content.site-content                 display: FLEX, padding: 0 32px

   Every top-level block of this design is a direct child of #content, so they
   all become FLEX ITEMS. With no flex property they shrink to content width:
   measured 364px for .product (its grid columns collapsing to 0px / 248px),
   325px, 426px, 304px, 264px for the sections below it, and 1,842px of
   horizontal overflow across the page.

   The design supplies its own measure -- .wrap is max-width 1200 with 40px
   gutters -- and several sections are deliberately full-bleed (the hero, the
   breather, the dark photographic bands). So GeneratePress's container has to
   stand down on these two page types and let the design do its own width.

   Scoped to the body classes, so nothing here touches any other page on the
   site. That scoping is the whole reason it is safe to be this blunt.
   ------------------------------------------------------------------------- */

body.ra-property #page.site,
body.ra-landing  #page.site {
  max-width: none;
}

body.ra-property #content.site-content,
body.ra-landing  #content.site-content {
  display: block;   /* not flex: our sections are not columns beside a sidebar */
  padding: 0;
}

/* GeneratePress's own inner wrappers, when the "one container" layout is not
   in use. Harmless when they are absent. */
body.ra-property #primary.content-area,
body.ra-landing  #primary.content-area {
  width: 100%;
  max-width: none;
  padding: 0;
}

body.ra-property .site-main,
body.ra-landing  .site-main {
  margin: 0;
  padding: 0;
}

/* The theme adds an article wrapper with its own margins on singular views. */
body.ra-property .site-main > article,
body.ra-landing  .site-main > article {
  margin: 0;
  padding: 0;
  border: 0;
}

/* GeneratePress prints the featured image above the content on singular views
   (post-image-above-header). This design opens with its own gallery, so a
   second copy of the same photograph above it is a duplicate. */
body.ra-property .featured-image,
body.ra-property .post-image {
  display: none;
}

/* The entry title would repeat the <h1> the design already prints. */
body.ra-property .entry-header .entry-title,
body.ra-landing  .entry-header .entry-title {
  display: none;
}

/* ---------------------------------------------------------------------------
   Headings must state that they inherit.

   ⚠️ This design colours headings ENTIRELY BY INHERITANCE: body sets
   --ra-contrast, .hero .inner sets #fff, .ink sets #fff, and h1/h2/h3 in
   pbs.css set font and margin but deliberately no colour.

   GeneratePress emits an inline `h1 { color: var(--contrast-2) }` (and the same
   for h2/h3). A DIRECT rule beats an INHERITED value no matter how low its
   specificity — inheritance only applies when nothing matches at all. So every
   heading on these pages took GeneratePress's colour instead:

     .hero h1 "PBS RURAL ASSETS"   #ffffff -> #1a1a1a   (black on a photograph)
     every other h2/h3             #141414 -> #1a1a1a   (imperceptible, same bug)

   `color: inherit` restores exactly what the design assumes, in one rule, and
   keeps working in every context: white inside .hero .inner and .ink, and
   --ra-contrast everywhere else. Enumerating each context would need updating
   every time a section is added.

   ⚠️ :not([class]) matters. Without it this rule is (0,2,1) and overrides the
   headings that legitimately set their OWN colour — .eoi__title is (0,1,0) and
   went from the green it is meant to be to near-black. Bare h1/h2/h3 are
   exactly the ones relying on inheritance; a heading carrying a class is
   styling itself and must be left alone.
   --------------------------------------------------------------------------- */
body.ra-property h1:not([class]), body.ra-property h2:not([class]),
body.ra-property h3:not([class]), body.ra-property h4:not([class]),
body.ra-property h5:not([class]), body.ra-property h6:not([class]),
body.ra-landing  h1:not([class]), body.ra-landing  h2:not([class]),
body.ra-landing  h3:not([class]), body.ra-landing  h4:not([class]),
body.ra-landing  h5:not([class]), body.ra-landing  h6:not([class]) {
  color: inherit;
}

/* ===========================================================================
   WPForms, wearing the approved design's form.

   The preview's forms were mock <form> elements: a <label> wrapping its own
   <input>, styled by `.form-card input, .form-card textarea`. WordPress renders
   WPForms 2.0.2 in MODERN MARKUP, which shares none of that DOM and brings its
   own complete visual language. Measured on the real rendered pages before any
   of this was written, the four live forms shipped as:

     label    700 16px sentence case, rgba(0,0,0,.85)   design: 600 12px UPPERCASE .08em
     input    boxed, 1px all round, 3px radius,         design: border-bottom only,
              14px inset, white, 43px tall, max 60%             flush left, transparent
     textarea 97px fixed height, 14px on all sides      design: ruled, 10px 0
     rhythm   30px between fields                       design: 18px / 20px grid

   So the design's ruled treatment was reaching NOTHING: every one of its
   selectors is outranked, and WPForms' stylesheet loads in the BODY, after
   ra.css in the head, so it also wins every tie on source order.

   ⚠️ SPECIFICITY IS THE WHOLE GAME HERE. WPForms' field rules sit at (0,3,2)
   and its focus rule at (0,4,2). Everything below is written from
   `body.ra-* div.wpforms-container .wpforms-field …`, which is (0,3,3) / (0,4,3)
   — one type selector clear. Drop the `div`, or the `.wpforms-field`, and the
   rule silently stops applying. It will not error; it will just look wrong.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   1. The variables.

   ⚠️ Declared on .wpforms-container, NOT :root. WPForms declares all 52 of its
   properties on :root in an inline <style> printed in the BODY — after ra.css —
   so a :root block here loses on source order. A nearer declaring ancestor wins
   regardless of order, and .wpforms-container is nearer. (The per-form
   `#wpforms-NNNNN {}` blocks would shadow this at (1,0,0), but they are emitted
   EMPTY on all four forms, checked.)

   ⚠️ --wpforms-button-background-color is NOT just the button. It also paints
   every input's :focus border and box-shadow. An earlier version of this file
   set it to --red-hover to darken the button on hover, which quietly gave every
   field in the section a red focus ring instead of the design's green underline.
   The button reads `var(--…-alt, var(--…))` — a fallback chain, not a pair — so
   with -alt set the non-alt one is free to be what the fields need.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container,
body.ra-landing  div.wpforms-container {
  /* The field fill. Deliberately close to white — --ra-base-2 (#f5f7f5) was the
     obvious choice and is only 1.077:1 against white, which is why the design's
     own light band reads as no band at all. This is green-tinted so it belongs
     to the palette rather than looking like a browser default. */
  --ra-field: #EDF1EC;
  --ra-field-focus: #E6EDE4;

  /* fields */
  --wpforms-field-border-color: var(--ra-base);
  --wpforms-field-border-size: 1px;
  --wpforms-field-border-style: solid;
  --wpforms-field-border-radius: 0px;
  --wpforms-field-background-color: transparent;
  --wpforms-field-text-color: var(--ra-contrast);
  --wpforms-field-menu-color: #ffffff;          /* the country list stays readable */
  --wpforms-field-size-font-size: 16px;
  --wpforms-field-size-line-height: 21px;

  /* labels */
  --wpforms-label-color: var(--ra-contrast);
  --wpforms-label-size-font-size: 12px;
  --wpforms-label-size-line-height: 15px;
  --wpforms-label-sublabel-color: var(--muted);
  --wpforms-label-size-sublabel-font-size: 12px;
  --wpforms-label-size-sublabel-line-height: 16px;
  --wpforms-label-error-color: var(--red);

  /* the button */
  --wpforms-button-background-color-alt: var(--red);   /* rest AND hover */
  --wpforms-button-background-color: var(--rural);     /* the FIELD focus ring */
  --wpforms-button-text-color: #ffffff;
  --wpforms-button-border-radius: 5px;

  --wpforms-container-padding: 0px;
}

/* ---------------------------------------------------------------------------
   2. Rhythm. The design lays a card form out as a two-column grid.

   Fields span BOTH columns by default and only the two short ones opt into a
   half. That way round on purpose: if George adds a field later it comes out
   full width, which is always safe. Opting in by field TYPE rather than by
   position means it also cannot drift when fields are reordered.

   The anti-spam decoys are children of this container too, and they share the
   exact classes of real fields — but WPForms pins them with inline
   `position:absolute !important; height:1px !important; overflow:hidden
   !important; z-index:-1000 !important`, so they take no part in the grid and
   nothing here can widen one into view. Checked, because getting that wrong
   would put a honeypot on screen.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .wpforms-field-container,
body.ra-landing  div.wpforms-container .wpforms-field-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px 20px;
}

body.ra-property div.wpforms-container .wpforms-field,
body.ra-landing  div.wpforms-container .wpforms-field {
  grid-column: 1 / -1;
  padding: 0;            /* WPForms' own 15px 0, which made a 30px gap */
}

body.ra-property div.wpforms-container .wpforms-field-name,
body.ra-property div.wpforms-container .wpforms-field-phone,
body.ra-landing  div.wpforms-container .wpforms-field-name,
body.ra-landing  div.wpforms-container .wpforms-field-phone {
  grid-column: span 1;
}

/* The property reference. It must submit, and a hidden input submits whatever
   CSS says, but as a grid item it would otherwise open an 18px hole. */
body.ra-property div.wpforms-container .wpforms-field-hidden,
body.ra-landing  div.wpforms-container .wpforms-field-hidden {
  display: none;
}

/* Under the design's own breakpoint the grid collapses, exactly as .form-grid
   does at pbs.css:223. */
@media (max-width: 900px) {
  body.ra-property div.wpforms-container .wpforms-field-container,
  body.ra-landing  div.wpforms-container .wpforms-field-container {
    grid-template-columns: 1fr;
  }
  body.ra-property div.wpforms-container .wpforms-field-name,
  body.ra-property div.wpforms-container .wpforms-field-phone,
  body.ra-landing  div.wpforms-container .wpforms-field-name,
  body.ra-landing  div.wpforms-container .wpforms-field-phone {
    grid-column: 1 / -1;
  }
}

/* The gate modal is a single column at 16px, not a grid — the design sets its
   own rhythm there and the panel is only 520px wide. ra.css:1708 makes the form
   a flex column, which with WPForms' DOM puts a 16px gap around the zero-height
   reCAPTCHA container as well; block display hands the spacing back to the
   rules above. */
body.ra-property .modal form.wpforms-form {
  display: block;
}
body.ra-property .modal div.wpforms-container .wpforms-field-container {
  grid-template-columns: 1fr;
  gap: 16px;
}
body.ra-property .modal div.wpforms-container .wpforms-field-name,
body.ra-property .modal div.wpforms-container .wpforms-field-phone {
  grid-column: 1 / -1;
}

/* ---------------------------------------------------------------------------
   3. Labels.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .wpforms-field .wpforms-field-label,
body.ra-landing  div.wpforms-container .wpforms-field .wpforms-field-label {
  display: block;
  margin: 0 0 2px;
  font: 600 12px/1.25 'Be Vietnam Pro', sans-serif;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ra-contrast);
}

/* The design has no required marker at all — it marks the INVERSE, an
   "(optional)" suffix on the few fields that are. WPForms marks required with
   an asterisk and there is no way to invert that without editing every form, so
   the asterisk stays (removing it would leave nothing at all indicating a
   required field) but it is quietened to the design's muted tone rather than
   sitting at label weight. */
body.ra-property div.wpforms-container .wpforms-required-label,
body.ra-landing  div.wpforms-container .wpforms-required-label {
  color: var(--muted);
  font-weight: 400;
  border: 0;
}

/* Sublabels and descriptions — the design's "(optional)" treatment. */
body.ra-property div.wpforms-container .wpforms-field-description,
body.ra-property div.wpforms-container .wpforms-field-sublabel,
body.ra-landing  div.wpforms-container .wpforms-field-description,
body.ra-landing  div.wpforms-container .wpforms-field-sublabel {
  margin: 4px 0 0;
  font: 400 12px/1.35 'Be Vietnam Pro', sans-serif;
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
}

/* ---------------------------------------------------------------------------
   4. The fields themselves: the ruled treatment.

   ⚠️ max-width. WPForms caps a "medium" field at 60% — and the 100% override
   that looks like it fixes that lives inside `@media (max-width: 600px)`, so it
   only applies on a phone. Four of the eight fields on the landing form are
   medium, which rendered as underlines stopping 60% of the way across the card.
   Measured, not assumed: 262px against 436px.

   ⚠️ The phone field's 53px left indent is an INLINE style written by
   intl-tel-input at runtime to clear its flag button. Inline wins the longhand,
   so the `padding: 10px 0` shorthand below leaves it alone — which is what we
   want, and is why there is no phone-specific padding rule here.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .wpforms-field input,
body.ra-property div.wpforms-container .wpforms-field textarea,
body.ra-landing  div.wpforms-container .wpforms-field input,
body.ra-landing  div.wpforms-container .wpforms-field textarea {
  width: 100%;
  max-width: 100%;
  height: auto;
  border: 0;
  border-bottom: 1px solid var(--ra-base);
  border-radius: 0;
  padding: 10px 12px;
  /* ⚠️ A FILL, not transparent. The approved design made fields ruled and
     flush-left, which is elegant and — the client's words — "arent obvious
     enough where the input is". A rule alone reads as a divider; a filled box
     reads as somewhere to type. The rule stays, so the design language does too.
     The 12px horizontal padding is the cost: the value no longer sits flush
     with its label. Worth it. */
  background: var(--ra-field);
  color: var(--ra-contrast);
  font: 400 16px/1.3 'Be Vietnam Pro', sans-serif;
  box-shadow: none;
  transition: border-color .18s ease, padding-bottom .18s ease;
}

/* The textarea ships with BOTH a 43px min-height and a hard 97.17px height, and
   14px of padding on all four sides where an input gets it horizontally only. */
body.ra-property div.wpforms-container .wpforms-field textarea,
body.ra-landing  div.wpforms-container .wpforms-field textarea {
  min-height: 84px;
  resize: vertical;
}

body.ra-property div.wpforms-container .wpforms-field input::placeholder,
body.ra-property div.wpforms-container .wpforms-field textarea::placeholder,
body.ra-landing  div.wpforms-container .wpforms-field input::placeholder,
body.ra-landing  div.wpforms-container .wpforms-field textarea::placeholder {
  color: var(--muted);
  opacity: 1;
}

/* ---------------------------------------------------------------------------
   5. Focus. The underline thickens and nothing moves.

   ⚠️ `:focus:invalid` is matched explicitly. :invalid is a NATIVE pseudo-class
   that fires the instant an empty required field is focused, before any script
   runs, and WPForms styles it at (0,4,2) with a coloured box-shadow ring. A
   focus override written against `:focus` alone is outranked by it, and the ring
   comes back on the Name and Email fields the moment they are tabbed into.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .wpforms-field input:focus,
body.ra-property div.wpforms-container .wpforms-field textarea:focus,
body.ra-property div.wpforms-container .wpforms-field input:focus:invalid,
body.ra-property div.wpforms-container .wpforms-field textarea:focus:invalid,
body.ra-landing  div.wpforms-container .wpforms-field input:focus,
body.ra-landing  div.wpforms-container .wpforms-field textarea:focus,
body.ra-landing  div.wpforms-container .wpforms-field input:focus:invalid,
body.ra-landing  div.wpforms-container .wpforms-field textarea:focus:invalid {
  border: 0;
  border-bottom: 2px solid var(--rural);
  border-radius: 0;
  padding-bottom: 9px;
  /* ⚠️ Keeps the fill. This used to re-declare transparent, so the fill would
     have disappeared at the exact moment someone started typing — a worse bug
     than the one being fixed. */
  background: var(--ra-field-focus);
  box-shadow: none;
  outline: none;
}

/* ---------------------------------------------------------------------------
   6. Errors.

   WPForms paints an error with the `border` SHORTHAND and a hard-coded #d63637,
   so it resets all four sides — an override that sets only border-bottom would
   leave the other three painted red.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .wpforms-field input.wpforms-error,
body.ra-property div.wpforms-container .wpforms-field textarea.wpforms-error,
body.ra-landing  div.wpforms-container .wpforms-field input.wpforms-error,
body.ra-landing  div.wpforms-container .wpforms-field textarea.wpforms-error {
  border: 0;
  border-bottom: 2px solid var(--red);
  padding-bottom: 9px;
}

body.ra-property div.wpforms-container .wpforms-field label.wpforms-error,
body.ra-property div.wpforms-container .wpforms-field em.wpforms-error,
body.ra-landing  div.wpforms-container .wpforms-field label.wpforms-error,
body.ra-landing  div.wpforms-container .wpforms-field em.wpforms-error {
  display: block;
  min-width: 0;
  margin: 4px 0 0;
  font: 400 12px/1.35 'Be Vietnam Pro', sans-serif;
  font-style: normal;
  text-transform: none;
  letter-spacing: 0;
  color: var(--red);
}

/* ---------------------------------------------------------------------------
   7. The phone field's country button.

   It carries its own focus ring from the same variable as the inputs, so a
   focus override written only against input and textarea leaves a ring on the
   flag button on three of the four forms.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .iti__selected-country,
body.ra-landing  div.wpforms-container .iti__selected-country {
  background: transparent;
  border: 0;
  border-radius: 0;
}

body.ra-property div.wpforms-container .iti__selected-country:focus,
body.ra-landing  div.wpforms-container .iti__selected-country:focus {
  border: 0;
  box-shadow: none;
  outline: 2px solid var(--rural);
  outline-offset: -2px;
}

/* The dropdown is flexible-width by configuration, so it is free to overflow
   the 40px card padding. Cap it to the field. */
body.ra-property div.wpforms-container .iti__dropdown-content,
body.ra-landing  div.wpforms-container .iti__dropdown-content {
  max-width: 100%;
  border-radius: 4px;
  box-shadow: 0 10px 30px rgba(0,0,0,.18);
}

/* ---------------------------------------------------------------------------
   8. The submit button.

   Matched to .btn / .btn--solid rather than approximated, so if the design's
   button changes this follows it. The colour is the variable above; a plain
   background declaration here loses to WPForms' own rule, measured.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .wpforms-submit-container,
body.ra-landing  div.wpforms-container .wpforms-submit-container {
  margin: 18px 0 0;
  padding: 0;
}

body.ra-property div.wpforms-container button.wpforms-submit,
body.ra-landing  div.wpforms-container button.wpforms-submit {
  display: inline-block;
  min-height: 44px;              /* WPForms ships 41px, under the touch floor */
  font: 600 13px 'Be Vietnam Pro', sans-serif;
  text-transform: uppercase;
  letter-spacing: .06em;
  text-decoration: none;
  border-radius: 5px;
  padding: 15px 22px;
  border: 1px solid #fff;
  cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease, box-shadow .22s ease;
}

body.ra-property div.wpforms-container button.wpforms-submit:hover,
body.ra-landing  div.wpforms-container button.wpforms-submit:hover {
  box-shadow: 0 6px 18px rgba(193,33,43,.28);
}

body.ra-property div.wpforms-container button.wpforms-submit:focus-visible,
body.ra-landing  div.wpforms-container button.wpforms-submit:focus-visible {
  outline: 2px solid var(--ra-contrast);
  outline-offset: 2px;
}

/* On the dark appraisal band the white 1px border is the button's own edge and
   must stay; inside a white form card it would disappear into the card. */
body.ra-landing .form-card div.wpforms-container button.wpforms-submit,
body.ra-property .form-card div.wpforms-container button.wpforms-submit {
  border-color: var(--red);
}

/* In the gate modal the design's button is full width. */
body.ra-property .modal div.wpforms-container button.wpforms-submit {
  width: 100%;
  text-align: center;
}

/* ---------------------------------------------------------------------------
   9. The success message.

   All four forms submit by AJAX with a message confirmation, so on success the
   whole form is REPLACED in place by this container — including inside the gate
   modal, where it takes over the approved success panel. It has no design
   equivalent and no variable behind its hard-coded #333.
   --------------------------------------------------------------------------- */
body.ra-property div.wpforms-container .wpforms-confirmation-container-full,
body.ra-landing  div.wpforms-container .wpforms-confirmation-container-full {
  margin: 0;
  padding: 22px 24px;
  background: var(--ra-base-2);
  border: 1px solid var(--ra-base);
  border-left: 3px solid var(--rural);
  border-radius: 5px;
  color: var(--ra-contrast);
  font: 400 16px/1.5 'Be Vietnam Pro', sans-serif;
}

body.ra-property div.wpforms-container .wpforms-confirmation-container-full p,
body.ra-landing  div.wpforms-container .wpforms-confirmation-container-full p {
  margin: 0;
  color: inherit;
}

/* ---------------------------------------------------------------------------
   10. The phone.

   ⚠️ This sits at the END of the file on purpose. A @media block does not
   raise specificity, so a mobile rule placed ABOVE the desktop rule it means to
   override loses to it on source order. An earlier draft put this in the media
   query up at section 2 and the button's `display` and `padding` were silently
   taken back by the base rule in section 8 — only `width` survived, because
   that happened to be the one property the base rule does not set. Measured.
   --------------------------------------------------------------------------- */
@media (max-width: 900px) {
  /* "A button on a phone is a full-width target, not a word with a box round
     it" — pbs.css:219. The design applies that to .btn; WPForms' submit is not
     a .btn, so it has to be said again or it is the one button in the section
     that stays a small word on a phone. */
  body.ra-property div.wpforms-container button.wpforms-submit,
  body.ra-landing  div.wpforms-container button.wpforms-submit {
    display: block;
    width: 100%;
    text-align: center;
    padding: 15px 20px;
  }
}

/* ---------------------------------------------------------------------------
   11. A property tile with no photograph yet.

   WordPress-only, which is why it lives here rather than in the design source:
   the static preview always had a photograph, real content does not. George can
   publish a property before the photographer has been, and on a page headed
   "For sale now" an empty grey box reads as a broken image rather than as work
   in progress. The property page has always had this state; the tile had not.
   --------------------------------------------------------------------------- */
/* ⚠️ `.property a.shot { display:block }` in the design is ALSO (0,2,1), and
   this partial is concatenated FIRST, so a tie goes to the design and the flex
   centring silently did nothing. Measured. Match the design's own shape and add
   a class to clear it. */
body.ra-landing .property a.shot--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ra-base-2);
  border: 1px solid var(--ra-base);
}

body.ra-landing .property .shot__pending {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 24px;
  text-align: center;
}

body.ra-landing .property .shot__pending img {
  width: 64px;
  height: 64px;
  opacity: .5;
  /* the tile's own img rule stretches a photograph to fill; this is a mark */
  object-fit: contain;
  position: static;
}

body.ra-landing .property .shot__pending span {
  font: 600 11px 'Be Vietnam Pro', sans-serif;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--muted);
}

/* ---------- 1. SHARED BASE ------------------------------------------------ */
/* PBS Rural Assets preview
   Brand values read off premiumbovinesolutions.com on 18 Sep 2026.
   Anything not sourced from the live site is marked in the comment beside it. */

:root {
  --ra-contrast: #141414;      /* body text */
  --ra-accent: #000000;        /* header bar */
  --ra-base-3: #ffffff;        /* page background */
  --ra-base-2: #f5f7f5;        /* light band */
  --ra-base: #e3e6e3;          /* borders */
  --red: #c1212b;           /* PBS red, the Auctions pill and every solid CTA */
  --red-deep: #6b0014;
  --red-hover: #a91c25;     /* darkened from --red for hover, not on the live site */
  --gold: #bd852f;          /* Bulls for Sale */
  --purple: #424798;        /* Lots for Sale */
  --green: #599900;         /* Genetics for Sale */
  --rural: #3B6F2A;         /* Rural Assets. "Pasture", hsl(105 45% 30%). George asked for green,
                               near the Genetics green. Hue is 20 deg off #599900 so it reads as the
                               same family; relative luminance is exactly half, which is what keeps
                               the two apart in the pill row. 6.01:1 on white. */
  --rural-ink: #0D1A09;     /* --rural driven to near-black, same hue. The ground under every dark
                               zone, and the tint inside every veil. Black deletes the green that is
                               already in the photograph; this disappears into it. */
  --rural-paper: #ECF1EA;   /* the light "photography pending" panel */
  --rural-lift: #A5BF9B;    /* type on DARK grounds only. 2.0:1 on white, so never on a light one. */
  --rural-bar: #AEC1A3;     /* rainfall chart, the non-peak bars */
  --ink-body: #484E46;      /* replaces three hardcoded #4a4a4a body greys */
  --muted: #595959;
  --wrap: 1200px;           /* --gb-container-width on the live site */
}

* { box-sizing: border-box; }

/* In-page links glide rather than teleport. scroll-margin keeps the target
   clear of anything sitting at the top of the viewport instead of landing the
   heading flush against it. */
html { scroll-behavior: smooth; }
[id] { scroll-margin-top: 28px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* The browser's own [hidden] rule is display:none at the lowest specificity, so
   any class that sets a display value silently defeats it. The gallery's
   prev/next buttons stayed on screen over the photography-pending panel for
   exactly this reason. One reset, rather than remembering it per component. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--ra-base-3);
  color: var(--ra-contrast);
  font: 400 17px/1.55 'Be Vietnam Pro', sans-serif;
}

h1, h2, h3 { font-family: 'Outfit', sans-serif; font-weight: 700; margin: 0; }
h2 { font-size: 32px; text-transform: uppercase; line-height: 1.1; }
h3 { font-size: 20px; }
p { margin: 0 0 1em; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 40px; }
.band { background: var(--ra-base-2); }
section { padding: 88px 0; }

/* Section labels. Grey #595959 sat too close to body text to read as a label.
   Slate is the Rural Assets colour, so labels tie to the section without
   competing with the red reserved for calls to action. */
.eyebrow {
  font: 600 12px 'Be Vietnam Pro', sans-serif;
  text-transform: uppercase;
  letter-spacing: .18em;
  color: var(--rural);
  margin-bottom: 14px;
}

/* Buttons, exactly as the live site renders them */
.btn {
  display: inline-block;
  font: 600 13px 'Be Vietnam Pro', sans-serif;
  text-transform: uppercase;
  letter-spacing: .06em;
  text-decoration: none;
  border-radius: 5px;
  padding: 15px 38px;
  cursor: pointer;
  transition: background .15s ease, transform .15s ease;
}
.btn--solid { background: var(--red); color: #fff; border: 1px solid #fff; }
.btn--solid:hover, .btn--solid:focus, .btn--solid:active { background: var(--red-hover);
  color: #fff;
}
.btn--outline {
  background: transparent;
  color: var(--red);
  border: 1px solid var(--red);
}
.btn--outline:hover { background: var(--red); color: #fff; }
.pill { border-radius: 5px; padding: 5px 15px; color: #fff !important; }
.pill--gold { background: var(--gold); }
.pill--purple { background: var(--purple); }
.pill--green { background: var(--green); }
.pill--red { background: var(--red); }
.pill--rural { background: var(--rural); }

/* Placeholders, deliberately visible. A preview must not look more finished
   than it is: every unconfirmed value reads as unconfirmed. */
.tbc {
  font: 400 13px ui-monospace, Menlo, monospace;
  color: var(--muted);
  background: rgba(0,0,0,.045);
  border: 1px dashed #c4c8c4;
  border-radius: 3px;
  padding: 1px 6px;
  font-style: normal;
}
.slot {
  background: repeating-linear-gradient(135deg, #1F2D1B 0 14px, #27381F 14px 28px);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font: 400 12px ui-monospace, Menlo, monospace;
  letter-spacing: .04em;
  padding: 16px;
}

/* Forms */
label { display: flex; flex-direction: column; gap: 6px; font: 600 12px 'Be Vietnam Pro', sans-serif; text-transform: uppercase; letter-spacing: .08em; }
input, textarea, select {
  font: 400 16px 'Be Vietnam Pro', sans-serif;
  padding: 12px 14px;
  border: 1px solid var(--ra-base);
  border-radius: 5px;
  color: var(--ra-contrast);
  outline: none;
  background: #fff;
}
/* The focus ring is the underline, never a box. outline:none on the bare element
   selector is too weak to hold: any :focus or :focus-visible rule, including the
   browser's own, outranks (0,0,1) and draws a rectangle round the field. */
input:focus, textarea:focus, select:focus,
input:focus-visible, textarea:focus-visible, select:focus-visible { outline: none; }
input:focus, textarea:focus, select:focus { border-color: var(--rural); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 20px; }
.form-grid .full { grid-column: 1 / -1; }

/* George's disclaimer, 19 Sep: "we will have to have a disclaimer to proteck us
   from what we promote here". Quiet but legible -- a disclaimer nobody can read
   is not a disclaimer. Sits on the light ground above the black footer. */
.disclaimer { background: var(--ra-base-2); border-top: 1px solid var(--ra-base); padding: 34px 0 38px; }
.disclaimer p {
  max-width: 900px; margin: 0;
  font-size: 12.5px; line-height: 1.65; color: var(--muted);
}

/* Tablet gap. The nav carries three text links plus five pills and a 330px
   logo, which needs about 1180px. Below that and above the mobile breakpoint
   it overflowed the header and the pills sat on top of the logo. */
@media (max-width: 1180px) and (min-width: 1025px) {
  .pill { padding: 5px 9px; }
}

/* The eight-item nav measures about 707px and the wordmark 235px, so the header
   needs roughly 1010px before the two have any air between them. Below that the
   menu collapses. This is its own breakpoint: the phone rules at 900 are about
   touch targets and stacking, which is a different question. */
@media (max-width: 1024px) {
}

@media (max-width: 900px) {
  .wrap { padding: 0 16px; }

  /* A button on a phone is a full-width target, not a word with a box round it. */
  .btn { display: block; width: 100%; text-align: center; padding: 15px 20px; }
  section { padding: 56px 0; }
  h2 { font-size: 26px; }
  .form-grid { grid-template-columns: 1fr; }
}



/* The one dark section, used for the moment the page asks for something.
   A contour texture was tried here and removed: too fussy, and horizontal
   lines fought the horizon in the photography. If texture comes back it
   wants to be angled. */
.ink { background: var(--rural-ink); color: #fff; --muted: #B7C6AE; }
.ink h1, .ink h2, .ink h3 { color: #fff; }
.ink .eyebrow { color: var(--rural-lift); }
/* A white card inside the dark section must not inherit the section's white
   text. Every field label in the appraisal form was white on white, visible
   only because the "(optional)" span carried an inline colour. */
.ink .form-card { color: var(--ra-contrast); }
.ink .form-card label { color: var(--ra-contrast); }
/* ...and it must not inherit the section's --muted either. Redefining --muted
   above fixes the agent line on the dark ground (2.45:1 -> 9.85:1), but custom
   properties inherit, so the "(optional)" span on the WHITE card inside this
   section would have followed it to 1.79:1 and vanished. Resetting `color`
   does not cover this: the span sets its own colour FROM the property. */
.ink .form-card { --muted: #595959; }

/* The agent block appears on the dark ground too (the appraisal band). Its text
   colours already resolve -- .who inherits #fff, .num rides the --muted that .ink
   redefines to #B7C6AE, .contact is color:inherit. Its two HAIRLINES do not: both
   are specified in black and are invisible-to-wrong once the ground goes dark.
   .agent-mini's rule is var(--ra-base) #e3e6e3, which on near-black reads as a
   bright line rather than a divider; .agent-face's is rgba(0,0,0,.08), which
   disappears and lets the circular crop bleed into the photograph behind it. */
.ink .agent-mini { border-top-color: rgba(255,255,255,.22); }
.ink .agent-face { box-shadow: 0 0 0 1px rgba(255,255,255,.22); }

.ink .btn--outline { color: #fff; border-color: rgba(255,255,255,.55); }
.ink .btn--outline:hover { background: #fff; color: var(--rural-ink); border-color: #fff; }
.ink ::selection { background: var(--rural-lift); color: var(--rural-ink); }

/* ===========================================================================
   Craft pass.

   The things below are the difference between "laid out" and "designed".
   None of them are decoration: each fixes something the browser does badly
   by default, or something a reader notices without being able to name.
   =========================================================================== */

/* --- Typography -------------------------------------------------------- */

/* Outfit at display sizes sets too loose. Large type needs negative tracking
   or the letters drift apart; small caps type needs positive or it closes up.
   The browser applies neither. */
h1 { letter-spacing: -0.022em; }
h2 { letter-spacing: -0.012em; }
h1, h2, h3 { text-wrap: balance; }        /* no single-word last line */
p  { text-wrap: pretty; }                 /* no orphans */

/* Every figure on these pages is a measurement sitting in a column beside
   another measurement. Proportional numerals make those columns ragged. */
.facts dd, .stat, .im-list, table { font-variant-numeric: tabular-nums; }

/* A unit is not part of the number. Setting it at the same weight makes
   "2,809 ha" read as one long token instead of a quantity and its unit. */
.u { font-size: .82em; color: var(--muted); font-weight: 400; letter-spacing: .01em; }

/* --- Selection and focus ----------------------------------------------- */

::selection { background: var(--rural); color: #fff; }

/* One focus treatment, visible on light and dark, rather than the browser's
   default which disappears against the red buttons. */
:focus-visible { outline: 2px solid var(--rural); outline-offset: 3px; border-radius: 2px; }
.ink :focus-visible, .gal :focus-visible, .hero :focus-visible { outline-color: #fff; }

/* --- Buttons ------------------------------------------------------------ */

/* One size for both variants. The live site sets solid at 12px and outline at
   14px; two fills of the same control should not be two type sizes, so
   .btn--outline now sets colour only and .btn supplies every metric. */

/* Icons carry meaning or they do not appear:
     .btn--go   moves the reader, to a page or an anchor
     .btn--get  pulls a document
     a submit button gets neither, because its label already says what it does.
   Masked SVG rather than a text glyph, so it inherits currentColor, scales with
   the type and renders the same on every platform. */
.btn--go::after,
.btn--get::after {
  content: ''; display: inline-block; vertical-align: -0.09em;
  width: 1.05em; height: 1.05em; margin-left: .6em;
  background: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
  transform: translateX(-2px); opacity: .8;
  transition: transform .22s cubic-bezier(.2,.7,.3,1), opacity .22s ease;
}
.btn--go::after  { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2012h14M12.5%205.5%2019%2012l-6.5%206.5%27%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2012h14M12.5%205.5%2019%2012l-6.5%206.5%27%2F%3E%3C%2Fsvg%3E"); }
.btn--get::after { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203.5v11M7.5%2010.5%2012%2015l4.5-4.5M4.5%2019.5h15%27%2F%3E%3C%2Fsvg%3E");  mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%272.2%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203.5v11M7.5%2010.5%2012%2015l4.5-4.5M4.5%2019.5h15%27%2F%3E%3C%2Fsvg%3E"); transform: translateY(-1px); }
.btn--go:hover::after  { transform: translateX(2px); opacity: 1; }
.btn--get:hover::after { transform: translateY(1px); opacity: 1; }

.btn { transition: background .18s ease, color .18s ease, border-color .18s ease, box-shadow .22s ease; }
.btn--solid:hover, .btn--solid:focus, .btn--solid:active { box-shadow: 0 6px 18px rgba(193,33,43,.28);
  color: #fff;
}

/* --- Rural Assets lockup ---------------------------------------------------
   The circular PBS badge is never redrawn, recoloured or added to. Only its two
   existing colourways are used: ink on light, white on dark.

   ⚠️ The badge carries "PREMIUM BOVINE" and "SOLUTIONS" arched around its rim.
   Below about 44px that type collapses into a smudge, so .lockup--sm drops the
   badge and lets the wordmark carry the mark. Never scale the badge to fit.

   .lockup          badge · rule · RURAL ASSETS · attribution   (the full mark)
   .lockup--stacked badge above, wordmark and attribution centred under
   .lockup--sm      wordmark only, for anything under about 44px
   --------------------------------------------------------------------------- */
.lockup { display: inline-flex; align-items: center; color: inherit; }
.lockup img { display: block; flex: none; width: 54px; height: 54px; }
.lockup__rule { width: 1px; align-self: stretch; background: currentColor; opacity: .22; margin: 0 16px; }
.lockup__text { display: flex; flex-direction: column; }
.lockup__wm { font: 700 19px/1 'Outfit', sans-serif; text-transform: uppercase; letter-spacing: .06em; }
.lockup__by {
  font: 400 9.5px/1.3 'Be Vietnam Pro', sans-serif; font-variant: small-caps;
  letter-spacing: .09em; opacity: .78;
}
.lockup__wm + .lockup__by { margin-top: 6px; }

.lockup--stacked { flex-direction: column; text-align: center; }
.lockup--stacked img { width: 62px; height: 62px; }
.lockup--stacked .lockup__rule { width: 28px; height: 1px; align-self: center; margin: 14px 0; }
.lockup--stacked .lockup__text { align-items: center; }

/* George, 19 Sep: "Can we have rural assets on the top and the proudly line
   below". The wordmark and attribution sit inside .lockup__text, so straddling
   the badge means promoting them to flex items rather than restructuring the
   markup -- one markup shape has to serve every variant, because this becomes a
   single component on the live site. */
.lockup--crest, .lockup--over { flex-direction: column; align-items: center; text-align: center; }
.lockup--crest .lockup__text, .lockup--over .lockup__text { display: contents; }
.lockup--crest .lockup__rule, .lockup--over .lockup__rule { display: none; }

/* wordmark · badge · attribution */
.lockup--crest .lockup__wm  { order: 1; font-size: 22px; letter-spacing: .08em; }
.lockup--crest img          { order: 2; width: 62px; height: 62px; margin: 14px 0 11px; }
.lockup--crest .lockup__by  { order: 3; margin-top: 0; }

/* wordmark · attribution · badge */
.lockup--over .lockup__wm  { order: 1; font-size: 22px; letter-spacing: .08em; }
.lockup--over .lockup__by  { order: 2; margin-top: 7px; }
.lockup--over img          { order: 3; width: 62px; height: 62px; margin-top: 16px; }

@media (max-width: 900px) {
  .lockup--crest .lockup__wm, .lockup--over .lockup__wm { font-size: 19px; }
  .lockup--crest img, .lockup--over img { width: 54px; height: 54px; }
}

.lockup--sm img, .lockup--sm .lockup__rule { display: none; }
.lockup--sm .lockup__wm { font-size: 12px; letter-spacing: .1em; }
.lockup--sm .lockup__by { display: none; }

@media (max-width: 900px) {
  .lockup img { width: 46px; height: 46px; }
  .lockup__rule { margin: 0 13px; }
  .lockup__wm { font-size: 17px; }
}

/* --- Underlined form fields ------------------------------------------------
   A boxed input per line is the default everywhere; a ruled line reads as a
   form you fill in rather than a widget you operate.

   ⚠️ Do NOT reach for box-shadow to thicken the rule on focus. A shadow paints
   the element's whole border-box silhouette, and these fields are transparent,
   so the entire shadow rectangle shows through as a box around the input. The
   border itself thickens instead, with the pixel taken back off padding-bottom
   so nothing moves. */
.form-card input, .form-card textarea,
.modal input:not([readonly]), .modal textarea {
  border: 0; border-bottom: 1px solid var(--ra-base); border-radius: 0;
  padding: 10px 12px; background: #EDF1EC;   /* a fill, so it reads as somewhere to type */
  transition: border-color .18s ease, padding-bottom .18s ease;
}
.form-card input:focus, .form-card textarea:focus,
.modal input:focus, .modal textarea:focus,
.form-card input:focus-visible, .form-card textarea:focus-visible,
.modal input:focus-visible, .modal textarea:focus-visible {
  border-bottom: 2px solid var(--rural);
  padding-bottom: 9px;
  outline: none;
}

/* --- Agent ---------------------------------------------------------------- */
/* One block, used on the property template and on each landing tile. */
.agent-mini {
  margin-top: 28px; padding-top: 22px; border-top: 1px solid var(--ra-base);
}
/* A listing can carry more than one agent -- the post type already has six
   agent checkboxes -- so this is a list of one-or-more, not a pair. The
   eyebrow is the only thing that knows the count. */
.agent-row { display: flex; align-items: center; gap: 14px; }
.agent-row + .agent-row { margin-top: 14px; }
.agent-mini .who { font: 700 17px 'Outfit', sans-serif; }
.agent-mini .num { font-size: 15px; color: var(--muted); margin-top: 1px; }
.agent-face {
  width: 54px; height: 54px; flex: none; border-radius: 50%; object-fit: cover;
  background: var(--ra-base); box-shadow: 0 0 0 1px rgba(0,0,0,.08);
}
@media (max-width: 560px) {
  .agent-face { width: 46px; height: 46px; }
}

/* --- Status --------------------------------------------------------------*/

/* A plain black rectangle reads as a system label. A dot plus a hairline
   reads as a status, which is what it is. */
.status {
  position: absolute; top: 16px; left: 16px; z-index: 2;
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(13,26,9,.72); backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.22);
  color: #fff; border-radius: 40px; padding: 7px 14px 7px 11px;
  font: 600 10px 'Be Vietnam Pro', sans-serif; text-transform: uppercase; letter-spacing: .14em;
}
.status { --dot: #7ac143; }
.status--offer { --dot: #e8a33d; }
.status--sold  { --dot: var(--red); }
.status::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--dot);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--dot) 25%, transparent);
}

/* The ring is a second dot laid over the first and scaled outwards. Animating
   transform and opacity keeps it off the paint path, which a growing
   box-shadow would not. .status is already positioned, and an absolutely
   positioned ::after leaves the flex row alone, so the label does not move.
   Left offset matches the 11px padding that sets the dot's own position. */
.status::after {
  content: ''; position: absolute; left: 11px; top: 50%;
  width: 6px; height: 6px; margin-top: -3px; border-radius: 50%;
  background: var(--dot); pointer-events: none;
  animation: status-pulse 2s cubic-bezier(.22,.61,.36,1) infinite;
}
/* Sold is not a live state, so it does not pulse. */
.status--sold::after { animation: none; opacity: 0; }

@keyframes status-pulse {
  0%   { transform: scale(1);   opacity: .6; }
  70%  { transform: scale(3.4); opacity: 0; }
  100% { transform: scale(3.4); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .status::after { animation: none; opacity: 0; }
  .btn--solid::after, .btn--outline::after { transition: none; }
}

.contact { color: inherit; text-decoration: none; border-bottom: 1px solid currentColor; border-bottom-color: color-mix(in srgb, currentColor 35%, transparent); }
.contact:hover { border-bottom-color: currentColor; }


/* ---------- 2. LANDING PAGE ---------------------------------------------- */

/* Field spacing for these two contexts; the underline itself is in pbs.css. */
.form-card label, .modal label { gap: 2px; }
.form-card ::placeholder, .modal ::placeholder { color: #a8adb1; }
.form-card { padding: 34px 38px; }

/* Page-specific. Shared rules live in pbs.css. */
.hero { position: relative; min-height: 620px; display: flex; align-items: center; background: var(--rural-ink); overflow: hidden; }
.hero .inner { width: 100%; }                 /* fill the grid, do not shrink to fit */
.hero .measure { max-width: 620px; }          /* text stops here; country fills the rest */
.hero img.bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 55%; }
.hero .scrim {
  position: absolute; inset: 0;
  background:
    /* a low warm ember where the old black bar sat. Light inside the
       photograph, never a type or fill colour: at swatch size this hue is
       --gold, which means Bulls for Sale. */
    radial-gradient(80% 55% at 26% 106%, rgba(94,58,12,.20) 0%, rgba(94,58,12,0) 100%),
    /* Stops are in px off the centre line, not percentages. .wrap is
       max-width:1200px and .measure is 620px, so the text column's right edge
       is a fixed offset from centre; percentage stops drift and break at 1280
       and 1366. Below 1200 the first stop clamps to 0, which is correct.
       The fall is deliberately spread far wider than the text column: at 160px
       it read as a curtain edge down the middle of the photograph. Legibility
       is carried by text-shadow below, not by this. */
    linear-gradient(90deg,
      rgba(13,26,9,.38) 0,
      rgba(13,26,9,.30) calc(50% - 280px),
      rgba(13,26,9,.10) calc(50% + 340px),
      rgba(13,26,9,.02) 100%),
    linear-gradient(180deg,
      rgba(13,26,9,.14) 0%, rgba(13,26,9,.02) 30%,
      rgba(13,26,9,0)   62%, rgba(13,26,9,.06) 100%);
}
/* Keeps .wrap's horizontal padding. Setting `padding: 96px 0` here would win on
   specificity and push the hero text flush to the screen edge on a phone. */
.hero .inner { position: relative; color: #fff; padding-top: 96px; padding-bottom: 96px; text-shadow: 0 1px 2px rgba(9,18,6,.62), 0 2px 14px rgba(9,18,6,.55); }
.hero .lockup { margin-bottom: 28px; }
.hero .lockup__by { opacity: 1; }   /* pbs.css sets .78; at 9.5px that measured 3.39:1 */
.hero h1 { font-size: 56px; line-height: 1.02; text-transform: uppercase; letter-spacing: .01em;
           text-shadow: 0 1px 2px rgba(9,18,6,.55), 0 3px 22px rgba(9,18,6,.60); }
.hero .tagline { font: 300 italic 22px/1.4 'Be Vietnam Pro', sans-serif; margin: 18px 0 0; }
.hero .intro { margin: 22px 0 34px; font-size: 18px; }
.hero .cta-row { display: flex; gap: 14px; flex-wrap: wrap; }

/* What is actually on offer, at a glance, in the spec plate's voice. A hero
   that only states the section's own name tells a buyer nothing. */
.portfolio { display: flex; gap: 40px; margin: 0 0 34px; padding: 22px 0 0;
             border-top: 1px solid rgba(255,255,255,.28); }
.portfolio dt { font: 600 10px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
                letter-spacing: .16em; color: rgba(255,255,255,.92); margin-bottom: 5px; }
.portfolio dd { margin: 0; font: 600 30px/1 'Outfit', sans-serif; letter-spacing: -0.02em;
                font-variant-numeric: tabular-nums; }
.portfolio .pu { font: 600 12px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
                 letter-spacing: .12em; margin-left: 6px; color: rgba(255,255,255,.92); }
.hero .btn--outline { color: #fff; border-color: #fff; }
.hero .btn--outline:hover { background: #fff; color: var(--ra-contrast); }

/* 2 · Property blocks, the Auctions layout George pointed at */
/* The photograph now sets the height of the row and fills its column, rather
   than sitting centred in it with dead white above and below. Rows alternate
   so two properties do not read as one repeated block. */
.property { display: grid; grid-template-columns: 52fr 48fr; gap: 64px; align-items: stretch; padding: 64px 0; border-bottom: 1px solid var(--ra-base); }
.property:first-of-type { padding-top: 40px; }
.property__text { display: flex; flex-direction: column; justify-content: center; }
.property:nth-of-type(even) .shot { order: 2; }
.property:last-of-type { border-bottom: 0; }
.property .shot { position: relative; min-height: 460px; border-radius: 4px; overflow: hidden; box-shadow: 0 2px 6px rgba(0,0,0,.08), 0 24px 60px rgba(0,0,0,.12); }
.property .shot .slot,
.property .shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Photography pending, matching the property page's own empty state. */
.shot-pending {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center;
  color: var(--rural);
  /* An absent photograph is an unfinished state, not a void. Going light also
     removes one of the page's four dark zones outright. */
  background: radial-gradient(120% 90% at 50% 35%, #ffffff 0%, var(--rural-paper) 72%);
  box-shadow: inset 0 0 0 1px var(--ra-base);
}
.property .shot .shot-pending img {
  position: static; width: 54px; height: 54px; object-fit: contain;
  opacity: .34; margin-bottom: 16px;
}
.shot-pending .t { font: 700 13px 'Outfit', sans-serif; text-transform: uppercase; letter-spacing: .12em; color: var(--rural); }

/* The photograph is the link. It already lifted under the cursor, which
   promised a target that was not there. */
.property a.shot { display: block; }
.property a.shot:focus-visible { outline: 2px solid var(--ra-contrast); outline-offset: 3px; }
/* The photograph lifts a little under the cursor, so the row reads as one
   object rather than a picture sitting next to some text. */
.property .shot img { transition: transform .6s cubic-bezier(.2,.7,.3,1); }
.property:hover .shot img { transform: scale(1.03); }
.facts { display: grid; grid-template-columns: 1fr 1fr; column-gap: 32px; margin: 26px 0; border-top: 1px solid var(--ra-base); }
.facts div { padding: 13px 0; border-bottom: 1px solid var(--ra-base); }
.facts dt {
  display: flex; align-items: center; gap: 8px;
  font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase; letter-spacing: .12em;
  margin-bottom: 7px; color: var(--rural);
}
.facts dd { margin: 0; padding-left: 26px; }   /* value aligns to the label text, past the icon */
/* Carrying capacity is the bull from the PBS badge, masked and filled with
   currentColor so it inherits colour like the stroke icons beside it. The badge
   artwork is untouched: the head was lifted out of it, the surrounding ring cut
   away, and nothing redrawn. */
.ico--bull {
  /* An <i> is not a replaced element, so width and height are ignored while it
     is inline and it collapses to nothing outside a flex parent. */
  display: inline-block;
  background: currentColor;
  -webkit-mask: url(img/pbs-bull.png) center / contain no-repeat;
  mask: url(img/pbs-bull.png) center / contain no-repeat;
}
.ico { width: 18px; height: 18px; flex: 0 0 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
/* 19px on a tile, 18px on the property page -- different jobs, both kept. */
.ra-landing .positioning { font: 300 italic 19px/1.5 'Be Vietnam Pro', sans-serif; margin: 14px 0 0; }


/* 7 · Sales process */
.steps { display: grid; grid-template-columns: repeat(6, 1fr); gap: 24px; margin-top: 48px; position: relative; }
.steps .step { position: relative; padding-top: 34px; }
.steps .step::before { content: ''; position: absolute; top: 11px; left: 0; right: 0; height: 1px; background: var(--ra-base); }
.steps .step:first-child::before { left: 50%; }
.steps .step:last-child::before { right: 50%; }
.steps .n { position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 22px; height: 22px; border-radius: 50%; background: var(--ra-contrast); color: #fff; font: 600 11px/22px 'Be Vietnam Pro', sans-serif; text-align: center; }
.steps h3 { font-size: 14px; text-transform: uppercase; letter-spacing: .08em; text-align: center; margin-bottom: 8px; color: var(--rural); }
.steps p { font-size: 13px; line-height: 1.55; text-align: center; color: var(--muted); margin: 0; }





@media (max-width: 900px) {
}


/* 3 · Why PBS, paired with the evidence rather than standing alone */
.why { display: grid; grid-template-columns: 1fr 1fr; gap: 72px; align-items: center; }
.why__shot { margin: 0; aspect-ratio: 5 / 4; overflow: hidden; }
.why__shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Full-bleed breather. Carries George's tagline where it can be read against
   the country rather than floating over the hero. */
.breather { position: relative; padding: 0; min-height: 460px; display: flex;
            align-items: center; justify-content: center; overflow: hidden; background: var(--rural-ink); }
.breather img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.breather__veil {
  position: absolute; inset: 0;
  /* A flat veil spends ink on the edges, where nothing is written.
     Centre-weighting protects the line and opens the corners. */
  background:
    radial-gradient(78% 86% at 50% 50%,
      rgba(13,26,9,.60) 0%, rgba(13,26,9,.44) 55%, rgba(13,26,9,.20) 100%),
    linear-gradient(180deg,
      rgba(13,26,9,.16) 0%, rgba(13,26,9,0) 28%,
      rgba(13,26,9,0) 72%, rgba(13,26,9,.18) 100%);
}
.breather__line {
  position: relative; z-index: 2; margin: 0; text-align: center; color: #fff;
  font: 300 italic 34px/1.35 'Be Vietnam Pro', sans-serif;
  text-shadow: 0 2px 12px rgba(9,18,6,.55); padding: 0 24px;
}

/* The appraisal call to action, on country rather than on flat ink */
/* The breather and this section are both green-veiled aerials sitting directly
   on top of each other, so the boundary has to be stated rather than implied.
   A hairline in --rural-lift, then a hard band of near-solid ground before the
   photograph starts: you see picture, edge, ground, picture. The 2px rule is the
   same signal .plate and .place use on light grounds, inverted for a dark one. */
.ink--shot { position: relative; overflow: hidden; border-top: 2px solid rgba(165,191,155,.55); }
.ink--shot .ink__bg { position: absolute; inset: 0; width: 100%; height: 100%;
                      object-fit: cover; opacity: .70; }
.ink--shot > .wrap { position: relative; z-index: 2; }
.ink--shot::after { content: ''; position: absolute; inset: 0;
                    background:
                      /* a definite top edge. Without it this section's aerial runs
                         straight into the breather's aerial above and the two read
                         as one photograph. */
                      linear-gradient(180deg,
                        rgba(13,26,9,.97) 0%, rgba(13,26,9,.97) 72px,
                        rgba(13,26,9,.55) 132px, rgba(13,26,9,0) 230px),
                      linear-gradient(90deg,
                        rgba(13,26,9,.84) 0%, rgba(13,26,9,.40) 100%); }
/* At .96 over an image already dimmed to .22 the photograph contributed under
   1% of the panel. The copy sits in the left 40fr and an opaque white card
   covers the right, so the gradient can be given away on that side for free. */
.ink--shot > .wrap { z-index: 3; }

@media (max-width: 900px) {
  .why { grid-template-columns: 1fr; gap: 28px; }
  .why__shot { aspect-ratio: 16 / 10; }
  .breather { min-height: 300px; }
  .breather__line { font-size: 23px; }
}


/* 4 · The PBS View. Seven lenses and a photograph make eight cells, so the
   count that made a four-column grid leave a hole now fills one. The 1px gap
   over a tinted ground draws hairlines between cells without card chrome. */
.lenses {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1px; background: var(--ra-base); border: 1px solid var(--ra-base);
  margin-top: 44px;
}
.lens { background: #fff; padding: 26px 24px 30px; }
.lens .ico { width: 21px; height: 21px; flex-basis: 21px; color: var(--rural); margin-bottom: 14px; }
.lens h3 { font-size: 17px; letter-spacing: -0.008em; margin-bottom: 8px; }
.lens p  { font-size: 14.5px; line-height: 1.58; color: var(--ink-body); margin: 0; }
.lens--shot { margin: 0; padding: 0; position: relative; overflow: hidden; min-height: 190px; }
.lens--shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
                  transition: transform .7s cubic-bezier(.2,.7,.3,1); }
.lenses:hover .lens--shot img { transform: scale(1.05); }
/* The seven lenses currently just stop and the next thing on the page is a
   form band. This closes the section on the claim the seven cells have earned.
   17px/500 over --ra-contrast so it reads as the conclusion, not the fine
   print: the disclaimer band lower down is 12.5px --muted and the two must not
   be confusable. No rule, no tint, no card -- the grid already carries a 1px
   border and a second edge under it reads as another grid row. */
.lenses__close {
  margin: 30px 0 0;
  max-width: 700px;
  font: 500 17px/1.6 'Be Vietnam Pro', sans-serif;
  color: var(--ra-contrast);
}

/* 7 · The process. Six across at 1120px gave each step 160px, which is a
   gutter with words in it. Three by two fits six exactly. Numbering stays
   because this is a sequence, unlike the lenses above. */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--ra-base);
         border: 1px solid var(--ra-base); margin-top: 44px; }
.steps .step { background: var(--ra-base-2); padding: 26px 26px 30px; position: static; }
.steps .n {
  display: block; position: static; transform: none; width: auto; height: auto;
  background: none; border-radius: 0; text-align: left;
  font: 600 13px 'Be Vietnam Pro', sans-serif; letter-spacing: .16em;
  color: var(--rural); opacity: 1; margin-bottom: 14px;   /* at .75 the token
     composites over the #f5f7f5 band to 3.35:1 and fails. Slate failed here too. */
  font-variant-numeric: tabular-nums;
}
.steps h3 { font-size: 17px; text-transform: uppercase; letter-spacing: .06em; text-align: left;
            margin-bottom: 8px; color: var(--ra-contrast); }
.steps p { font-size: 14.5px; line-height: 1.58; text-align: left; color: var(--ink-body); margin: 0; }
.steps .step::before { display: none; }

@media (max-width: 900px) {
  .lenses { grid-template-columns: 1fr 1fr; }
  .lens { padding: 20px 16px 24px; }
  .lenses__close { margin-top: 24px; font-size: 16px; }
  /* 7 lenses + 1 photograph = 8 cells, which divides into two columns
     exactly. Spanning the photograph full width left the 7th cell's
     neighbour empty, showing the grid ground as a grey box. */
  .lens--shot { min-height: 150px; }
  .steps { grid-template-columns: 1fr; }
  .steps .step { padding: 18px 16px 20px; }
}


/* 8 · Insights. PBS has nothing published, so three rows of invented titles
   with "Coming" beside them were pretending. This says what the section will
   carry, which is true, and sends the reader to the buyer register rather than
   asking for a third email address on one page. */
.insights { display: grid; grid-template-columns: 54fr 46fr; gap: 72px; align-items: center; }
.insights__shot { margin: 0; aspect-ratio: 4 / 5; overflow: hidden; }
.insights__shot img { width: 100%; height: 100%; object-fit: cover; display: block;
                      transition: transform .7s cubic-bezier(.2,.7,.3,1); }
.insights:hover .insights__shot img { transform: scale(1.04); }
.topics { list-style: none; margin: 26px 0 0; padding: 0; border-top: 1px solid var(--ra-base); }
.topics li { position: relative; padding: 13px 0 13px 26px; border-bottom: 1px solid var(--ra-base);
             font-size: 16px; }
.topics li::before {
  content: ''; position: absolute; left: 2px; top: 21px; width: 9px; height: 1px;
  background: var(--rural);
}

@media (max-width: 900px) {
  .insights { grid-template-columns: 1fr; gap: 30px; }
  .insights__shot { aspect-ratio: 16 / 10; order: -1; }
}

/* 2b · The two together. George's own point: "While the two properties can be
   assessed individually, their existing relationship provides an important
   point of difference." The arrow is the whole idea, so it carries the weight
   and everything around it stays quiet. */
.together__lede { max-width: 760px; font-size: 18px; margin-top: 22px; }
.pathway {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: stretch;
  gap: 1px; background: var(--ra-base); border: 1px solid var(--ra-base);
  margin-top: 40px;
}
.pathway__end {
  background: #fff; padding: 30px 30px 32px; display: flex; flex-direction: column;
  text-decoration: none; color: inherit;
  transition: background .18s ease;
}
.pathway__end:hover { background: var(--ra-base-2); }
.pathway__role {
  font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .18em; color: var(--rural); margin-bottom: 12px;
}
.pathway__name {
  font: 700 26px/1.1 'Outfit', sans-serif; letter-spacing: -0.015em;
  margin-bottom: 10px;
}
.pathway__size { font-size: 15px; line-height: 1.5; color: var(--ink-body); }
.pathway__link {
  margin-top: 16px; font: 600 13px 'Be Vietnam Pro', sans-serif;
  text-transform: uppercase; letter-spacing: .1em; color: var(--red);
}
.pathway__arrow {
  background: #fff; display: flex; align-items: center; justify-content: center;
  padding: 0 26px; color: var(--rural);
}
.pathway__arrow svg { width: 34px; height: 20px; display: block; }
.together__note {
  margin-top: 40px; font-size: 17px; line-height: 1.6; color: var(--ink-body); max-width: 760px;
}

/* ---------------------------------------------------------------------------
   2c · The offer, and the campaign window.

   .pathway above is a two-ended diagram with a connector between the ends. This
   is the same shape read against time: two dates, a scale between them, today
   marked on it. Full width, same end treatment, so the section reads as two
   views of one structure.

   The rail is a SIX-WEEK CALENDAR SCALE, not a progress bar and not a drawing
   of "unless sold prior". Solid is time already elapsed, tint is time still to
   run — nothing more is claimed. The week labels under it are what make it a
   scale; delete them and it becomes a progress bar. "Unless sold prior" is a
   sentence, and it is stated as one, twice.

   The 2px rule is the survey-schedule signal .plate and .place already use.
   --------------------------------------------------------------------------- */
.eoi { margin-top: 22px; border-top: 2px solid var(--ra-contrast); padding-top: 20px; }
.eoi__title { font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
              letter-spacing: .18em; color: var(--rural); margin: 0 0 18px; }

/* The two ends, deliberately unequal. The opening date is history; the closing
   date is the one fact that decides whether a buyer acts, so it is the block's
   only display figure. align-items:end sits both on the rail whatever the
   line count. */
.eoi__ends { display: grid; grid-template-columns: 1fr 1fr; gap: 24px;
             align-items: end; margin: 0 0 16px; }
.eoi__ends dt { font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
                letter-spacing: .18em; color: var(--rural); margin-bottom: 9px; }
.eoi__ends dd { margin: 0; }
.eoi__end--close { text-align: right; }
.eoi__end--close time { display: block; }
.eoi__end--open dd { font: 600 19px 'Outfit', sans-serif; letter-spacing: -.005em;
                     font-variant-numeric: tabular-nums; color: var(--muted); }
.eoi__end--close b { display: block; font: 700 34px/1.02 'Outfit', sans-serif;
                     letter-spacing: -.02em; font-variant-numeric: tabular-nums;
                     color: var(--ra-contrast); }
.eoi__end--close span { display: block; margin-top: 5px;
                        font: 600 12px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
                        letter-spacing: .14em; color: var(--muted); }

/* The two weights of green are the rainfall chart's --rural / --rural-bar pair.
   Square ends: every hairline on this page is square and a rounded cap reads as
   browser chrome. */
.eoi__rail { position: relative; height: 10px; background: var(--rural-bar); }
.eoi__run  { position: absolute; left: 0; top: 0; bottom: 0;
             width: var(--elapsed, 0%); background: var(--rural); }
/* Cells of exactly seven days. Sized off --days, not a week count, so a span
   that is not a whole number of weeks ends on a short cell instead of six lying
   ones. 42 days -> 16.6667%. background-position -1px keeps the first divider
   off the rail's own left edge. */
.eoi__rail::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(90deg, #fff 0 1px, transparent 1px);
  background-size: calc(100% * 7 / var(--days, 42)) 100%;
  background-position: -1px 0;
}
/* Today, as a survey tick. A dot is a control you can drag. */
.eoi__tick { position: absolute; top: -7px; bottom: -7px; width: 2px;
             left: var(--elapsed, 0%); margin-left: -1px; background: var(--ra-contrast); }

.eoi__weeks { display: grid; grid-template-columns: repeat(var(--weeks, 6), 1fr);
              margin-top: 7px;
              font: 500 9.5px 'Be Vietnam Pro', sans-serif; color: var(--muted);
              letter-spacing: .06em; }
.eoi__weeks span { padding-left: 4px; }

.eoi__status { display: grid; grid-template-columns: 1fr auto; gap: 24px;
               align-items: baseline; margin-top: 16px;
               padding-bottom: 20px; border-bottom: 1px solid var(--ra-base); }
.eoi__state { margin: 0; font: 600 15px 'Be Vietnam Pro', sans-serif;
              color: var(--ra-contrast); font-variant-numeric: tabular-nums; }
/* John's phrase as the rail's label, at the end of the rail it qualifies.
   --rural is 6.01:1 on white. The full sentences follow below at reading size. */
.eoi__prior { margin: 0; text-align: right; font: 600 11px 'Be Vietnam Pro', sans-serif;
              text-transform: uppercase; letter-spacing: .18em; color: var(--rural); }
.eoi__terms { margin: 18px 0 0; max-width: 760px; font-size: 14.5px; line-height: 1.65;
              color: var(--ink-body); }

/* States. sold and withdrawn are identical: both mean "this window is no longer
   live", and a withdrawn campaign rendering as open is not cosmetic. */
.eoi[data-state="before"] .eoi__tick { display: none; }
.eoi[data-state="before"] .eoi__end--open dd { color: var(--ra-contrast); }
.eoi[data-state="closed"] .eoi__rail,
.eoi[data-state="sold"]   .eoi__rail,
.eoi[data-state="withdrawn"] .eoi__rail,
.eoi[data-state="closed"] .eoi__run,
.eoi[data-state="sold"]   .eoi__run,
.eoi[data-state="withdrawn"] .eoi__run { background: var(--ra-base); }
.eoi[data-state="closed"] .eoi__tick,
.eoi[data-state="sold"]   .eoi__tick,
.eoi[data-state="withdrawn"] .eoi__tick,
.eoi[data-state="closed"] .eoi__prior,
.eoi[data-state="sold"]   .eoi__prior,
.eoi[data-state="withdrawn"] .eoi__prior { display: none; }
.eoi[data-state="closed"] .eoi__end--close b,
.eoi[data-state="sold"]   .eoi__end--close b,
.eoi[data-state="withdrawn"] .eoi__end--close b { color: var(--muted); }

@media (max-width: 640px) {
  .together__note { margin-top: 26px; font-size: 16px; }
  .eoi { margin-top: 20px; padding-top: 18px; }
  .eoi__title { font-size: 10.5px; letter-spacing: .16em; margin-bottom: 14px; }
  /* The ends stay left and right. They ARE the rail's two ends; stacking them
     destroys the only thing the graphic is for. At 375px the close date wraps
     to "4 November / 2026", which reads as a plate and keeps the figure large. */
  .eoi__ends { gap: 14px; margin-bottom: 14px; }
  .eoi__ends dt { font-size: 9.5px; letter-spacing: .14em; margin-bottom: 6px; }
  .eoi__end--open dd { font-size: 15px; }
  .eoi__end--close b { font-size: 24px; letter-spacing: -.015em; }
  .eoi__end--close span { font-size: 10.5px; letter-spacing: .1em; margin-top: 4px; }
  .eoi__rail { height: 8px; }
  .eoi__tick { top: -6px; bottom: -6px; }
  .eoi__weeks { font-size: 9px; }
  .eoi__weeks span:nth-child(n+2) { text-align: center; padding-left: 0; }
  .eoi__status { grid-template-columns: 1fr; gap: 8px; padding-bottom: 16px; }
  .eoi__state { font-size: 14px; }
  .eoi__prior { text-align: left; font-size: 10px; }
  .eoi__terms { font-size: 13.5px; margin-top: 15px; }
}

@media (max-width: 760px) {
  .pathway { grid-template-columns: 1fr; }
  .pathway__end { padding: 22px 18px 24px; }
  .pathway__name { font-size: 22px; }
  .pathway__arrow { padding: 14px 0; }
  .pathway__arrow svg { transform: rotate(90deg); }
}

/* John Friend's endorsement. A named quote with a face carries weight that no
   amount of specification does, and it is the only thing on the site that says
   why PBS should be taken seriously on rural property rather than cattle. */
.endorse {
  margin: 44px 0 0; padding: 30px 0 0; border-top: 1px solid var(--ra-base);
  display: grid; grid-template-columns: 1fr 260px; gap: 44px; align-items: start;
}
.endorse blockquote { margin: 0; }
.endorse blockquote p {
  margin: 0; font: 300 italic 20px/1.55 'Be Vietnam Pro', sans-serif; color: var(--ra-contrast);
}
.endorse figcaption { display: flex; align-items: center; gap: 14px; padding-top: 4px; }
.endorse figcaption img {
  width: 54px; height: 54px; flex: none; border-radius: 50%; object-fit: cover;
  background: var(--ra-base); box-shadow: 0 0 0 1px rgba(0,0,0,.08);
}
.endorse__who { font: 700 16px 'Outfit', sans-serif; }
.endorse__role {
  display: block; margin-top: 2px;
  font: 600 10px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .16em; color: var(--rural);
}
@media (max-width: 860px) {
  .endorse { grid-template-columns: 1fr; gap: 22px; }
  .endorse blockquote p { font-size: 18px; }
}

/* 5 + 6 · Forms */
.form-card { background: #fff; border: 1px solid var(--ra-base); border-radius: 5px; padding: 36px 40px; }
.two-col { display: grid; grid-template-columns: 40fr 60fr; gap: 64px; align-items: center; }


@media (max-width: 900px) {
  .hero { min-height: 0; }
  /* On a phone `cover` shows nearly the whole frame and the text spans it, so
     the ink cannot be aimed away from the reading column. Vertical, and evenly
     carried. */
  .hero .scrim {
    background:
      radial-gradient(115% 46% at 46% 102%, rgba(94,58,12,.20) 0%, rgba(94,58,12,0) 100%),
      linear-gradient(180deg,
        rgba(13,26,9,.40) 0%, rgba(13,26,9,.30) 20%,
        rgba(13,26,9,.28) 58%, rgba(13,26,9,.34) 100%);
  }
  .hero .inner { padding-top: 56px; padding-bottom: 56px; }
  .hero h1 { font-size: 34px; }
  .hero .tagline { font-size: 18px; }
  .hero .cta-row .btn { flex: 1 1 100%; text-align: center; padding: 15px 20px; }
  .portfolio { gap: 24px; margin-bottom: 26px; }
  .portfolio dd { font-size: 22px; }
  .property { grid-template-columns: 1fr; gap: 24px; padding: 40px 0; }
  .property .shot { min-height: 0; aspect-ratio: 4 / 3; }
  .property:nth-of-type(even) .shot { order: 0; }
  .facts dd { padding-left: 0; }
  /* the stale mobile block for the old numbered-timeline .steps was here.
     It set gap:22px over the hairline grid's tinted ground, which rendered
     as thick grey bands between the tiles, plus 40px left padding for a
     numeral that is no longer positioned. The live mobile rule is above. */
  .ra-landing .two-col { grid-template-columns: 1fr; gap: 32px; }
  .form-card { padding: 24px 20px; }
}


/* ---------- 3. PROPERTY TEMPLATE ----------------------------------------- */

/* Single property template. Every property renders from this structure, so
   adding one is content entry rather than a build.

   Desktop is a product page: photographs on the left, the detail a buyer needs
   in order to act on the right. It stacks to a single column on a phone. */

/* ---- Breadcrumb bar ---- */
.crumb {
  background: var(--ra-base-2); border-bottom: 1px solid var(--ra-base);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 11px max(40px, calc((100% - 1200px) / 2));
}
.crumb .left { display: flex; align-items: center; gap: 14px; min-width: 0; }
.crumb .back { font-size: 13px; color: var(--muted); text-decoration: none; white-space: nowrap; }
.crumb .back:hover { color: var(--ra-contrast); }
.crumb .sep { width: 1px; height: 16px; background: var(--ra-base); }
.crumb .here { font: 600 12px 'Be Vietnam Pro', sans-serif; text-transform: uppercase; letter-spacing: .1em; color: var(--rural); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.icon-btn {
  width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--ra-base);
  background: #fff; cursor: pointer; display: flex; align-items: center; justify-content: center;
  color: var(--ra-contrast); flex-shrink: 0; transition: border-color .15s ease;
  /* The circle stays 38px; the hit area is 44px. A control small enough
     to be pretty is still a control too small to hit. */
  min-width: 44px; min-height: 44px;
}
.icon-btn:hover { border-color: var(--ra-contrast); }
.icon-btn svg { width: 17px; height: 17px; }
.icon-btn:focus-visible { outline: 2px solid var(--ra-contrast); outline-offset: 2px; }

/* ---- The product block ---- */
.product {
  max-width: var(--wrap); margin: 0 auto; padding: 40px 40px 72px;
  display: grid; grid-template-columns: 57fr 43fr; gap: 56px; align-items: start;
}
/* A grid item defaults to min-width: auto, so this column would grow to fit the
   widest thing inside it. The thumbnail strip is wider than the column by design
   and can only scroll if the column is allowed to be narrower than its content. */
.product__media { grid-column: 1; grid-row: 1; min-width: 0; }
.info { grid-column: 2; grid-row: 1 / span 2; }
.aside { grid-column: 1; grid-row: 2; }

/* ---- Gallery, now a column rather than the full window ---- */
.gal { position: relative; background: var(--ra-base-2); border-radius: 4px; overflow: hidden; padding: 0; }
/* Photography pending. Every property starts without stills, so this is a state
   the template owns rather than a hole where a gallery should be. */
.gal[data-empty] {
  aspect-ratio: 4 / 3; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 90% at 50% 35%, #ffffff 0%, var(--rural-paper) 72%);
}
.gal[data-empty] .gal__track { display: none; }
.gal[data-empty]::after {
  content: ''; position: absolute; inset: 14px; border: 1px solid var(--ra-base);
  border-radius: 3px; pointer-events: none;
}
/* The pending panel belongs to the empty state, so it is gated on that state
   rather than on being absent from the file. Leaving it ungated meant it
   painted over the photographs the moment a property got its stills. */
.gal__pending { display: none; }
.gal[data-empty] .gal__pending { display: block; text-align: center; color: var(--rural);
  padding: 32px; position: relative; z-index: 2; }
.gal__pending img { width: 62px; height: 62px; opacity: .34; display: block; margin: 0 auto 20px; }
.gal__pending .t { font: 700 16px 'Outfit', sans-serif; text-transform: uppercase; letter-spacing: .1em; }
.gal__pending .s { font-size: 14px; line-height: 1.55; color: var(--muted); margin: 10px auto 0; max-width: 300px; }
.gal__track {
  display: flex; overflow-x: auto;
  scroll-snap-type: x mandatory; scroll-behavior: smooth;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.gal__track::-webkit-scrollbar { display: none; }
.gal__slide {
  flex: 0 0 100%; scroll-snap-align: center; scroll-snap-stop: always;
  position: relative; aspect-ratio: 4 / 3; margin: 0; cursor: zoom-in;
}
.gal__slide img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Only as much shading as the overlaid controls need */
.gal__slide::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,.28) 0%, rgba(0,0,0,0) 22%, rgba(0,0,0,0) 68%, rgba(0,0,0,.34) 100%);
}

.gal__nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 6;
  width: 46px; height: 46px; border-radius: 50%; border: 1px solid rgba(255,255,255,.35); cursor: pointer;
  background: rgba(20,20,20,.34); color: #fff; font-size: 22px; line-height: 1;
  display: flex; align-items: center; justify-content: center; backdrop-filter: blur(6px);
  transition: background .15s ease, opacity .15s ease;
}
.gal__nav:hover { background: rgba(20,20,20,.72); }
.gal__nav:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.gal__nav[disabled] { opacity: .22; cursor: default; }
.gal__prev { left: 14px; }
.gal__next { right: 14px; }

.gal__count {
  position: absolute; bottom: 14px; right: 14px; z-index: 6;
  background: rgba(20,20,20,.48); backdrop-filter: blur(6px); border: 1px solid rgba(255,255,255,.22);
  color: #fff; border-radius: 40px; padding: 6px 14px;
  font: 600 11px 'Be Vietnam Pro', sans-serif; letter-spacing: .08em;
}
.gal__expand {
  position: absolute; bottom: 14px; left: 14px; z-index: 6;
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid rgba(255,255,255,.4); background: rgba(20,20,20,.34);
  backdrop-filter: blur(6px); color: #fff; cursor: pointer;
  border-radius: 40px; padding: 7px 15px;
  font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase; letter-spacing: .08em;
  transition: background .15s ease;
}
.gal__expand:hover { background: rgba(20,20,20,.72); }
.gal__expand:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* ---- Thumbnails, sitting under the gallery in the same column ---- */
.thumbs { margin-top: 8px; }
.thumbs__row {
  display: flex; gap: 8px;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-behavior: smooth;
  scrollbar-width: none; -ms-overflow-style: none;
}
.thumbs__row::-webkit-scrollbar { display: none; }   /* the cut-off thumb is the affordance */
.thumbs button {
  flex: 0 0 78px;
  aspect-ratio: 3 / 2; padding: 0; border: 0; cursor: pointer;
  border-radius: 3px; overflow: hidden; background: var(--ra-base); opacity: .72;
  transition: opacity .18s ease, box-shadow .18s ease;
}
.thumbs button img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumbs button:hover { opacity: .9; }
.thumbs button[aria-current="true"] { opacity: 1; box-shadow: inset 0 0 0 2px var(--ra-contrast); }
.thumbs button:focus-visible { outline: 2px solid var(--ra-contrast); outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   The left column below the photographs.

   A third grid child rather than part of .product__media: the media column
   stacks above .info on a phone, so anything nested inside it would arrive
   before the property is even named.
   --------------------------------------------------------------------------- */
.aside { min-width: 0; }
.place { border-top: 2px solid var(--ra-contrast); padding: 16px 0 0; }   /* shorthand: .place is a <section> and would keep section's 88px bottom */
.place__towns { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin: 16px 0 0; }
.place__towns dt {
  font: 600 10.5px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .13em; color: var(--rural);
}
.place__towns dd {
  margin: 5px 0 0; font: 600 21px 'Outfit', sans-serif;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
.place__towns .u { font-size: .58em; letter-spacing: .04em; }
.place__market { margin: 22px 0 0; }
.place__market > div { padding: 11px 0; border-bottom: 1px solid var(--ra-base); }
.place__market > div:first-child { border-top: 1px solid var(--ra-base); }
.place__market dt {
  font: 600 10.5px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .13em; color: var(--rural); margin-bottom: 6px;
}
.place__market dd { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-body); }
.aside .agent-mini { margin-top: 26px; }

/* The other half of the operation. Both properties are on the market at once and
   were run as one system, so each page has to say so -- a buyer who arrives on
   one from a news article has no other way to learn the second exists. */
.sibling { margin-top: 28px; padding-top: 22px; border-top: 1px solid var(--ra-base); }
.sibling__eyebrow {
  font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .18em; color: var(--rural); margin-bottom: 10px;
}
.sibling p { font-size: 15px; line-height: 1.55; color: var(--ink-body); margin: 0 0 10px; }
.sibling a { font: 600 14px 'Be Vietnam Pro', sans-serif; color: var(--red); text-decoration: none; }
.sibling a:hover { text-decoration: underline; }

/* ---- The buying column ---- */
.info h1 { font-size: 40px; line-height: 1.04; text-transform: uppercase; margin: 10px 0 0; }
.info .where { margin: 12px 0 0; font-size: 17px; }
.ra-property .positioning { font: 300 italic 18px/1.5 'Be Vietnam Pro', sans-serif; margin: 18px 0 0; }

/* Stroke icons, sized to sit beside a label */
.ico {
  width: 18px; height: 18px; flex: 0 0 18px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Carrying capacity is the bull from the PBS badge, masked and filled with
   currentColor so it inherits colour like the stroke icons beside it. The badge
   artwork is untouched: the head was lifted out of it, the surrounding ring cut
   away, and nothing redrawn. */
.ico--bull {
  /* An <i> is not a replaced element, so width and height are ignored while it
     is inline and it collapses to nothing outside a flex parent. */
  display: inline-block;
  background: currentColor;
  -webkit-mask: url(img/pbs-bull.png) center / contain no-repeat;
  mask: url(img/pbs-bull.png) center / contain no-repeat;
}
.ico--lg { width: 22px; height: 22px; flex-basis: 22px; stroke-width: 1.6; }


/* ---------------------------------------------------------------------------
   The specification plate.

   Modelled on the schedule of a survey plan rather than a card grid: the
   qualifying figure set at display size, then measurements ruled off beneath
   it. Label left, value right, hairline between. Figures are tabular so the
   right edge stays true.
   --------------------------------------------------------------------------- */
.plate { margin-top: 26px; border-top: 2px solid var(--ra-contrast); }

.plate__head { display: flex; align-items: baseline; gap: 14px; padding: 20px 0 12px; }
.plate__fig {
  font: 600 68px/0.86 'Outfit', sans-serif;
  letter-spacing: -0.035em; font-variant-numeric: tabular-nums;
  color: var(--ra-contrast);
}
.plate__unit {
  font: 600 15px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .16em; color: var(--rural);
}
.plate__alt {
  font: 400 15px 'Be Vietnam Pro', sans-serif; color: var(--muted);
  font-variant-numeric: tabular-nums; padding-bottom: 18px;
  border-bottom: 1px solid var(--ra-base);
}

.sched { margin: 0; }
.sched > div {
  display: grid; grid-template-columns: 1fr auto; gap: 18px; align-items: baseline;
  padding: 11px 0; border-bottom: 1px solid var(--ra-base);
}
.sched dt {
  display: flex; align-items: center; gap: 8px;
  font: 600 10.5px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .13em; color: var(--rural); white-space: nowrap;
}
.sched dd {
  margin: 0; text-align: right; font-variant-numeric: tabular-nums;
  font-size: 15.5px; line-height: 1.45;
}
.sched .q { color: var(--muted); }                 /* the qualifier, not the quantity */
.sched .u { font-size: .8em; color: var(--muted); letter-spacing: .02em; }

/* Rainfall. Real BOM figures, summer dominant, which is the whole point of
   the district and the first thing a grazier checks. */
.rain { margin: 20px 0 0; padding: 16px 0 0; }
.rain figcaption {
  font: 600 10.5px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .13em; color: var(--rural); margin-bottom: 12px;
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
}
.rain figcaption b { font: 600 14px 'Outfit', sans-serif; color: var(--ra-contrast); letter-spacing: 0; }
.rain__bars { display: block; width: 100%; height: 66px; }
.rain__wrap { border-bottom: 1px solid var(--ra-base); padding-bottom: 6px; }
.rain__bars rect { fill: var(--rural-bar); }
.rain__bars rect.pk { fill: var(--rural); }
.rain__axis {
  display: grid; grid-template-columns: repeat(12, 1fr); margin-top: 7px;
  font: 500 9.5px 'Be Vietnam Pro', sans-serif; color: var(--muted);
  letter-spacing: .06em; text-align: center;
}

/* ---------------------------------------------------------------------------
   Terms of sale.

   The commercial terms, gathered once, ABOVE the measurements. A buyer has to
   know what is on offer before the plate tells them how big it is: the vendors
   would rather sell both properties as one holding, and a buyer who reads
   2,816 ha in isolation has been told half of it.

   Same survey-schedule idiom as .sched -- label left, value right, hairline
   between -- so it reads as terms of sale rather than more pitch. No icons:
   .sched's icons mark measurements and this block is not one. The closing date
   is this block's only figure, so it is set in Outfit like every other figure.

   The note is John's wording verbatim. It is the operative term of the campaign
   and is not to be paraphrased; the plain-English job is done by the two labels
   above it.
   --------------------------------------------------------------------------- */
.terms { margin-top: 26px; padding-top: 16px; border-top: 2px solid var(--ra-contrast); }
.terms .eyebrow { margin-bottom: 10px; }

.terms__rows { margin: 0; }
/* auto 1fr, not 1fr auto: row 1's value is a phrase plus a qualifier and needs
   the wide side. */
.terms__rows > div {
  display: grid; grid-template-columns: auto 1fr; gap: 18px; align-items: baseline;
  padding: 11px 0; border-bottom: 1px solid var(--ra-base);
}
.terms__rows dt {
  font: 600 10.5px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .13em; color: var(--rural); white-space: nowrap;
}
.terms__rows dd {
  margin: 0; text-align: right; font-variant-numeric: tabular-nums;
  font-size: 15.5px; line-height: 1.45;
}
.terms__rows .q { color: var(--muted); }          /* the qualifier, not the term */
.terms__date { font: 600 17px 'Outfit', sans-serif; letter-spacing: -.005em; }
/* The legal paragraph, one tap away.

   <details> and not a scripted accordion: no JavaScript means a script failure
   cannot hide the operative terms of the sale, and the keyboard and screen
   reader behaviour is native. Chrome also opens it for find-on-page, so the
   wording stays discoverable.

   The two labelled rows above stay visible on purpose -- they decide whether a
   buyer acts, and the "one holding" condition changes what is being bought. */
/* The WHOLE terms block behind one disclosure.

   Closed, the column shows "Terms of sale" and a chevron, nothing else. The
   closing date and the "one holding" condition are inside it. That is a
   deliberate client decision: the top of the property page was carrying too
   much text against a much shorter gallery column.

   <details> and not a scripted accordion: no JavaScript means a script failure
   cannot hide the operative terms of the sale, the keyboard and screen-reader
   behaviour is native, and Chrome opens it for find-on-page, so the wording
   stays discoverable to anyone searching the document. */
.terms__more { margin-top: 0; }
.terms__more summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  /* 16px of vertical padding, not 3px, so the whole row is a 44px tap target.
     Measured at 18px before this and the compact look was the cause: the label
     is ~12px, so the padding IS the target. The negative margin gives the hit
     area back to the touch layer without giving the space to the layout, so it
     still reads as tight as the client asked for. */
  padding: 16px 2px 16px 0; margin: -13px 0; cursor: pointer;
  list-style: none;                       /* Firefox */
  -webkit-tap-highlight-color: transparent;
}
.terms__more summary::-webkit-details-marker { display: none; }   /* Safari/Chrome */
.terms__more-label {
  font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .13em; color: var(--rural);
}
/* Deliberately heavy. Closed, this is the ONLY thing telling a reader there is
   anything here, so it has to read as a control rather than as punctuation.
   Drawn from two borders: no icon font, no SVG, and it rotates. */
.terms__more summary::after {
  content: ''; flex: none;
  width: 11px; height: 11px; margin: -5px 3px 0 0;
  border-right: 2.5px solid var(--rural); border-bottom: 2.5px solid var(--rural);
  transform: rotate(45deg); transform-origin: center;
  transition: transform .18s ease;
}
.terms__more[open] summary::after { transform: rotate(-135deg); margin-top: 3px; }
.terms__more summary:hover::after { border-color: var(--ra-contrast); }
.terms__more summary:focus-visible { outline: 2px solid var(--rural); outline-offset: 3px; }
/* Open: the rows need air under the summary they now sit inside. */
.terms__more[open] .terms__rows { margin-top: 12px; }
.terms__note { margin: 14px 0 2px; font-size: 13px; line-height: 1.6; color: var(--muted); }

@media (prefers-reduced-motion: reduce) {
  .terms__more summary::after { transition: none; }
}

/* Replaces the inline margin-bottom:0 the eyebrow used to carry. */
.info__status { margin-bottom: 0; text-wrap: balance; }

@media (max-width: 900px) {
  .plate__fig { font-size: 52px; }
  .sched > div { grid-template-columns: 1fr; gap: 3px; }
  /* Matches what .sched already does at this width: the value cannot be held
     right in a 343px column. */
  .terms__rows > div { grid-template-columns: 1fr; gap: 3px; }
  .terms__rows dd { text-align: left; }
  .sched dd { text-align: left; }
}

.actions { display: flex; flex-direction: column; gap: 10px; margin-top: 28px; }
.actions .btn { width: 100%; text-align: center; }

/* ---- Description, full width below the product block ---- */
.detail-grid { max-width: var(--wrap); margin: 0 auto; padding: 0 40px; display: grid; grid-template-columns: 1fr 1fr; gap: 40px 64px; }
.detail-grid .lbl {
  display: flex; align-items: center; gap: 10px;
  font: 600 12px 'Be Vietnam Pro', sans-serif; text-transform: uppercase; letter-spacing: .16em;
  margin-bottom: 10px; color: var(--rural);
}
.detail-grid p { margin: 0; padding-left: 32px; }


/* ---------------------------------------------------------------------------
   Property overview. Evidence, not prose: each aspect is shown as well as
   described. No card chrome, the photograph is the container.
   --------------------------------------------------------------------------- */
.overview { max-width: var(--wrap); margin: 0 auto; padding: 0 40px;
            display: grid; grid-template-columns: 1fr 1fr; gap: 52px 64px; }
.aspect figure { margin: 0 0 18px; position: relative; aspect-ratio: 16 / 9;
                 overflow: hidden; background: var(--ra-base); }
.aspect figure img { width: 100%; height: 100%; object-fit: cover; display: block;
                     transition: transform .7s cubic-bezier(.2,.7,.3,1); }
.aspect:hover figure img { transform: scale(1.04); }
.aspect figure::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,0) 45%, rgba(0,0,0,.62) 100%); }
.aspect figcaption {
  position: absolute; left: 16px; bottom: 13px; z-index: 2;
  display: flex; align-items: center; gap: 9px; color: #fff;
  font: 600 11px 'Be Vietnam Pro', sans-serif; text-transform: uppercase; letter-spacing: .16em;
}
.aspect figcaption .ico { width: 16px; height: 16px; flex-basis: 16px; }
.aspect p { margin: 0; }
/* A property with no photography yet uses the text-only panel: the label carries
   itself. Kept on both pages because the template owns both states. */
.aspect--plain .lbl { display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
  font: 600 12px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .16em; color: var(--rural); }

@media (max-width: 900px) {
  .overview { grid-template-columns: 1fr; gap: 34px; padding: 0 16px; }
}

/* Field spacing for these two contexts; the underline itself is in pbs.css. */
.form-card label, .modal label { gap: 2px; }
.form-card ::placeholder, .modal ::placeholder { color: #a8adb1; }
.form-card { padding: 34px 38px; }

/* What the place can be run as. George's argument, and the thing that separates
   these pages from a listing: the property does not dictate one future. A
   schedule rather than a grid, because Te Angie has six options and Forest
   Lodge four, and either count leaves a hole in a three or four column grid. */
.runs { border-top: 2px solid var(--ra-contrast); margin-top: 8px; }
.runs__row {
  display: grid; grid-template-columns: 220px 1fr; gap: 28px;
  padding: 18px 0; border-bottom: 1px solid var(--ra-base);
}
.runs__name {
  font: 600 12px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .16em; color: var(--rural); padding-top: 3px;
}
.runs__what { font-size: 16px; line-height: 1.55; color: var(--ink-body); margin: 0; }
@media (max-width: 760px) {
  .runs__row { grid-template-columns: 1fr; gap: 6px; padding: 14px 0; }
}

.runs__note {
  margin: 26px 0 0; max-width: 820px;
  font-size: 12.5px; line-height: 1.6; color: var(--muted);
}

/* ---- The IM teaser ---- */
.im-block { display: grid; grid-template-columns: 62fr 38fr; gap: 72px; align-items: center; }
.im-list { margin: 26px 0 0; padding: 0; list-style: none; }
.im-list li { position: relative; padding: 9px 0 9px 26px; border-bottom: 1px solid var(--ra-base); font-size: 16px; }
.ink .im-list li { border-bottom-color: rgba(255,255,255,.14); }
.ink .im-list li::before { border-right-color: var(--rural-lift); border-bottom-color: var(--rural-lift); }
.ink .im-cover { box-shadow: 0 2px 8px rgba(0,0,0,.4), 0 30px 70px rgba(0,0,0,.5); }
.im-list li:last-child { border-bottom: 0; }
.im-list li::before {
  content: ''; position: absolute; left: 3px; top: 17px;
  width: 7px; height: 7px; border-right: 2px solid var(--rural); border-bottom: 2px solid var(--rural);
  transform: rotate(45deg);
}
/* The cover of the document itself, in page proportions, so the panel reads as
   the thing being offered rather than a cropped photograph with a caption. */
.im-cover {
  position: relative; aspect-ratio: 1 / 1.414; border-radius: 2px; overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,.12), 0 30px 70px rgba(0,0,0,.22);
}
/* Direct child only: the lockup's badge is an <img> inside .im-cover too, and
   it was inheriting this absolute positioning and pinning to the corner. */
.im-cover > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.im-cover__veil {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(13,26,9,.58) 0%, rgba(13,26,9,.10) 34%, rgba(13,26,9,.90) 100%);
}
.im-cover__inner {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between;
  padding: 26px 26px 28px; color: #fff;
}
/* The full lockup. The badge is held at 46px, just above the 44px floor below
   which its rim type collapses, and the type scales to suit rather than the
   badge shrinking to fit. */
/* inline-flex still stretches as a flex item, so the box ran the full width
   of the cover while its content sat left. Shrink it to its content. */
.im-cover .lockup { align-self: flex-start; }
.im-cover .lockup img { width: 46px; height: 46px; }
.im-cover .lockup__rule { margin: 0 13px; }
.im-cover .lockup__wm { font-size: 15px; letter-spacing: .05em; }
.im-cover .lockup__by { font-size: 7.5px; letter-spacing: .07em; margin-top: 5px; opacity: .72; }
.im-cover__kicker {
  font: 600 9px 'Be Vietnam Pro', sans-serif; text-transform: uppercase;
  letter-spacing: .22em; color: rgba(255,255,255,.72);
}
.im-cover__rule { height: 1px; background: rgba(255,255,255,.34); margin: 0 0 14px; }
.im-cover__name { font: 700 25px/1.06 'Outfit', sans-serif; margin-top: 9px; letter-spacing: -.005em; }
.im-cover__where { font: 400 13px 'Be Vietnam Pro', sans-serif; color: rgba(255,255,255,.8); margin-top: 7px; }

.two-col { display: grid; grid-template-columns: 40fr 60fr; gap: 64px; align-items: center; }
.form-card { background: #fff; border: 1px solid var(--ra-base); border-radius: 5px; padding: 36px 40px; }
.im-band { display: flex; align-items: center; justify-content: space-between; gap: 28px; flex-wrap: wrap; border-top: 1px solid var(--ra-base); padding-top: 36px; }
.im-band__line { margin: 0; max-width: 430px; font-size: 15.5px; line-height: 1.55; color: var(--ink-body); }

/* ---- Modals ---- */

/* ⚠️ THE OVERLAY LAYER SITS ABOVE THE THEME, AND THESE NUMBERS ARE MEASURED.
   GeneratePress puts z-index:100 on .main-navigation and 100001 on the
   slide-out. The nav is position:static, which normally makes z-index inert —
   but .inside-header is display:flex, so the nav is a FLEX ITEM, and z-index
   DOES apply to flex items whatever their position. That is why a static
   element was painting over a fixed one.

   At 60/70/80 the header drew across the top of the open lightbox on desktop,
   and on a phone the burger sat on top of the lightbox's own close button.
   Anything that covers the whole viewport has to clear 100001. */
.modal { position: fixed; inset: 0; z-index: 100100; background: rgba(20,20,20,.58); display: flex; align-items: center; justify-content: center; padding: 24px; }
.modal[hidden] { display: none; }
.modal .panel { width: 100%; max-width: 520px; background: #fff; border-radius: 6px; box-shadow: 0 30px 80px rgba(0,0,0,.35); padding: 40px 44px 44px; position: relative; max-height: 90vh; overflow: auto; }
.modal .panel:focus { outline: none; }   /* a container, not a control */
.modal .close { position: absolute; top: 12px; right: 12px; width: 40px; height: 40px; border: 0; background: none; cursor: pointer; color: var(--muted); font: 300 26px/1 'Be Vietnam Pro', sans-serif; }
.modal .close:hover { color: var(--ra-contrast); }
.modal h2 { font-size: 28px; line-height: 1.1; margin: 8px 0 12px; }
/* The lede is outside the form, so `gap` never applies between them and the
   paragraph's own 6px was the entire separation. The fields sit 16px apart,
   so the break before the first one has to be visibly larger than that. */
.modal form { display: flex; flex-direction: column; gap: 16px; margin-top: 22px; }
.modal .btn { width: 100%; text-align: center; }
.err { color: var(--red); font-size: 14px; margin: 0; }

.ra-lightbox { position: fixed; inset: 0; z-index: 100200; background: rgba(12,12,12,.96); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.ra-lightbox[hidden] { display: none; }
.ra-lightbox img { max-width: 94vw; max-height: 88vh; object-fit: contain; }
.ra-lightbox img { touch-action: none; cursor: zoom-in; will-change: transform; }
.ra-lightbox img.is-zoomed { cursor: grab; }
.ra-lightbox img.is-zoomed:active { cursor: grabbing; }
.ra-lightbox button { position: absolute; border: 0; background: rgba(255,255,255,.1); color: #fff; width: 52px; height: 52px; border-radius: 50%; cursor: pointer; font-size: 22px; }
.ra-lightbox button:hover { background: rgba(255,255,255,.22); }
.ra-lightbox .ra-lb-close { top: 20px; right: 20px; }
.ra-lightbox .ra-lb-prev { left: 20px; top: 50%; transform: translateY(-50%); }
.ra-lightbox .ra-lb-next { right: 20px; top: 50%; transform: translateY(-50%); }
.ra-lightbox .ra-lb-count { position: absolute; bottom: 22px; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,.75); font: 400 13px 'Be Vietnam Pro', sans-serif; }

.toast {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%) translateY(20px);
  background: #141414; color: #fff; border-radius: 40px; padding: 11px 22px;
  font: 600 13px 'Be Vietnam Pro', sans-serif; z-index: 100300;
  opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease;
}
.toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }


/* Between the phone and full desktop the buying column gets too narrow to hold
   two fact columns, so give the gallery less of the width and the facts one. */
@media (max-width: 1080px) and (min-width: 901px) {
  .product { grid-template-columns: 52fr 48fr; gap: 36px; }
  .info h1 { font-size: 32px; }
  .im-block { gap: 40px; }
}

@media (max-width: 900px) {
  .crumb { padding: 9px 16px; }
  /* Stacks: photographs first, then everything a buyer needs to act. */
  .product { grid-template-columns: 1fr; gap: 28px; padding: 0 0 48px; }
  .product__media, .info, .aside { grid-column: auto; grid-row: auto; }
  .place { margin-top: 4px; }
  .gal { border-radius: 0; }
  .gal__slide { aspect-ratio: 3 / 2; }
  .gal__nav { width: 40px; height: 40px; font-size: 19px; }
  .gal__prev { left: 8px; } .gal__next { right: 8px; }
  .gal__expand { display: none; }          /* tapping the photograph already opens it */
  .thumbs { padding: 0 16px; }
  .thumbs__row { gap: 6px; }
  .thumbs button { flex-basis: 64px; }
  /* .product goes edge to edge on a phone, so every text column restores its own
     gutter. .aside was added after this block was written and missed out. */
  .info, .aside { padding: 0 16px; }
  .place__towns { grid-template-columns: 1fr 1fr; gap: 20px 16px; }
  .info h1 { font-size: 30px; }
  .detail-grid { grid-template-columns: 1fr; gap: 28px; padding: 0 16px; }
  .detail-grid p { padding-left: 0; }
  .im-block { grid-template-columns: 1fr; gap: 32px; }
  .im-cover { max-width: 260px; }
  .ra-property .two-col { grid-template-columns: 1fr; gap: 28px; }
  .form-card { padding: 24px 20px; }
  /* Contained on a phone too: edge to edge with no radius reads as a new page,
     not as a dialog sitting over this one. */
  .modal { padding: 16px; }
  .modal .panel { padding: 44px 22px 30px; max-height: 84vh; }
}

@media (prefers-reduced-motion: reduce) {
  .gal__track, .thumbs__row { scroll-behavior: auto; }
  .toast { transition: none; }
}


/* ---------- 4. PREMIUM TOUCHES ------------------------------------------- */

/* =============================================================================
   Premium touches, 21 Sep 2026.

   Taken from what the auctions page does well, translated into this section's
   own vocabulary rather than copied. The gold ribbon and the catalogue covers
   there are SUPPLIED ARTWORK that arrives with each sale; Rural Assets has no
   equivalent per property, so the same effect has to be earned structurally.

   ⚠️ Contour texture is NOT reintroduced. It was tried on this section and
   removed: too fussy, and horizontal lines fought the horizon in the
   photography. The note left open was that texture, if it came back, "wants to
   be angled" -- which is what the cut below is, and it is a single edge rather
   than a field.
   ============================================================================= */


/* --- 1. The Information Memorandum cover, as an object -------------------- */
/* It already carried 0 2px 8px rgba(0,0,0,.4) and 0 30px 70px rgba(0,0,0,.5).
   Both are invisible: the cover sits inside section.ink, whose ground is
   rgb(13,26,9). A black shadow on a near-black surface does nothing.

   What separates a pale document from a dark ground is a LIGHT rim, not a
   heavier shadow. The 1px rim reads as the cut edge of the paper; the wide
   green-tinted glow is the ambient bounce a real object would cast back. Both
   are kept under 0.16 alpha -- any more and it reads as a sticker, not paper. */
.ink .im-cover {
  box-shadow:
    0 2px 8px rgba(0,0,0,.4),
    0 30px 70px rgba(0,0,0,.5),
    0 0 0 1px rgba(255,255,255,.15),        /* the paper's own edge */
    0 0 90px -20px rgba(165,191,155,.16);   /* --rural-lift, as bounce */
}


/* --- 2. The brand edge ---------------------------------------------------- */
/* Where a photographic or dark band meets a light section, the boundary is a
   shallow diagonal with a --rural edge following it, instead of a straight
   horizontal seam.

   This is the same DEVICE as the gold ribbon on the auctions page -- a shaped
   boundary carrying the brand colour -- at this section's weight. The rise is
   38px across the full width, about 1.8 degrees: enough to register as
   deliberate, not enough to look like a swoosh.

   --ra-cut-to must be set to the ground of the section BELOW, or the wedge
   fills with the wrong colour and the seam becomes obvious rather than less so.
   --------------------------------------------------------------------------- */
.ra-cut { position: relative; }

/* ⚠️ A REAL CHILD ELEMENT, NOT ::before AND ::after ON THE SECTION.
   That is what this was, and it was wrong. #sell on the landing page carries
   BOTH .ink--shot and .ra-cut, an element has only ONE ::after, and _premium.css
   is appended last by the build — so .ra-cut::after silently overwrote
   .ink--shot::after and took two things with it:

     1. The wedge inherited `inset: 0` from the rule it replaced, so with top,
        bottom AND height all set the box was over-constrained, the browser
        dropped `bottom`, and the divider drew across the TOP of the section.
        That is the white slash in the client's screenshot.

     2. Worse, and silently: .ink--shot::after's two gradients vanished. One is
        a hard top edge that exists solely so this section's aerial and the
        breather's aerial above it do not read as one photograph; the other is a
        left-to-right wash that darkens the ground under the copy. Measured
        background-image on that pseudo was `none`.

   Adding `top: auto` fixes the picture and ships the undimmed aerial, so it is
   not the fix. Owning a real element instead gives both pseudos back to the
   design and cannot collide with anything a section already uses. */
.ra-cut__edge {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 46px;
  pointer-events: none;
  z-index: 3;   /* above .ink--shot's veil and its background photograph */
}

/* ⚠️ THE DIAGONAL MUST MEET THE CORNERS. The first version used a shallow
   polygon inside the 46px strip — fill from (0,44) to (100%,6) — which left the
   dark section showing for 44px below the line on the LEFT, terminating in a
   hard HORIZONTAL edge at the section boundary. So one end of the cut was a
   clean angle and the other was a blunt step with a sliver of the next colour
   under it. That is what the client saw, twice.

   Now the fill is a right triangle whose hypotenuse runs corner to corner:
   bottom-left to top-right. There is no leftover wedge at either end, because
   the diagonal terminates exactly where the section does. */
.ra-cut__edge::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--ra-cut-to, var(--ra-base-3));
  clip-path: polygon(0 100%, 100% 0, 100% 100%);
}

/* The brand edge is the SAME triangle sitting 5px higher, painted underneath —
   so all that shows of it is a 5px band riding the hypotenuse. Drawing a
   separate thin parallelogram would need its own trigonometry and would drift
   out of step the moment the height changes. */
.ra-cut__edge::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--rural);
  clip-path: polygon(0 calc(100% - 5px), 100% -5px, 100% 100%, 0 100%);
}

/* ⚠️ --ra-cut-to must match the ground of whatever section follows, or the
   wedge paints a colour that belongs to nothing. Default is --ra-base-3 (white).
   If you give the following section a new ground, change this IN THE SAME EDIT. */
.ra-cut--to-base2 { --ra-cut-to: var(--ra-base-2); }

/* ---------------------------------------------------------------------------
   Between two PHOTOGRAPHIC sections: ONE STRAIGHT DIVIDER, no angle.

   The angled cut was tried here twice and rejected both times. It is the wrong
   device between two images: a filled wedge cannot blend into a photograph, and
   a line-only wedge still reads as a slanted stripe laid over a boundary that
   already had .ink--shot's own 2px rule and 72px of near-solid veil beneath it.
   The angle earns its place where a section meets a FLAT ground — there it is a
   shape cut out of one colour into another. Between two photographs there is no
   shape, only a line.

   So: keep .ink--shot's 2px rule as the single divider (it is the design's own
   signal, the one .plate and .place use on light grounds, inverted for a dark
   one) and soften the veil beneath it so the rule is the ONLY edge rather than
   the first of three.
   --------------------------------------------------------------------------- */
.ink--shot::after {
  background:
    linear-gradient(180deg, rgba(13,26,9,.92) 0%, rgba(13,26,9,.55) 120px, rgba(13,26,9,0) 230px),
    linear-gradient(90deg, rgba(13,26,9,.84) 0%, rgba(13,26,9,.40) 100%);
}

@media (max-width: 760px) {
  /* A 38px rise across 375px is 5.8 degrees, which reads as a slant rather than
     an edge. Shallower, so it stays a boundary. */
  .ra-cut::after  { height: 26px; clip-path: polygon(0 100%, 100% 100%, 100% 4px, 0 24px); }
  .ra-cut::before { height: 26px; clip-path: polygon(0 20px, 100% 0px, 100% 4px, 0 24px); }
}

/* ---------------------------------------------------------------------------
   The locality map.

   A Google embed arrives with its own bright cartography, which fights a design
   built on hairlines, a muted palette and near-black type. It cannot be
   restyled — the Embed API takes no styling parameters — so the frame does the
   work instead: the same 1px --ra-base hairline and 0 radius as everything else
   on the page, and a slight desaturation so it sits back rather than shouting.
   --------------------------------------------------------------------------- */
.ra-map {
  margin: 16px 0 0;
  border: 1px solid var(--ra-base);
  background: var(--ra-base-2);
  line-height: 0;          /* an iframe is inline: kills the descender gap */
}

.ra-map iframe {
  display: block;
  width: 100%;
  height: 320px;
  border: 0;
  filter: saturate(.82);
}

@media (max-width: 900px) {
  .ra-map iframe { height: 240px; }
}

@media (prefers-reduced-motion: reduce) {
  .ra-map iframe { filter: saturate(.82); }
}

/* ---------------------------------------------------------------------------
   "Coming soon" on the Information Memorandum.

   Shown only while a property has no PDF in the document store. It is a note,
   not a warning: the section's whole job is to trade the document for an email
   address, and that trade is worth more while the document is still coming.
   So it reads as anticipation, in --rural-lift on the dark band, rather than as
   an apology in an error colour.
   --------------------------------------------------------------------------- */
.im-soon {
  margin: 26px 0 0;
  padding: 14px 0 0;
  border-top: 1px solid rgba(255,255,255,.18);
  font-size: 15px;
  line-height: 1.5;
  color: rgba(255,255,255,.78);
}

.im-soon span {
  display: block;
  margin-bottom: 4px;
  font: 600 11px 'Be Vietnam Pro', sans-serif;
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--rural-lift);
}

