/* ============================================================
   Self-hosted type — Karrik (SIL OFL 1.1), velvetyne.fr/fonts/karrik
   License copy: assets/fonts/Karrik-LICENSE.txt
   ============================================================ */
@font-face {
  font-family: "Karrik";
  src: url("../assets/fonts/Karrik-Regular.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;

}
@font-face {
  font-family: "Karrik";
  src: url("../assets/fonts/Karrik-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* ============================================================
   ALMONER — design tokens
   ============================================================ */
:root {
  /* Color */
  --color-bg: #F1ECE1;
  --color-ink: #17140F;
  --color-ink-soft: rgba(23, 20, 15, 0.64);
  --color-accent: #C8451F;
  /* darker variant for small/bold text and button backgrounds — the
     brighter accent above only clears WCAG AA (4.5:1) at large-text
     sizes, e.g. the big "01"–"04" numerals on the dark band */
  --color-accent-text: #B43A1A;
  --color-rule: rgba(23, 20, 15, 0.18);

  --color-bg-invert: #17140F;
  --color-ink-invert: #F1ECE1;
  --color-ink-invert-soft: rgba(241, 236, 225, 0.62);
  --color-rule-invert: rgba(241, 236, 225, 0.18);

  /* Type families — all free. Archivo (wght 100–900) carries every
     headline/label. --font-body is the one being auditioned for the
     unbolded running copy under Practice Statement and Capabilities —
     currently Karrik (self-hosted, OFL), falling back to Noto Sans
     (Google-hosted) then system Arial/sans-serif if either fails to load. */
  --font-display: "Archivo", Arial, sans-serif;
  --font-body: "Karrik", "Noto Sans", Arial, sans-serif;

  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-black: 900;

  /* Fluid type scale */
  --fs-3xs: clamp(0.6875rem, 0.66rem + 0.12vw, 0.75rem);
  --fs-2xs: clamp(0.75rem, 0.72rem + 0.14vw, 0.8125rem);
  --fs-xs:  clamp(0.8125rem, 0.775rem + 0.2vw, 0.9375rem);
  --fs-sm:  clamp(0.95rem, 0.89rem + 0.3vw, 1.0625rem);
  --fs-md:  clamp(1.1rem, 1rem + 0.5vw, 1.375rem);
  --fs-lg:  clamp(1.5rem, 1.2rem + 1.5vw, 2.25rem);
  --fs-xl:  clamp(2rem, 1.35rem + 3vw, 3.5rem);
  --fs-2xl: clamp(2.5rem, 1.5rem + 4.5vw, 5rem);

  /* dedicated to the Karrik body copy (Practice Statement + Capabilities
     detail lists) — decoupled from --fs-sm/--fs-md above since those are
     still shared with header/label UI text */
  --fs-body: clamp(1.2rem, 1.05rem + 0.65vw, 1.5rem);
  --fs-body-sm: clamp(1.05rem, 0.95rem + 0.5vw, 1.3rem);

  /* Grid & spacing */
  --edge: clamp(1.25rem, 1rem + 1.8vw, 3rem);
  --gutter: clamp(1rem, 0.6rem + 1.5vw, 2rem);
  --gap-block: clamp(2.5rem, 2rem + 2.5vw, 5rem);

  /* Rule weights */
  --rule-hair: 1px;
  --rule-bold: clamp(3px, 0.3vw, 5px);

  /* Motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 0.5s;
  --dur-slow: 1.3s;
  --stagger: 0.09s;

  /* Brutal industrial stretch applied to the wordmark and the bled keyword note */
  --stretch-x: 1.35;
}

/* ============================================================
   Reset
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; interpolate-size: allow-keywords; }

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  line-height: 1.5;
  font-feature-settings: "ss01" 1;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--color-ink);
  color: var(--color-bg);
  padding: 0.75em 1.25em;
  z-index: 100;
}
.skip-link:focus { left: var(--edge); }

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* ============================================================
   Shared text roles
   ============================================================ */
.eyebrow {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* nudges the label down to match the Karrik paragraph's glyph top —
   Archivo and Karrik sit at different offsets within an equal line-box,
   so grid's align-items: start alone leaves them ~2px off. Applied to
   an inner span, not #statement-heading itself, since that element's
   own transform is already driven by its .reveal scroll animation. */
.statement-heading__text {
  display: inline-block;
  transform: translateY(2px);
}

/* Header document link — a thin rule underneath, like every other
   divider on the page, instead of a filled/outlined button box */
.header-doc {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-bottom: 0.3em;
  border-bottom: var(--rule-hair) solid var(--color-ink);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.header-doc:hover { color: var(--color-accent-text); border-color: var(--color-accent-text); }

.header-doc__glyph { display: inline-block; transition: transform var(--dur-fast) var(--ease-out); }
.header-doc:hover .header-doc__glyph { transform: translateY(0.15em); }

/* ============================================================
   Header
   ============================================================ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--color-bg);
  border-bottom: var(--rule-hair) solid var(--color-rule);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gutter);
  padding: 1rem var(--edge);
}

.site-header__mark {
  font-size: var(--fs-md);
  font-weight: var(--fw-black);
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

.site-nav { flex: 1; display: flex; justify-content: center; min-width: 0; }
.site-nav__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1rem, 1vw + 0.5rem, 2.25rem);
}
.site-nav__list a {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: color var(--dur-fast) var(--ease-out);
}
.site-nav__list a:hover { color: var(--color-accent-text); }
.site-nav__index { color: var(--color-accent-text); font-weight: var(--fw-bold); }

/* ============================================================
   Hero wordmark — fluid, full-bleed
   ============================================================ */
.hero {
  container-type: inline-size;
  overflow: hidden;
  border-bottom: var(--rule-bold) solid var(--color-ink);
  padding: 0 var(--edge);
}

.wordmark {
  /* sized off the hero's own content width; the unstretched glyphs only
     need to reach ~75% of it, since the scaleX below stretches the rest
     of the way across — see .wordmark__text */
  font-size: clamp(2.25rem, 13.5cqw, 12.5rem);
  font-weight: var(--fw-black);
  line-height: 0.86;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  margin: 0.05em 0 0.02em;
  white-space: nowrap;
}

/* The industrial stretch lives on this outer wrapper, not on
   .wordmark__text itself, because the typewriter effect below needs
   overflow: hidden on .wordmark__text to hide the not-yet-typed
   letters — and overflow: hidden on the same element as the stretch
   transform would clip the stretch's own intentional bleed past its
   unstretched box. Keeping them on separate elements lets each do its
   job without fighting the other. */
.wordmark__stretch {
  display: inline-block;
  transform: scaleX(var(--stretch-x));
  transform-origin: left;
}

.wordmark__text { display: inline-block; }

.wordmark__cursor {
  display: inline-block;
  width: 0.05em;
  height: 0.78em;
  margin-left: 0.03em;
  background: var(--color-accent);
  vertical-align: -0.06em;
  opacity: 0;
}

/* Fallback for browsers without interpolate-size support (needed to
   animate width: auto precisely, see below): the previous smooth wipe. */
@supports not (interpolate-size: allow-keywords) {
  @media (prefers-reduced-motion: no-preference) {
    .wordmark__stretch { animation: clip-reveal var(--dur-slow) var(--ease-out) both; }
  }
}

/* A literal typed-on effect with a tracking cursor. interpolate-size
   makes "width: auto" animatable, so the reveal always matches
   "Almoner"'s real rendered width exactly, instead of guessing a
   per-character width for this font. */
@supports (interpolate-size: allow-keywords) {
  @media (prefers-reduced-motion: no-preference) {
    .wordmark__text {
      overflow: hidden;
      white-space: nowrap;
      width: 0;
      animation: type-wordmark 0.9s steps(7, end) both;
    }
    .wordmark__cursor {
      opacity: 1;
      animation: cursor-blink 0.4s steps(2, jump-none) infinite,
                 cursor-fade-out 0.3s ease-out 1.85s both;
    }
  }
}

@keyframes clip-reveal {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}
@keyframes type-wordmark { to { width: auto; } }
@keyframes cursor-blink { 50% { opacity: 0; } }
@keyframes cursor-fade-out { to { opacity: 0; } }

/* ============================================================
   Tagline bar
   ============================================================ */
.tagline-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gutter);
  justify-content: space-between;
  padding: 1.1rem var(--edge);
  border-bottom: var(--rule-hair) solid var(--color-rule);
}

.tagline-bar__item {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.tagline-bar__item--accent { color: var(--color-accent-text); }

/* ============================================================
   Practice statement
   ============================================================ */
.statement {
  container-type: inline-size;
  padding: var(--gap-block) var(--edge);
  /* lets the keyword column's scaleX stretch bleed to the true edge and
     clip cleanly there, instead of forcing a horizontal scrollbar */
  overflow: hidden;
}

.statement__grid {
  display: grid;
  grid-template-columns: minmax(8rem, 0.7fr) repeat(2, minmax(0, 1fr)) minmax(11rem, 1.3fr);
  gap: var(--gutter) clamp(1.5rem, 3vw, 4rem);
  align-items: start;
}

/* spans the outer grid's two paragraph tracks, then lays its own
   children out in a matching 2-column sub-grid */
.statement__copy {
  grid-column: 2 / 4;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gutter) clamp(1.5rem, 3vw, 4rem);
}

.statement__copy p { font-family: var(--font-body); font-size: var(--fs-body); color: var(--color-ink); max-width: 42ch; }

/* pinned to the second paragraph's column so it stacks directly below
   it, rather than auto-flowing back under the first paragraph */
.statement__note { grid-column: 2; }

/* The mockup's bold overflowing keyword column, sitting beside the
   practice statement copy — static, not a marquee. */
.statement__keywords {
  transform: scaleX(var(--stretch-x));
  transform-origin: left;
}

.statement__keywords li {
  /* sized off .statement's own content width (container query, not vw) so
     it scales down safely when the 4-column grid gets cramped at
     mid-range viewports, instead of overflowing off the page */
  font-size: clamp(1.3rem, 4.2cqw, 3.5rem);
  font-weight: var(--fw-black);
  text-transform: uppercase;
  letter-spacing: -0.01em;
  line-height: 1.15;
  white-space: nowrap;
}

/* ============================================================
   Capabilities — full-bleed inverted block
   ============================================================ */
.capabilities {
  background: var(--color-bg-invert);
  color: var(--color-ink-invert);
  padding: var(--gap-block) var(--edge);
  display: grid;
  grid-template-columns: minmax(4.5rem, 8rem) 1fr;
  gap: 0 var(--gutter);
  /* safety net for the label's stretch transform, same pattern as .hero */
  overflow: hidden;
}

.capabilities__label {
  grid-row: 1 / -1;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* the stretch is a scaleY here, not scaleX: vertical-rl rotates each
   glyph 90° for rendering, so the letterform's own "width" (the axis we
   want to stretch, matching the wordmark/keywords treatment) ends up
   running down the screen's vertical axis */
.capabilities__label-text {
  writing-mode: vertical-rl;
  transform: rotate(180deg) scaleY(var(--stretch-x));
  font-size: var(--fs-2xl);
  font-weight: var(--fw-black);
  letter-spacing: -0.02em;
  text-transform: uppercase;
  line-height: 0.86;
}

.capabilities__list { display: flex; flex-direction: column; }

.cap-row {
  display: grid;
  grid-template-columns: minmax(3.5rem, 5.5rem) minmax(9rem, 17rem) 1fr;
  gap: var(--gutter);
  align-items: start;
  padding: clamp(1.5rem, 3vw, 2.75rem) 0;
  border-bottom: var(--rule-hair) solid var(--color-rule-invert);
}
.capabilities__list .cap-row:last-child { border-bottom: none; }

.cap-row__index {
  font-size: var(--fs-xl);
  font-weight: var(--fw-black);
  color: var(--color-accent);
  line-height: 1;
}

.cap-row__title {
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: clamp(1.35rem, 1.1rem + 1.1vw, 2rem);
  font-weight: var(--fw-black);
  text-transform: uppercase;
  letter-spacing: -0.01em;
  /* the numeral's much larger line-box rounds its glyph top slightly
     higher than the title's at line-height: 1 — nudge to match */
  transform: translateY(-1.3px);
  line-height: 1;
}

.cap-row__details {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem clamp(1.5rem, 3vw, 3rem);
}

.cap-row__details ul { display: flex; flex-direction: column; gap: 0.9rem; }

.cap-row__details li {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  color: var(--color-ink-invert-soft);
  padding-top: 0.7rem;
  border-top: var(--rule-hair) solid var(--color-rule-invert);
}
.cap-row__details li:first-child { border-top: none; padding-top: 0; }

.cap-row--contracting .cap-row__contracting {
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
}

/* the download action anchors to the bottom-right corner of the row,
   below the contracting details, rather than sitting inline with them */
/* the document link — an eyebrow/title/meta stack, right-aligned into
   the row's bottom-right corner, echoing the label pattern used
   everywhere else on the page instead of a filled button */
.doc-link {
  align-self: flex-end;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.35rem;
  text-align: right;
}

.doc-link__eyebrow {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-invert-soft);
}

.doc-link__title {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5em;
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  padding-bottom: 0.2em;
  border-bottom: var(--rule-hair) solid var(--color-rule-invert);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.doc-link:hover .doc-link__title { color: var(--color-accent); border-color: var(--color-accent); }

.doc-link__glyph { display: inline-block; transition: transform var(--dur-fast) var(--ease-out); }
.doc-link:hover .doc-link__glyph { transform: translateY(0.15em); }

.doc-link__meta {
  font-size: var(--fs-3xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-ink-invert-soft);
}

.contracting-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 1.25rem clamp(1.5rem, 3vw, 3rem);
}

.contracting-grid dt {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-invert-soft);
  margin-bottom: 0.35rem;
}

.contracting-grid dd {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
}

/* ============================================================
   Contact
   ============================================================ */
.contact {
  padding: var(--gap-block) var(--edge);
  border-bottom: var(--rule-hair) solid var(--color-rule);
}

.contact__heading {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-black);
  letter-spacing: -0.01em;
  text-transform: uppercase;
  line-height: 1.02;
  max-width: 16ch;
  margin: 1rem 0 2rem;
  overflow-wrap: anywhere;
}

.contact__details {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 2rem;
  font-size: var(--fs-body);
  font-weight: var(--fw-black);
}

.contact__details a { text-decoration: underline; text-underline-offset: 0.2em; transition: color var(--dur-fast) var(--ease-out); }
.contact__details a:hover { color: var(--color-accent-text); }
.contact__details p { color: var(--color-ink-soft); }

/* ============================================================
   Footer
   ============================================================ */
.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 2rem;
  padding: 1.25rem var(--edge);
  border-top: var(--rule-bold) solid var(--color-ink);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ============================================================
   Scroll-driven reveals — progressive enhancement, no JS
   Each horizontal block gets its own trigger range so blocks
   near the fold arrive tighter/faster than deeper ones.
   ============================================================ */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      opacity: 0;
      transform: translateY(1.5rem);
      animation: reveal-up linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 100%;
    }
    .reveal--tight { animation-range: entry 0% entry 65%; }
    .reveal--loose { animation-range: entry 10% cover 60%; }

    /* Staggering a view()-timeline animation has to happen via
       animation-range, not animation-delay: a view timeline tracks
       scroll position, not wall-clock time, so a time-valued delay just
       shifts (and can outrun) the range an element has left to complete
       its fade in. That's what left the page's last, most-delayed row
       (Contracting) stuck permanently semi-transparent — worse, my first
       fix still ended ranges on a "cover" point, which requires scrolling
       the element back *out* of view to ever be reached; for the last
       row on the page there's no scroll room left to do that. Ending
       every range at "entry 100%" instead fixes both: it only requires
       scrolling *to* full visibility, which every row — including the
       last one — always reaches. */
    .reveal--delay-1 { animation-range: entry 20% entry 100%; }
    .reveal--delay-2 { animation-range: entry 35% entry 100%; }
    .reveal--delay-3 { animation-range: entry 50% entry 100%; }
    .reveal--tight.reveal--delay-1 { animation-range: entry 20% entry 75%; }
    .reveal--tight.reveal--delay-2 { animation-range: entry 35% entry 85%; }

    .cap-row__details ul:nth-child(2) { animation: reveal-up linear both; animation-timeline: view(); animation-range: entry 15% entry 100%; }

    /* Stepped "typed" reveal for the Contact section, standing in for
       .reveal where a mechanical typed-on look fits better than a
       fade — same entry-100%-ending safety rule as above, since this
       section sits right at the very end of the page too. */
    .reveal--type {
      clip-path: inset(0 100% 0 0);
      animation-name: clip-reveal;
      animation-timing-function: steps(var(--type-steps, 12), end);
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 0% entry 100%;
    }
    .reveal--type.reveal--delay-1 { animation-range: entry 15% entry 100%; }
  }
}

@keyframes reveal-up {
  from { opacity: 0; transform: translateY(1.5rem); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 900px) {
  .statement__grid { grid-template-columns: 1fr; }
  .statement__copy { grid-column: 1 / -1; grid-template-columns: 1fr; }
  .statement__note { grid-column: 1; }
  .statement__keywords { margin-top: 0.5rem; }
}

/* Below tablet width: vertical CAPABILITIES turns horizontal */
@media (max-width: 767px) {
  .site-nav { order: 3; flex: 1 1 100%; justify-content: flex-start; }
  .site-header__inner { flex-wrap: wrap; }

  /* The keyword column's edge-bleed only reads as intentional when
     there's a lot of canvas left over to bleed into, as on desktop.
     On a phone screen the same stretch just runs the longest word
     ("Interoperability") past the edge and looks like broken overflow
     rather than a poster-style flourish — so drop the stretch here and
     size the text to fit safely instead, with overflow-wrap as a
     last-resort safety net if a word still doesn't fit. */
  .statement__keywords { transform: none; }
  .statement__keywords li {
    /* calibrated so "Interoperability" — the longest unbroken word —
       fits on one line with margin to spare; overflow-wrap is a
       last-resort net only, not the primary fit mechanism */
    font-size: clamp(1.2rem, 6.8vw, 3.5rem);
    overflow-wrap: anywhere;
    white-space: normal;
  }

  .capabilities { grid-template-columns: 1fr; }
  .capabilities__label {
    grid-row: auto;
    justify-content: flex-start;
    padding-bottom: 1.5rem;
    border-bottom: var(--rule-hair) solid var(--color-rule-invert);
    margin-bottom: 0.5rem;
  }
  .capabilities__label-text {
    writing-mode: horizontal-tb;
    /* back to a plain scaleX now that the text runs horizontally again;
       sized off the viewport (not --fs-2xl) so it can't overrun this
       single-column width once stretched */
    transform: scaleX(var(--stretch-x));
    transform-origin: left;
    font-size: clamp(1rem, 6.4vw, 3.25rem);
  }

  .cap-row {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
  .cap-row__index { order: 1; }
  .cap-row__title { order: 2; }
  .cap-row__details { order: 3; grid-template-columns: 1fr; }
  .cap-row__contracting { order: 3; }

  .contracting-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 480px) {
  .wordmark { letter-spacing: -0.01em; }
  .contracting-grid { grid-template-columns: 1fr; }
  .contact__heading { max-width: none; }
}
