/* Kate Rosamond — site stylesheet.

   The four small stylesheets this replaces (accessibility, image reveal, cookie consent,
   sticky CTA) were four render-blocking requests for 5.7 KB between them, and on a throttled
   mobile connection each one was a round trip before anything painted. They are kept here as
   labelled sections in their original load order: accessibility first so a page can override
   it, then the image reveal, the consent bar and the sticky CTA. Edit the section, not a
   separate file — there is no build step, this IS the file the site loads. */

/* ═══════════════════════════════════════════════════════════════════════════
   kr-a11y.css
   ═══════════════════════════════════════════════════════════════════════════ */
/* Kate Rosamond — accessibility utilities.
   Loaded on every page, before the page's own styles so a page can override.

   The skip link is the first focusable element in the document. It stays out of the
   layout until it takes focus, then drops in at the top left so a keyboard user can
   jump the nav (logo, eight links, menu button, sticky CTA) and land on the content.
   WCAG 2.4.1. It is never visible to a pointer user. */
.kr-skip{position:fixed;top:0;left:0;z-index:1000;transform:translateY(-140%);padding:0.85rem 1.6rem;background:#1A1713;color:#F4F0E8;font-family:'Cormorant SC',serif;font-weight:300;font-size:13px;letter-spacing:0.26em;text-transform:uppercase;text-decoration:none;border-bottom-right-radius:2px;transition:transform 0.18s cubic-bezier(0.22,1,0.36,1)}
.kr-skip:focus,.kr-skip:focus-visible{transform:translateY(0);outline:2px solid #A8874E;outline-offset:-2px}
@media (prefers-reduced-motion:reduce){.kr-skip{transition:none}}

/* ═══════════════════════════════════════════════════════════════════════════
   kr-imgfade.css
   ═══════════════════════════════════════════════════════════════════════════ */
/* Kate Rosamond — image reveal.
   Below-the-fold photos sit on a blurred low-res preview (see kr-lqip.js) and fade up
   only once their slot is on screen, so the fade is always seen rather than spent
   off screen. Priority images (fetchpriority="high" — page heroes and the logo) get no
   preview layer and simply fade on load.
   Paired with kr-imgfade.js, which owns the timing, the observer and the layer. */

/* Hidden from first paint. .kr-shown is added by the script, never by CSS, so the
   noscript override in each page is what keeps images visible without JS. */
html.kr-imgfade img:not(.g-hover):not(.kr-shown) { opacity: 0; }

/* The reveal. Long and eased so it reads as intentional rather than as a pop.
   Below-the-fold images get the full 1.8s over their preview; hero images, which
   have no preview to cross-fade from, get 1.2s so the first screen is not sluggish. */
html.kr-imgfade img.kr-shown { animation: krImgFade 1.8s cubic-bezier(0.22, 1, 0.36, 1) forwards; }
html.kr-imgfade img.kr-nopreview.kr-shown { animation-duration: 1.2s; }
/* Lightbox sources and anything hidden at scan time: no preview, no fade, just visible. */
html.kr-imgfade img.kr-instant { animation: none !important; opacity: 1; }

@keyframes krImgFade { from { opacity: 0; } to { opacity: 1; } }

/* The preview layer. A separate element is unavoidable: fading the photo's own opacity
   would fade a background on the same element with it. The script inserts one of these
   into the photo's offset parent, sized to the photo's box, and removes it once the
   photo is opaque — so it is never in the document longer than the reveal itself.
   Having no children of its own, it can safely carry a CSS blur.

   It sits at z-index -1 and the script isolates the host, so the layer lands above the
   host's own background and below every one of its children. The photo itself is never
   lifted: lifting it used to outrank sibling overlays that carry no z-index of their own
   (a hover photo, a caption scrim), which hid them for as long as the preview existed. */
.kr-ph-layer {
  position: absolute;
  z-index: -1;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: var(--surface, #141210);
  filter: blur(12px) saturate(1.1);
  transform: scale(1.06);
  opacity: 1;
  pointer-events: none;
  transition: opacity 1s cubic-bezier(0.22, 1, 0.36, 1) 0.5s;
}
/* Released only after the photo is most of the way in, so there is no gap between them. */
.kr-ph-layer.kr-ph-done { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  html.kr-imgfade img:not(.g-hover):not(.kr-shown) { opacity: 1; }
  html.kr-imgfade img.kr-shown { animation: none; }
  .kr-ph-layer { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   kr-consent.css
   ═══════════════════════════════════════════════════════════════════════════ */
/* Kate Rosamond — cookie consent (option A: full-width bar) + policy overlay.

   The banner and the policy overlay appear on both themes, so every colour here has to
   resolve on either. Gold text (--accent) clears 9:1 on the dark pages but only 2.7:1 on
   the light journal pages, so accents read --accent-deep first: the light pages define it
   (#7A5F2E, 4.7:1) and the dark pages do not, which makes the fallback the switch. Rules
   and borders derive from currentColor for the same reason, and the greys go through
   --border / --muted rather than hard-coded near-white. */
/* The bar is in every page's markup rather than injected, so its text paints with the first
   frame instead of after a deferred script — as the largest text on the page it was the
   Largest Contentful Paint, and injecting it put that 6s into the load. Two classes, both set
   by the inline head block before paint, govern it: .kr-cb-show puts it in the document at
   all, .kr-cb-reserve holds the homepage hero clear of it. They come off at different moments
   on dismiss, which is why they are separate: the hero should start easing down as the bar
   slides out, but the bar itself cannot be display:none until that slide has finished. */
/* The bar arrives in place rather than sliding up. It used to start at translateY(100%) and
   wait for JS to add a class, which put it outside the viewport at first paint — and an
   off-screen element is not a Largest Contentful Paint candidate, so as the largest text on
   the page it still set LCP, just later. .is-out drives the exit instead.

   min-height is the other half: the bar paints before the webfonts arrive, and without a
   floor its height changed when they swapped in, which was the whole layout shift on the
   homepage. The four values are the measured heights WITH the fonts loaded; fallback text is
   always a few pixels shorter, never taller, so the floor absorbs the swap completely. They
   are the same numbers .kr-cb-reserve holds the hero clear by — one set for both. */
.kr-cb{position:fixed;left:0;right:0;bottom:0;z-index:9000;background:var(--surface,#141210);border-top:1px solid var(--border,rgba(240,235,227,0.12));padding:1.5rem 1.75rem;display:none;align-items:center;gap:1.75rem;justify-content:space-between;min-height:100px;transition:transform .45s cubic-bezier(.22,1,.36,1)}
html.kr-cb-show .kr-cb{display:flex}
.kr-cb.is-out{transform:translateY(100%)}
@media (max-width:768px){.kr-cb{min-height:130px}}
@media (max-width:640px){.kr-cb{min-height:165px}}
@media (max-width:480px){.kr-cb{min-height:187px}}
.kr-cb-t{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:16px;line-height:1.6;color:var(--muted,rgba(240,235,227,.65));margin:0;max-width:66ch;text-wrap:pretty}
.kr-cb-t a,.kr-cookie-line button{color:var(--accent-deep,var(--accent,#C5A97A));text-decoration:none;border-bottom:1px solid color-mix(in srgb,currentColor 38%,transparent);transition:color .2s,border-color .2s}
.kr-cb-t a:hover{color:var(--text,#F0EBE3);border-color:rgba(240,235,227,.45)}
.kr-cb-acts{display:flex;align-items:center;gap:.9rem;flex-shrink:0}
.kr-btn{font-family:'Jost',sans-serif;font-weight:300;font-size:12px;letter-spacing:.2em;text-transform:uppercase;padding:.75rem 1.6rem;min-height:44px;background:transparent;border:1px solid color-mix(in srgb,currentColor 52%,transparent);color:var(--accent-deep,var(--accent,#C5A97A));cursor:pointer;transition:background .25s,border-color .25s,color .25s;white-space:nowrap}
.kr-btn:hover{background:var(--accent-deep,var(--accent,#C5A97A));border-color:var(--accent-deep,var(--accent,#C5A97A));color:var(--bg,#0C0B09)}
.kr-btn.kr-q{border-color:transparent;color:var(--muted,rgba(240,235,227,.65))}
.kr-btn.kr-q:hover{background:transparent;color:var(--text,#F0EBE3)}

/* footer re-open link */
.kr-cookie-line{display:flex;justify-content:center;padding:1.6rem 1.5rem 0}
.kr-cookie-line button{font-family:'Cormorant SC',serif;font-weight:300;font-size:12px;letter-spacing:.28em;text-transform:uppercase;background:none;border:0;border-bottom:1px solid rgba(240,235,227,.18);padding:0 0 3px;cursor:pointer;color:var(--muted,rgba(240,235,227,.65))}
.kr-cookie-line button:hover{color:var(--accent-deep,var(--accent,#C5A97A))}

/* policy overlay */
.kr-cp{position:fixed;inset:0;z-index:9100;background:rgba(12,11,9,.82);display:grid;place-items:center;padding:2rem 1.25rem;opacity:0;transition:opacity .3s}
.kr-cp.is-in{opacity:1}
.kr-cp[hidden]{display:none}
.kr-cp-box{width:100%;max-width:640px;max-height:100%;background:var(--surface,#141210);border:1px solid var(--border,rgba(240,235,227,.12));padding:2.25rem 2.25rem 2rem;display:grid;gap:1.15rem;overflow:auto;position:relative;-webkit-overflow-scrolling:touch}
.kr-cp-x{position:absolute;top:.9rem;right:1rem;width:44px;height:44px;display:flex;align-items:center;justify-content:center;font-family:'Jost',sans-serif;font-weight:200;font-size:22px;line-height:1;color:var(--muted,rgba(240,235,227,.65));background:none;border:0;cursor:pointer}
.kr-cp-x:hover{color:var(--text,#F0EBE3)}
.kr-cp-box h2{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:30px;line-height:1.1;color:var(--text,#F0EBE3);margin:0;padding-right:2.5rem}
.kr-cp-box h3{font-family:'Cormorant SC',serif;font-weight:300;font-size:11px;letter-spacing:.3em;text-transform:uppercase;color:var(--accent-deep,var(--accent,#C5A97A));margin:.4rem 0 0}
.kr-cp-box p{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:16px;line-height:1.65;color:var(--muted,rgba(240,235,227,.65));margin:0;text-wrap:pretty}
.kr-cp-box p a{color:var(--accent-deep,var(--accent,#C5A97A));text-decoration:none;border-bottom:1px solid color-mix(in srgb,currentColor 38%,transparent)}
.kr-cp-box p a:hover{color:var(--text,#F0EBE3)}
.kr-cp-box .kr-cp-rule{height:1px;background:var(--border,rgba(240,235,227,.12))}
.kr-cp-tbl{width:100%;border-collapse:collapse;text-align:left}
.kr-cp-tbl th{font-family:'Cormorant SC',serif;font-weight:300;font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:var(--muted,rgba(240,235,227,.5));padding:0 1rem .55rem 0;border-bottom:1px solid var(--border,rgba(240,235,227,.12))}
.kr-cp-tbl td{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:15px;line-height:1.5;color:var(--muted,rgba(240,235,227,.65));padding:.8rem 1rem .8rem 0;border-bottom:1px solid color-mix(in srgb,var(--border,rgba(240,235,227,.12)) 60%,transparent);vertical-align:top}
.kr-cp-tbl td:first-child{font-family:'Jost',sans-serif;font-size:12.5px;letter-spacing:.04em;color:var(--text,#F0EBE3);white-space:nowrap}
.kr-cp-tbl th:last-child,.kr-cp-tbl td:last-child{white-space:nowrap;padding-right:0}
body.kr-noscroll{overflow:hidden}

@media (max-width:640px){
  .kr-cb{padding:1.6rem 1.4rem 1.5rem;gap:1.1rem}
  html.kr-cb-show .kr-cb{display:grid}
  .kr-cb-t{font-size:15px;max-width:none}
  .kr-cb-acts{display:grid;grid-template-columns:1fr 1fr;gap:.75rem}
  .kr-btn{width:100%;text-align:center;padding:.85rem .6rem;letter-spacing:.16em}
  .kr-btn.kr-q{border-color:color-mix(in srgb,currentColor 24%,transparent)}
  .kr-cp{padding:1rem}
  .kr-cp-box{padding:1.9rem 1.4rem 1.6rem;gap:1rem}
  .kr-cp-box h2{font-size:26px}
  .kr-cp-tbl td:first-child{white-space:normal}
  .kr-cp-tbl th:last-child,.kr-cp-tbl td:last-child{white-space:normal}
}
@media (prefers-reduced-motion:reduce){.kr-cb,.kr-cp,.hero-noir{transition:none}}

/* Home hero: the whole bottom-anchored text block, arrow included, sits clear of the banner.

   The clearance is reserved BEFORE first paint by an inline script in the page head, which
   reads the stored consent choice and sets .kr-cb-reserve on <html> when no choice has been
   made. It used to be applied afterwards, from the measured height of the injected banner,
   which moved the hero text after it had already painted and was the entire layout shift on
   the homepage. Fixed per-breakpoint values are what make the pre-paint version possible:
   the real banner measures 187px at phone widths down to 360, 163 by 600, 126 by 700 and 100
   above 768, so each step reserves the tallest case in its range. A few pixels of extra
   clearance costs nothing; measuring costs a reflow after paint.

   Removing the class on dismiss does move the text, but that shift lands within 500ms of the
   click that caused it, so it is user-initiated and outside the CLS window. */
.hero-noir{transition:bottom .45s cubic-bezier(.22,1,.36,1)}
html.kr-cb-reserve .hero-noir{bottom:calc(9vh + 100px)}
@media (max-width:768px){html.kr-cb-reserve .hero-noir{bottom:calc(7vh + 130px)}}
@media (max-width:640px){html.kr-cb-reserve .hero-noir{bottom:calc(7vh + 165px)}}
@media (max-width:480px){html.kr-cb-reserve .hero-noir{bottom:calc(7vh + 187px)}}

/* ═══════════════════════════════════════════════════════════════════════════
   kr-cta.css
   ═══════════════════════════════════════════════════════════════════════════ */
/* Kate Rosamond — sticky mobile enquiry button.
   Hidden until the visitor has answered the cookie notice (kr-consent.js fires kr-consent-settled),
   then eases up once they are past the hero, and slides away over the enquiry form and footer.
   Hidden means visibility:hidden, not opacity alone: opacity stops the mouse but leaves the
   link in the tab order, so a keyboard user could reach a button they cannot see. The
   visibility transition is delayed by the length of the slide so it still animates out. */
.kr-cta{position:fixed;left:0;right:0;bottom:0;z-index:8000;display:none;padding:1rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom,0px));background:linear-gradient(to top,var(--kr-cta-fade,rgba(12,11,9,.95)),var(--kr-cta-fade-mid,rgba(12,11,9,.7)) 62%,transparent);transform:translateY(115%);opacity:0;visibility:hidden;transition:transform .5s cubic-bezier(.22,1,.36,1),opacity .5s cubic-bezier(.22,1,.36,1),visibility 0s linear .5s;pointer-events:none}
.kr-cta.is-in{transform:none;opacity:1;visibility:visible;pointer-events:auto;transition:transform .5s cubic-bezier(.22,1,.36,1),opacity .5s cubic-bezier(.22,1,.36,1),visibility 0s}
.kr-cta a{display:flex;align-items:center;justify-content:center;min-height:56px;background:rgba(12,11,9,.55);backdrop-filter:blur(10px);border:1px solid rgba(197,169,122,.5);color:var(--accent,#C5A97A);font-family:'Jost',sans-serif;font-weight:300;font-size:13px;letter-spacing:.2em;text-transform:uppercase;text-decoration:none;transition:background .25s,border-color .25s,color .25s}
.kr-cta a:active{background:var(--accent,#C5A97A);border-color:var(--accent,#C5A97A);color:var(--bg,#0C0B09)}
@media (max-width:768px){.kr-cta{display:grid}}
@media (prefers-reduced-motion:reduce){.kr-cta{transition:opacity .2s}}
