/* ==========================================================================
   Etnika Group - corporate site
   One stylesheet. No build step, no external requests, no dependencies.

   Palette note: the accent is sampled from the group's own monogram field
   (#FAF0E1, oklch 0.959 0.023 78.2) and taken down the lightness ramp at the
   same hue to a usable bronze. The accent has exactly one job on this site -
   it marks things you can act on and where you are. Nothing decorative.

   --------------------------------------------------------------------------
   CLASS CONTRACT
   --------------------------------------------------------------------------
   Every class another page may rely on. Anything not listed here is private
   to the homepage and may be renamed without notice. Page-scoped rules belong
   in styles-pages.css, which loads after this file on secondary pages.

   STRUCTURE
     .shell                page width and gutters. Wrap every band of content.
     .section              a band with a hairline above it and vertical air.
     .section--dark        warm near-black band. Sets its own local ink tokens,
                           so .kicker / .lede / .btn invert automatically.
     .section--tight       half the usual vertical air.
     .row                  label column | content column (the document grammar).
     .row__body            the content column of a .row.
     .prose                text held to a readable measure.
     .duo  .duo__text      two equal columns, text beside media.
     .duo__media .duo__fit media column; --fit cover-fills the text's height.

   TYPE
     .kicker               small caps eyebrow above a heading.
     .display              editorial display line, larger than h1.
     .lede                 opening paragraph, one step up from body.
     .note                 quiet secondary text.
     .rule-list            hairline-separated list of short lines.

   NAVIGATION AND FOOTER (markup pinned - copy the pattern exactly)
     .nav .nav__inner .nav__mark .nav__list .nav__ext .nav__toggle
     .foot .foot__top .foot__cols .foot__col .foot__legal

   COMPONENTS
     .btn .btn--ghost      actions. --ghost is the quiet one.
     .grid-figures .figure .figure__value .figure__label .figure__unit
     .hub-card             one Group hub: city, entity, role, capability list.
     .flow-line            the drawn path behind the operating chain.
     .gallery-strip        full-width horizontal image sequence.
     .format               one retail format card.
     .principles           the four numbered operating principles.
     .netdiag              the Etnika OS network drawing.
     .euromap              the ambition map.
     .team-grid .team-card leadership portraits.
     .partners             the text-only partner wall.
     .reveal               lifts once on first entry. Static without JS.

   FORMS (unchanged from v1, still used by contact.html)
     .form .field .hp .btn .formstatus .printonly .registry
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Surfaces and ink. Hue 78 throughout, chroma kept under 0.01 on neutrals
     so the greys read as off-white and near-black, never as cream or brown. */
  --paper:        #F7F2E8;  /* oklch 0.962 0.017 84 - soft beige, 16.2:1 ink */
  --paper-sunk:   #F1EADC;  /* deeper beige - image frame fallback           */
  --ink:          #181613;  /* oklch 0.201 0.007 78 - 16.2:1 on paper        */
  --ink-2:        #474540;  /* oklch 0.391 0.009 78 -  8.6:1 on paper        */
  --ink-3:        #6A6763;  /* oklch 0.517 0.007 78 -  5.0:1 on paper, 4.7:1 on sunk */
  --rule:         #DDDAD6;  /* hairline, quiet                               */
  --rule-strong:  #BDBAB6;  /* hairline, structural / default underlines     */

  --accent:       #73592D;  /* oklch 0.481 0.070 78 -  5.9:1 on paper        */
  --accent-deep:  #5C4215;  /* oklch 0.399 0.070 78 -  8.4:1 on paper        */

  --night:        #12100D;  /* footer band                                   */
  --night-ink:    #D4D0CB;  /* 12.4:1 on night                               */
  --night-ink-2:  #A7A49F;  /*  7.7:1 on night                               */
  --night-rule:   #35322E;

  /* Dark sections. Warmer and one step lighter than the footer band so the
     footer still reads as the end of the page rather than one more section. */
  --ink-section:  #191713;  /* paper on this is 14.8:1                       */
  --sect-ink:     #EFE9DC;  /* body ink on --ink-section                     */
  --sect-ink-2:   #B6AFA1;  /*  8.2:1 on --ink-section                       */
  --sect-rule:    #33302A;
  --sect-land:    #3A342B;  /* map land fill, lifted so coastlines survive a phone */
  --sect-accent:  #C8873A;  /* the bronze lifted to work on near-black       */

  --field:        #FFFFFF;  /* form inputs - 18.9:1 for ink                  */

  /* Type. A system serif for headings against the system UI sans for text:
     a contrast-axis pairing, and it costs nothing to download. */
  --serif: "Iowan Old Style", Charter, "Sitka Text", Cambria, Georgia,
           "Times New Roman", Times, serif;
  --sans:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
           Helvetica, Arial, sans-serif;

  /* Strict scale, ≥1.25 between steps. */
  --t-fine:    0.8125rem;                                   /* 13px */
  --t-small:   0.875rem;                                    /* 14px */
  --t-body:    1rem;                                        /* 16px */
  --t-lede:    clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);    /* 17 → 20 */
  --t-h3:      1.25rem;                                     /* 20px */
  --t-h2:      clamp(1.375rem, 1.2rem + 0.75vw, 1.75rem);   /* 22 → 28 */
  --t-h1:      clamp(2rem, 1.45rem + 2.3vw, 3rem);          /* 32 → 48 */
  --t-place:   clamp(1.75rem, 1.2rem + 2.4vw, 2.75rem);     /* 28 → 44 */
  /* One step above h1, for the lines a visitor is meant to remember. */
  --t-display: clamp(2.25rem, 1.35rem + 3.9vw, 4rem);       /* 36 → 64 */
  /* Mid-page pull statements: one step below the headline scale, so a
     paragraph set as .display no longer ties the page's own h1. */
  --t-pull:    clamp(1.75rem, 1.1rem + 2.8vw, 3rem);        /* 28 → 48 */
  --t-figure:  clamp(2.5rem, 1.6rem + 3.2vw, 3.75rem);      /* 40 → 60 */

  /* Space. */
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;     --s-7: 3rem;     --s-8: 4rem;

  --band:    clamp(3rem, 1.5rem + 6vw, 5.5rem);   /* between sections */
  --band-lg: clamp(4rem, 2rem + 8vw, 7.5rem);     /* around the hero  */

  --gutter:  clamp(1.25rem, 4vw, 3rem);
  --shell:   66rem;      /* 1056px */
  /* Measure in rem, not ch: the `0` glyph of the UI sans is far wider than its
     average character, so 68ch renders as ~90 characters. 33rem lands at ~70. */
  --measure: 33rem;

  color-scheme: light;
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.65;
}

img { display: block; max-width: 100%; height: auto; }

h1, h2, h3 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  text-wrap: balance;
}

h1 {
  font-size: var(--t-h1);
  line-height: 1.12;
  letter-spacing: -0.018em;
  max-width: 20ch;
}

h2 {
  font-size: var(--t-h2);
  line-height: 1.28;
  letter-spacing: -0.008em;
}

h3 {
  font-size: var(--t-h3);
  line-height: 1.3;
  letter-spacing: -0.006em;
}

p { margin: 0; text-wrap: pretty; }
p + p { margin-top: var(--s-4); }

ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 1px;
}

::selection { background: #E8DEC9; color: var(--ink); }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  padding: var(--s-3) var(--s-4);
  background: var(--ink);
  color: var(--paper);
  font-size: var(--t-small);
  text-decoration: none;
}
.skip:focus { left: var(--s-4); top: var(--s-4); }

/* Text for screen readers only, e.g. the new-tab note on external links. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   3. Shell
   -------------------------------------------------------------------------- */

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

main { flex: 1; }

/* Label column | content column. The document grammar of the whole site:
   the section heading lives in the margin, the prose sits at a fixed measure. */
.row { display: grid; gap: var(--s-5); }

/* Zero-specificity default so any component rule below can override it. */
:where(.row > .row__body) > * + * { margin-top: var(--s-4); }

.prose { max-width: var(--measure); }

@media (min-width: 56.25em) {
  .row {
    grid-template-columns: minmax(8rem, 14rem) minmax(0, 1fr);
    column-gap: clamp(2rem, 4vw, 3.5rem);
  }
  /* Sit the margin heading's baseline on the first baseline of the body text. */
  .row > h2 { margin-top: -0.18em; }
}

/* --------------------------------------------------------------------------
   4. Navigation

   A paper band above the page, not a floating bar: the hero starts below it
   and nothing overlays the photograph. The external retail link is separated
   by a rule because it leaves the corporate site.
   -------------------------------------------------------------------------- */

.nav { border-bottom: 1px solid var(--rule); }

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding-block: clamp(1rem, 2.2vw, 1.5rem);
}

.nav__mark { display: block; flex: none; text-decoration: none; }

.nav__mark img {
  width: auto;
  height: clamp(2.125rem, 4vw, 2.875rem);  /* 34 → 46px */
}

.nav__list {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  column-gap: clamp(0.875rem, 2.1vw, 1.6rem);
  row-gap: var(--s-2);
}

.nav__list a {
  display: inline-block;
  padding-block: 0.2rem;
  border-bottom: 1px solid transparent;
  color: var(--ink-2);
  font-size: var(--t-fine);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color 120ms ease, border-color 120ms ease;
}

.nav__list a:hover { color: var(--ink); }

.nav__list a[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

/* Leaves the corporate site: given its own compartment. text-decoration is
   reset here because the UA default underline survives otherwise: .nav__ext
   is a sibling of .nav__list, not a descendant, so the list reset misses it. */
.nav__ext {
  margin-left: clamp(0.5rem, 1.4vw, 1rem);
  padding-left: clamp(0.75rem, 2vw, 1.4rem);
  border-left: 1px solid var(--rule-strong);
  color: var(--accent-deep) !important;
  text-decoration: none;
}

.nav__ext:hover { border-bottom-color: var(--accent) !important; }

.nav__toggle {
  display: none;
  flex: none;
  padding: 0.7rem 0.9rem;
  font: inherit;
  font-size: var(--t-fine);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  cursor: pointer;
}

/* The disclosure state, readable without reading: a triangle that flips. */
.nav__toggle::after {
  content: "\25BE";
  display: inline-block;
  margin-left: 0.45em;
  transition: transform 160ms ease;
}

.nav__toggle[aria-expanded="true"]::after { transform: rotate(180deg); }

/* Collapse at 1000px, not 960: between 961 and ~995px the full desktop row
   no longer fits and wraps "Contact" onto a second line, so the toggle takes
   over while the row still reads as one line. */
@media (max-width: 62.5em) {
  .nav__inner { flex-wrap: wrap; }
  .nav__toggle { display: block; }
  /* The flex item here is the <nav> WRAPPER, not .nav__list inside it. Without
     this, the wrapper (empty-looking while the list is closed) still claims
     the right-hand space-between slot and strands the Menu button mid-bar.
     Sending the wrapper to its own full-width row leaves exactly two items on
     row one - wordmark left, Menu flush right - and gives the open list the
     full width its own rules below already assume. */
  .nav__inner > nav { order: 3; width: 100%; }
  .nav__list {
    display: none;
    order: 3;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    row-gap: 0;
    margin-top: var(--s-3);
    padding-top: var(--s-3);
    border-top: 1px solid var(--rule);
  }
  .nav__list.is-open { display: flex; }
  .nav__list li { width: 100%; }
  /* Full-row targets at 44pt and up, separated by a hairline instead of a
     gap, so a thumb cannot land between two links or on dead space beside
     one. */
  .nav__list li + li { border-top: 1px solid var(--rule); }
  .nav__list a {
    display: block;
    width: 100%;
    padding-block: 0.7rem;
    font-size: var(--t-small);
  }
  .nav__ext { margin-left: 0; padding-left: 0; border-left: 0; }
}

/* Without JavaScript the toggle can do nothing, so the menu stays open. */
.nav__toggle[hidden] { display: none; }
html:not(.js-ready) .nav__list { display: flex; }

/* --------------------------------------------------------------------------
   5. Page furniture
   -------------------------------------------------------------------------- */

.hero { padding-block: var(--band-lg) var(--band); }

.hero .lede { margin-top: clamp(1.25rem, 2.5vw, 2rem); }

.lede {
  max-width: 32rem;
  color: var(--ink-2);
  font-size: var(--t-lede);
  line-height: 1.58;
  text-wrap: pretty;
}

/* Section rules are drawn inside the gutter so they land exactly on the
   content columns rather than bleeding past them by the padding. */
.section,
.onward { position: relative; }

.section::before,
.onward::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  border-top: 1px solid var(--rule);
}

.section { padding-block: var(--band); }

.section:last-of-type { padding-bottom: var(--band-lg); }

/* The nav already draws a hairline at its bottom edge; a section opening the
   page directly under it would double the line. */
main > .section:first-child::before { display: none; }

/* Quiet forward wayfinding, so a page ends rather than stops. */
.onward { padding-block: var(--s-6) var(--band); }

.onward a {
  display: inline-block;
  max-width: 100%;
  font-family: var(--serif);
  font-size: var(--t-h3);
  letter-spacing: -0.006em;
  text-decoration: none;
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 0.1em;
  transition: border-color 120ms ease, color 120ms ease;
}

.onward a:hover { color: var(--accent-deep); border-bottom-color: var(--accent); }

.onward__cue {
  display: block;
  margin-bottom: var(--s-2);
  color: var(--ink-3);
  font-family: var(--sans);
  font-size: var(--t-small);
  letter-spacing: 0.01em;
}

/* --------------------------------------------------------------------------
   6. Text-level pieces
   -------------------------------------------------------------------------- */

.prose a,
.link {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--rule-strong);
  transition: color 120ms ease, text-decoration-color 120ms ease;
}

.prose a:hover,
.link:hover {
  color: var(--accent-deep);
  text-decoration-color: var(--accent);
}

.note { color: var(--ink-2); }

/* Operating-entity attribution under a business line. */
.entity {
  margin-top: var(--s-5);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
  max-width: var(--measure);
  font-size: var(--t-small);
  color: var(--ink-2);
}

.entity__label {
  display: block;
  color: var(--ink-3);
  font-size: var(--t-fine);
}

/* --------------------------------------------------------------------------
   7. Leadership
   -------------------------------------------------------------------------- */

.people > * + * {
  margin-top: var(--band);
  padding-top: var(--band);
  border-top: 1px solid var(--rule);
}

.person { display: grid; gap: var(--s-5); }

@media (min-width: 40em) {
  .person {
    grid-template-columns: 15rem minmax(0, 1fr);
    column-gap: clamp(1.75rem, 4vw, 3rem);
    align-items: start;
  }
}

/* Architectural crop. Both source photographs are 2:3; the frame is 4:5 and
   each image is placed by hand inside it, so a full-length environmental shot
   and a studio portrait sit at the same scale and read as one set.
   --pw / --px / --py place the image inside the frame; grayscale on both is
   what makes a colour in-store photograph and a B&W studio portrait agree.
   Placement lives here rather than in a style attribute so the pages stay
   free of inline CSS and survive a strict style-src policy. */
.portrait {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  max-width: 15rem;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
}

.portrait img {
  position: absolute;
  top: var(--py, 0);
  left: var(--px, 0);
  width: var(--pw, 100%);
  max-width: none;
  height: auto;
  filter: grayscale(1);
}

.person__name { margin-bottom: var(--s-1); }

.person__role {
  color: var(--ink-3);
  font-size: var(--t-small);
  letter-spacing: 0.01em;
}

.person__bio {
  margin-top: var(--s-4);
  max-width: 30rem;
  color: var(--ink-2);
}

/* --------------------------------------------------------------------------
   8. Locations
   -------------------------------------------------------------------------- */

.places > * + * {
  margin-top: var(--band);
  padding-top: var(--band);
  border-top: 1px solid var(--rule);
}

.place__city {
  font-family: var(--serif);
  font-size: var(--t-place);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.place__country {
  display: block;
  margin-top: var(--s-2);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: var(--t-body);
  letter-spacing: 0;
}

.place__role { color: var(--ink-2); max-width: var(--measure); }

.place__entity {
  margin-top: var(--s-2);
  color: var(--ink-3);
  font-size: var(--t-small);
}

/* The city sits in the margin column; drop it so its baseline meets the first
   line of the description rather than its cap-height floating above. */
@media (min-width: 56.25em) {
  .row > .place__city { margin-top: -0.5em; }
}

/* --------------------------------------------------------------------------
   9. Contact - form and entity registry
   -------------------------------------------------------------------------- */

.form { max-width: 30rem; margin-top: clamp(2rem, 5vw, 3rem); }

.field + .field { margin-top: var(--s-5); }

.field label {
  display: block;
  margin-bottom: var(--s-2);
  color: var(--ink-2);
  font-size: var(--t-small);
}

/* The boundary is the control: #BDBAB6 on paper measured 1.7:1, so the
   fields read as ghosts. --ink-3 holds 4.7:1 against paper and 5:1 against
   the white fill while staying a hairline. */
.field input,
.field select,
.field textarea {
  display: block;
  width: 100%;
  padding: 0.7rem 0.8rem;
  font: inherit;
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--ink-3);
  border-radius: 2px;
  transition: border-color 120ms ease;
}

.field select {
  appearance: none;
  padding-right: 2.4rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23474540' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
}

.field textarea { resize: vertical; min-height: 8rem; }

.field input:hover,
.field select:hover,
.field textarea:hover,
.field input:focus,
.field select:focus,
.field textarea:focus { border-color: var(--ink-2); }

/* Validation is styled only once the visitor has left the field, so nothing
   nags mid-typing. The message element is filled by contact.html's script
   and announced through aria-describedby; the colour never stands alone. */
.field input:user-invalid,
.field select:user-invalid,
.field textarea:user-invalid,
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: #8C2F1E;
  border-width: 2px;
  padding: calc(0.7rem - 1px) calc(0.8rem - 1px);
}

.field__error {
  margin-top: var(--s-2);
  color: #8C2F1E;
  font-size: var(--t-small);
}

.field__error:empty { display: none; }

/* Honeypot: present for machines, gone for people and screen readers. */
.hp {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.btn {
  display: inline-block;
  margin-top: var(--s-6);
  padding: 0.7rem 1.5rem;
  font: inherit;
  font-size: var(--t-small);
  letter-spacing: 0.01em;
  color: var(--paper);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 2px;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.btn:hover { background: var(--accent-deep); border-color: var(--accent-deep); }

/* Solid quiet grey, not opacity: a half-transparent label fell to 3.3:1, and
   "Sending..." is the only feedback shown for the whole network call. */
.btn[disabled] { cursor: default; background: var(--ink-3); border-color: var(--ink-3); color: var(--paper); }

.formstatus {
  max-width: 30rem;
  margin-top: var(--s-5);
  color: var(--ink);
  font-size: var(--t-body);
}

.formstatus:empty { display: none; }

.printonly { display: none; }

.registry {
  display: grid;
  gap: var(--s-5);
  margin-top: clamp(2.5rem, 6vw, 4rem);
  padding-top: var(--s-6);
  border-top: 1px solid var(--rule);
}

@media (min-width: 46em) {
  /* Sized to content, not to a fixed three: the registry currently holds one
     entry, and empty tracks read as a mistake. */
  .registry { grid-template-columns: repeat(auto-fit, minmax(0, 18rem)); column-gap: var(--s-6); }
}

.registry__name {
  font-family: var(--serif);
  font-size: var(--t-h3);
  letter-spacing: -0.006em;
}

.registry__meta { margin-top: var(--s-1); color: var(--ink-2); font-size: var(--t-small); }

/* --------------------------------------------------------------------------
   10. Footer

   The wordmark and the brand idea, then five columns of wayfinding, then the
   entity registry and the legal line. Markup is pinned: every page uses it.
   -------------------------------------------------------------------------- */

.foot {
  margin-top: auto;
  background: var(--night);
  color: var(--night-ink);
  /* The global focus ring is bronze for paper; on the night band the same
     bronze measures 2.9:1. The lifted section accent reads 6.3:1 here. */
  --accent: var(--sect-accent);
  --accent-deep: var(--sect-accent);
}

.foot__inner { padding-block: clamp(3rem, 6vw, 5rem) clamp(2rem, 4vw, 3rem); }

.foot__top {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: var(--s-4) var(--s-7);
  padding-bottom: clamp(2rem, 4vw, 3rem);
  margin-bottom: clamp(2rem, 4vw, 3rem);
  border-bottom: 1px solid var(--night-rule);
}

.foot__mark { width: auto; height: 2.25rem; flex: none; }

.foot__idea {
  font-family: var(--serif);
  font-size: var(--t-h3);
  letter-spacing: -0.006em;
  color: var(--night-ink);
}

.foot__cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-6) var(--s-5);
}

@media (min-width: 46em) {
  .foot__cols { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

.foot__col h3 {
  margin: 0 0 var(--s-3);
  font-family: var(--sans);
  font-size: var(--t-fine);
  font-weight: 400;
  letter-spacing: 0.09em;
  color: var(--night-ink-2);
}

.foot__col li + li { margin-top: var(--s-2); }

.foot__col a,
.foot__col span {
  display: inline-block;
  padding-block: var(--s-1);
  font-size: var(--t-small);
  color: var(--night-ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 120ms ease;
}

.foot__col a:hover { border-bottom-color: var(--night-ink-2); }

/* Under a thumb the wayfinding rows become full-height targets: 14px text in
   a 45px row, the padding carrying the separation the margins used to. */
@media (max-width: 62.5em) {
  .foot__col a,
  .foot__col span { display: block; padding-block: 0.7rem; }
  .foot__col li + li { margin-top: 0; }
}

/* CasaPro has no public destination. It is named, never linked. */
.foot__col span { color: var(--night-ink-2); }

.foot__legal {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: var(--s-4);
  border-top: 1px solid var(--night-rule);
  font-size: var(--t-fine);
  color: var(--night-ink-2);
}


/* --------------------------------------------------------------------------
   11. Motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   12. Print
   -------------------------------------------------------------------------- */

@media print {
  :root { --gutter: 0; --band: 1.5rem; --band-lg: 1.5rem; }

  body { background: #FFF; color: #000; font-size: 11pt; line-height: 1.45; }

  .nav__list, .nav__ext, .nav__toggle, .skip, .onward,
  .hero__cue, .gallery-strip, .netdiag, .euromap, .wmap, .flow-line { display: none; }

  .nav { border-bottom: 1px solid #999; }
  .nav__inner { padding-block: 0 0.5rem; }
  .nav__mark img { height: 34px; }

  .shell { max-width: none; padding-inline: 0; }

  /* Dark bands and photographs cost a page of toner and say nothing on paper. */
  .section--dark, .hero, .closing {
    background: none !important;
    color: #000 !important;
    min-height: 0 !important;
  }
  .section--dark img, .hero img, .closing img { display: none; }

  .foot { background: none; color: #000; border-top: 1px solid #999; }
  .foot__mark { display: none; }
  .foot__col a, .foot__col span,
  .foot__legal, .foot__col h3 { color: #000; }
  .foot__legal, .foot__top { border-color: #999; }

  .lede, .note, .person__bio, .place__role, .entity,
  .registry__meta, .figure__label { color: #000; }

  /* A form is useless on paper; print the address instead. */
  .form, .formstatus { display: none; }
  .printonly { display: block; margin-top: 1rem; }

  .section::before, .people > * + *, .places > * + * { border-top-color: #999; }

  h1, h2, h3, .place__city, .display { break-after: avoid; }
  .person, .place, .portrait, .figure, .hub-card, .format { break-inside: avoid; }

  .reveal { opacity: 1 !important; transform: none !important; }

  a { text-decoration: none; }
}

/* --------------------------------------------------------------------------
   13. Figures - the v1 four-up glance grid (secondary pages)
   -------------------------------------------------------------------------- */

.figures {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-7) var(--s-5);
}

@media (min-width: 56.25em) {
  /* Content-sized columns with the free space shared between them. Equal 1fr
     tracks put a two-character figure and a seven-character one in identical
     boxes, so the AIR between the figures varied wildly. Flexed content boxes
     plus space-between makes the gutters what the eye actually measures. */
  .figures {
    display: flex;
    justify-content: space-between;
    column-gap: var(--s-5);
  }
  .figure {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 11.5rem;
  }
  .figure__value { white-space: nowrap; }
}

.figure__value {
  font-family: var(--serif);
  /* Not --t-place: at 44px the widest figure in this four-up grid is wider
     than a quarter of the row, so it can never sit evenly. This clamp tops out
     where the widest value still fits its box with air. */
  font-size: clamp(1.6rem, 1.02rem + 1.5vw, 2.2rem);
  line-height: 1.05;
  letter-spacing: -0.012em;
  font-variant-numeric: lining-nums;
}

.figure__label {
  margin-top: var(--s-2);
  color: var(--ink-2);
  font-size: var(--t-small);
  line-height: 1.45;
  text-wrap: pretty;
}

.figures__note {
  margin-top: var(--s-6);
  color: var(--ink-3);
  font-size: var(--t-fine);
  max-width: var(--measure);
}

/* --------------------------------------------------------------------------
   14. Plates, image pairs and the sourcing globe
   -------------------------------------------------------------------------- */

/* A full-width editorial plate: one image, one caption, framed like a
   document figure rather than a banner. */
.plate { margin: 0; }

.plate img {
  width: 100%;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
}

.plate figcaption,
.duo__media figcaption,
.globe figcaption {
  margin-top: var(--s-3);
  color: var(--ink-3);
  font-size: var(--t-fine);
}

/* The sourcing globe. A canvas drawn by the small script at the foot of the
   page: an orthographic earth, slowly turning, with the group's sea routes
   traced from origin ports to Gdansk and on to Warsaw. Colours are read from
   the custom properties at draw time so the figure can never drift from the
   palette. Reduced motion gets a single still frame. */
.globe { margin: 0; }

.globe canvas {
  display: block;
  width: 100%;
  height: auto;
}


/* --------------------------------------------------------------------------
   15. Split layouts - text beside media
   -------------------------------------------------------------------------- */

/* A section split in two: heading and prose on the left, one piece of media
   filling the right. The media stretches to the height of the text so the
   column reads full, not floated. */
.duo {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: stretch;
}

@media (min-width: 56.25em) {
  .duo { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

.duo__text > h2 { margin-bottom: var(--s-5); }

.duo__block + .duo__block { margin-top: clamp(2.5rem, 5vw, 4rem); }

.duo__block > h2 { margin-bottom: var(--s-5); }

.duo__media {
  margin: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.duo__media img {
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  object-fit: cover;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
}

@media (max-width: 56.24em) {
  .duo__media img { height: auto; }
}

/* The globe sits centred in its column rather than cover-stretched. */
.duo__media--globe { justify-content: center; }

.globe-legend {
  margin-top: var(--s-4);
  color: var(--ink-3);
  font-size: var(--t-fine);
  line-height: 1.6;
}

.globe-legend p { margin: 0; }

.globe-legend strong { color: var(--ink-2); font-weight: 500; }


/* Fit-to-text media: the figure adopts the height of the text column and the
   image cover-fills it, so a tall photograph never drags the section past its
   own prose. The caption sits outside the fitted box. */
.duo__fit {
  position: relative;
  flex: 1 1 auto;
  min-height: 14rem;
}

.duo__fit img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
}

@media (max-width: 56.24em) {
  .duo__fit { min-height: 0; }
  .duo__fit img { position: static; height: auto; }
}

/* A second image stacked under the text in the left column, growing to meet
   the media column's height. */
.duo__text--fill { display: flex; flex-direction: column; }

.duo__text--fill .duo__stack {
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

/* ==========================================================================
   V2 - the homepage system

   Everything below was added for the long-form Group homepage. It is additive:
   nothing above changed shape, so the secondary pages keep working while they
   are rebuilt. Two ideas carry the whole thing.

   One: a dark band does not get its own set of classes. `.section--dark`
   redefines --paper and --ink locally, so every component inside it inverts by
   inheritance and there is exactly one definition of what a lede or a button
   looks like. Two: nothing on this page is a card. Structure is made with
   hairlines, column position and air, which is why there is not a single
   box-shadow or border-radius in the sections below.
   ========================================================================== */

/* --------------------------------------------------------------------------
   16. Bands and inversion
   -------------------------------------------------------------------------- */

.section--tight { padding-block: clamp(2rem, 1rem + 4vw, 3.5rem); }

/* Full-bleed bands: no shell, no side gutters, no hairline. */
.section--flush { padding-inline: 0; }
.section--flush::before { display: none; }

.section--dark {
  --paper:       var(--ink-section);
  --paper-sunk:  #221F19;
  --ink:         var(--sect-ink);
  --ink-2:       var(--sect-ink-2);
  --ink-3:       var(--sect-ink-2);
  --rule:        var(--sect-rule);
  --rule-strong: #4A453C;
  --accent:      var(--sect-accent);
  --accent-deep: var(--sect-accent);
  background: var(--ink-section);
  color: var(--sect-ink);
}

.section--dark::before { display: none; }

/* Two dark bands in a row would read as one; give the seam a hairline back. */
.section--dark + .section--dark { border-top: 1px solid var(--sect-rule); }

/* A light section directly under a dark band needs no hairline: the band
   edge itself is the seam, and a grey rule doubled it. */
.section--dark + .section::before { display: none; }

/* --------------------------------------------------------------------------
   17. Editorial type
   -------------------------------------------------------------------------- */

.kicker {
  display: block;
  margin-bottom: clamp(1rem, 2.2vw, 1.75rem);
  color: var(--ink-3);
  font-family: var(--sans);
  font-size: var(--t-fine);
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.display {
  margin: 0;
  max-width: 16ch;
  font-family: var(--serif);
  font-size: var(--t-display);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.display--wide { max-width: 22ch; }

/* Second line of a two-line statement, set back so the pair reads as one
   thought with a beat in the middle rather than as two headings. */
.display span { display: block; color: var(--ink-2); }

/* A paragraph set as display is a pull statement, not the page title: one
   step down, so it can never tie the h1 it lives under. */
p.display { font-size: var(--t-pull); }

.section__head { max-width: 46rem; }
.section__head + * { margin-top: clamp(2.25rem, 5vw, 3.5rem); }
.section__head .lede { margin-top: clamp(1.25rem, 2.6vw, 1.75rem); }

.rule-list > li {
  padding-block: var(--s-3);
  border-top: 1px solid var(--rule);
  font-size: var(--t-small);
  color: var(--ink-2);
}
.rule-list > li:last-child { border-bottom: 1px solid var(--rule); }

/* --------------------------------------------------------------------------
   18. Actions
   -------------------------------------------------------------------------- */

.btnrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4) var(--s-5);
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
}

.btnrow .btn { margin-top: 0; }

.btn {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}

.btn--ghost {
  color: var(--ink);
  background: none;
  border-color: var(--rule-strong);
}

.btn--ghost:hover {
  color: var(--accent-deep);
  background: none;
  border-color: var(--accent);
}

/* A link that behaves like a next step without shouting like a button. */
.step-link {
  display: inline-block;
  font-family: var(--serif);
  font-size: var(--t-h3);
  letter-spacing: -0.006em;
  text-decoration: none;
  border-bottom: 1px solid var(--rule-strong);
  padding-bottom: 0.12em;
  transition: color 120ms ease, border-color 120ms ease;
}

.step-link:hover { color: var(--accent-deep); border-bottom-color: var(--accent); }

/* --------------------------------------------------------------------------
   19. Hero

   One photograph, held at 92% of the viewport so the page always shows that
   it continues. The scrim is a gradient rather than a flat wash: the sky
   keeps its light and the type keeps its contrast.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: min(92svh, 48rem);
  padding: 0;
  overflow: hidden;
  background: var(--ink-section);
  color: var(--sect-ink);

  --paper:       var(--ink-section);
  --ink:         var(--sect-ink);
  --ink-2:       #D6CFC0;
  --ink-3:       var(--sect-ink-2);
  --rule-strong: #6C6459;
  --accent:      var(--sect-accent);
  --accent-deep: var(--sect-accent);
}

.hero::before { display: none; }

.hero__media { position: absolute; inset: 0; }

/* The building's etnika sign lives at ~64-78% of the image width. Wide
   viewports never crop horizontally (image aspect 1.5), so this position is
   invisible on desktop; as the viewport narrows and cover starts cutting the
   sides, the crop window anchors on the sign instead of the dead centre —
   phones keep the name on the building in frame. */
.hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 71% 50%; }

/* The scrim holds strong across the text column: sampled against the crop,
   the lede's worst pixel reads ~6.5:1 with these stops where the old ramp
   let it fall to 1.3:1 on a phone. The sky still keeps its light at the
   trailing edge. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(100deg,
      rgba(10, 9, 7, 0.92) 0%,
      rgba(10, 9, 7, 0.88) 30%,
      rgba(10, 9, 7, 0.72) 56%,
      rgba(10, 9, 7, 0.30) 80%,
      rgba(10, 9, 7, 0.06) 100%),
    linear-gradient(to top,
      rgba(10, 9, 7, 0.60) 0%,
      rgba(10, 9, 7, 0.22) 38%,
      rgba(10, 9, 7, 0.02) 66%,
      rgba(10, 9, 7, 0.34) 100%);
}

.hero__body {
  position: relative;
  width: 100%;
  padding-block: var(--band-lg) clamp(3rem, 7vw, 5rem);
}

.hero .display { max-width: 14ch; }
.hero .display span { color: var(--sect-ink); opacity: 0.72; }
.hero .lede { max-width: 34rem; margin-top: clamp(1.5rem, 3vw, 2rem); }

/* A control edge over a photograph needs 3:1 against its brightest pixels;
   the remapped --rule-strong (#6C6459) cannot give it. */
.hero .btn--ghost,
.closing .btn--ghost { border-color: var(--sect-ink-2); }

.hero__cue {
  display: block;
  margin-top: clamp(2rem, 5vw, 3.5rem);
  color: var(--sect-ink-2);
  font-size: var(--t-fine);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Two stages: the statement, then everything that supports it. The scroll cue
   is deliberately NOT a third stage. A delayed fill-both animation is the one
   way a piece of copy can end up invisible if the animation never starts, and
   a cue that sometimes is not there is worse than a cue that never moves. */
@media (prefers-reduced-motion: no-preference) {
  .hero__stage { animation: rise 900ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  .hero__stage--2 { animation-delay: 340ms; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   20. Cities line
   -------------------------------------------------------------------------- */

.cities {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4em 0.75em;
  margin-top: clamp(2rem, 5vw, 3.5rem);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  border-top: 1px solid var(--rule);
  font-family: var(--serif);
  font-size: var(--t-place);
  line-height: 1.1;
  letter-spacing: 0.02em;
}

.cities .sep { color: var(--ink-3); font-size: 0.5em; }

/* A kicker used as a sub-label inside a block that already has one. */
.kicker--tight { margin-top: clamp(1.75rem, 4vw, 2.5rem); margin-bottom: var(--s-3); }

/* --------------------------------------------------------------------------
   21. Figures

   A register, not a row of tiles. The value sits in its own column at a fixed
   width so five very different numbers share one left edge, and the hairlines
   do the work that a card would otherwise do badly.
   -------------------------------------------------------------------------- */

.grid-figures { border-top: 1px solid var(--rule-strong); }

.grid-figures .figure {
  display: grid;
  gap: var(--s-1) clamp(1.5rem, 4vw, 3rem);
  padding-block: clamp(1.25rem, 2.8vw, 2rem);
  border-bottom: 1px solid var(--rule);
  max-width: none;
}

@media (min-width: 46em) {
  /* The fixed tracks are capped against the row's own width, so between the
     46em breakpoint and full shell (and at 200% text) the description column
     keeps enough room to hold each label on one line. */
  .grid-figures .figure {
    grid-template-columns:
      minmax(0, min(15rem, 25%)) minmax(0, min(13rem, 21%)) minmax(0, 1fr);
    align-items: baseline;
  }
}

.grid-figures .figure__value {
  font-family: var(--serif);
  font-size: var(--t-figure);
  line-height: 1;
  letter-spacing: -0.024em;
  font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap;
}

.figure__unit {
  color: var(--ink-2);
  font-size: var(--t-fine);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.grid-figures .figure__label {
  margin-top: 0;
  color: var(--ink-3);
  font-size: var(--t-small);
}

/* --------------------------------------------------------------------------
   22. Maps - shared drawing

   Both maps are the same land outline at the same projection. Only what is
   drawn on top of it changes.
   -------------------------------------------------------------------------- */

.wmap { display: block; width: 100%; height: auto; overflow: visible; }

.wmap__land { fill: var(--sect-land); }

.wmap__leg {
  fill: none;
  stroke: var(--sect-accent);
  stroke-width: 1.6;
  stroke-linecap: round;
  opacity: 0.9;
  transition: stroke-dashoffset 1100ms cubic-bezier(0.4, 0, 0.2, 1);
}

.wmap__halo {
  fill: var(--sect-accent);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0.4);
  transition: opacity 600ms ease, transform 600ms ease;
}

.wmap__pin {
  fill: var(--sect-ink);
  opacity: 0.25;
  transition: opacity 500ms ease, fill 500ms ease;
}

.wmap__label {
  fill: var(--sect-ink);
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.14em;
  opacity: 0;
  transition: opacity 600ms ease;
}

.wmap__hub.is-on .wmap__halo { opacity: 0.16; transform: scale(1); }
.wmap__hub.is-on .wmap__pin { opacity: 1; fill: var(--sect-accent); }
.wmap__hub.is-on .wmap__label { opacity: 1; }

/* The hub in play breathes, so the eye knows where the sequence has got to. */
@media (prefers-reduced-motion: no-preference) {
  .wmap__hub.is-on .wmap__halo { animation: hubpulse 3.2s ease-in-out infinite; }
}

@keyframes hubpulse {
  0%, 100% { opacity: 0.16; transform: scale(1); }
  50%      { opacity: 0.05; transform: scale(1.5); }
}

/* Sourcing map: the named origins and the wider network. */
.wmap--sourcing .wmap__land { fill: #302B23; }
.wmap--sourcing .wmap__net { fill: var(--sect-ink); opacity: 0; transition: opacity 900ms ease; }
.wmap--sourcing .wmap__halo { opacity: 0; transform: scale(1); }
.wmap--sourcing .wmap__pin { opacity: 0; fill: var(--sect-accent); }

#sourcing-map.is-in .wmap__net { opacity: 0.26; }
#sourcing-map.is-in .wmap__pin { opacity: 1; transition: opacity 700ms ease calc(var(--i, 0) * 90ms), r 220ms ease; }
#sourcing-map.is-in .wmap__halo { opacity: 0.14; transition: opacity 700ms ease calc(var(--i, 0) * 90ms + 200ms); }

.wmap__origin.is-lit .wmap__pin { r: 6px; }
.wmap__origin.is-lit .wmap__halo { opacity: 0.3; }

/* The maps scale with their box, so user-space sizes must grow as the box
   shrinks: a 12px user-space label renders at 5px on a 375px viewport. These
   steps keep labels at or above ~11px rendered and pins visibly larger than
   a speck at every width. */
@media (max-width: 56.25em) {
  .wmap__label { font-size: 20px; }
  .wmap__pin { r: 7px; }
  .wmap__halo { r: 24px; }
  .wmap__leg { stroke-width: 2.8; }
  .wmap--sourcing .wmap__pin { r: 6px; }
  .wmap--sourcing .wmap__halo { r: 18px; }
  .wmap__net { r: 4px; }
  .wmap__origin.is-lit .wmap__pin { r: 8px; }
}

@media (max-width: 46em) {
  .wmap__label { font-size: 34px; letter-spacing: 0.1em; }
  .wmap__pin { r: 12px; }
  .wmap__halo { r: 40px; }
  .wmap__leg { stroke-width: 4.6; }
  .wmap--sourcing .wmap__pin { r: 9px; }
  .wmap--sourcing .wmap__halo { r: 28px; }
  .wmap__net { r: 6px; }
  .wmap__origin.is-lit .wmap__pin { r: 12px; }
}

/* --------------------------------------------------------------------------
   23. Hubs section
   -------------------------------------------------------------------------- */

/* The map is the argument, so it gets the full width of the band. The gist
   line under it is the five-second reading of the whole section; the three
   cards below are the detail, and each lights with its hub. */
.hubs { margin-top: clamp(2.5rem, 6vw, 4rem); }

.hubs__gist {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2em 1.1em;
  margin-top: clamp(1.25rem, 3vw, 2rem);
  font-family: var(--serif);
  font-size: clamp(1.125rem, 0.85rem + 1.1vw, 1.625rem);
  letter-spacing: -0.012em;
}

.hubs__gist span { opacity: 0.26; transition: opacity 700ms ease; }
.hubs__gist span.is-on { opacity: 1; }

.hubs__cards {
  display: grid;
  gap: clamp(1.75rem, 3vw, 2.5rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

@media (min-width: 52em) {
  .hubs__cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.hub-card {
  padding-top: clamp(1.25rem, 2.5vw, 1.75rem);
  border-top: 1px solid var(--rule);
  opacity: 0.3;
  transition: opacity 700ms ease;
}

.hub-card.is-on { opacity: 1; }

.hub-card__city {
  font-family: var(--sans);
  font-size: var(--t-fine);
  letter-spacing: 0.16em;
  color: var(--sect-accent);
}

.hub-card__entity {
  margin-top: var(--s-2);
  font-family: var(--serif);
  font-size: clamp(1.375rem, 1.05rem + 1.3vw, 1.875rem);
  line-height: 1.1;
  letter-spacing: -0.018em;
}

.hub-card__role {
  margin-top: var(--s-2);
  font-size: var(--t-fine);
  letter-spacing: 0.12em;
  color: var(--ink-2);
}

.hub-card__does {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3em 0.7em;
  margin-top: var(--s-4);
  color: var(--ink-2);
  font-size: var(--t-small);
}

.hub-card__does li + li::before {
  content: "·";
  margin-right: 0.7em;
  color: var(--ink-3);
}

/* --------------------------------------------------------------------------
   24. Operating chain

   Six stations on one line. The line is drawn by script from the measured
   position of the six dots, so this layout can change freely and the
   drawing follows it.
   -------------------------------------------------------------------------- */

.flow {
  position: relative;
  margin-top: clamp(2.5rem, 6vw, 4rem);
}

.flow-line { position: absolute; top: 0; left: 0; overflow: visible; pointer-events: none; }

/* Below 47.5em the six nodes stack (see .flow__row), so the connecting line
   the script draws through their dots runs VERTICALLY down the page and reads
   as a stray rule through whatever follows. The line is a one-row device:
   stacked layouts go without it. */
@media (max-width: 47.4375em) {
  .flow-line { display: none; }
}

.flow-line__main {
  fill: none;
  stroke: var(--rule-strong);
  stroke-width: 1;
  transition: stroke-dashoffset 1600ms cubic-bezier(0.33, 0, 0.15, 1);
}

.flow__row { display: grid; gap: var(--s-5); position: relative; }

@media (min-width: 47.5em) {
  .flow__row { grid-template-columns: repeat(6, minmax(0, 1fr)); column-gap: clamp(0.75rem, 1.6vw, 1.25rem); }
}

.flow__node { position: relative; }

.flow__dot {
  display: block;
  width: 9px;
  height: 9px;
  margin-bottom: var(--s-4);
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--ink-3);
  transition: background-color 500ms ease, border-color 500ms ease;
}

.flow.is-drawn .flow__dot { background: var(--accent); border-color: var(--accent); }

.flow__n { font-size: var(--t-fine); letter-spacing: 0.1em; color: var(--ink-3); }

.flow__name {
  margin-top: var(--s-1);
  font-family: var(--sans);
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: 0.1em;
}

.flow__note { margin-top: var(--s-2); font-size: var(--t-fine); color: var(--ink-2); }

@media (max-width: 47.49em) {
  .flow__row { row-gap: var(--s-6); }
  .flow__node { display: grid; grid-template-columns: 9px minmax(0, 1fr); column-gap: var(--s-4); }
  .flow__dot { margin: 0.45rem 0 0; }
  .flow__n { grid-column: 2; }
  .flow__name, .flow__note { grid-column: 2; }
}

.flow__key {
  margin-top: clamp(1.5rem, 3vw, 2rem);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
  max-width: 40rem;
  font-family: var(--serif);
  font-size: var(--t-h3);
  letter-spacing: -0.006em;
}

/* --------------------------------------------------------------------------
   25. Sourcing
   -------------------------------------------------------------------------- */

.sourcing-map { background: var(--ink-section); padding: clamp(1rem, 3vw, 2rem) 0; }

@media (min-width: 56.25em) {
  #sourcing .duo { grid-template-columns: minmax(0, 1fr) minmax(0, 1.22fr); }
  #sourcing .duo__media { justify-content: center; }
}

.origins {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35em 0;
  margin-top: clamp(1.5rem, 3vw, 2rem);
  font-size: var(--t-small);
}

.origins li + li::before { content: "·"; margin: 0 0.6em; color: var(--ink-3); }

/* The list is the information and the map lighting is only a pointer, so
   these are plain spans, not controls: nothing to press, no dead tab stops. */
.origins [data-origin-link] {
  color: var(--ink-2);
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}

.origins [data-origin-link]:hover { color: var(--ink); border-bottom-color: var(--accent); }

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-5);
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
}

.stats .figure { padding-block: 0; }
.stats .figure__value { font-family: var(--serif); font-size: var(--t-place); line-height: 1; letter-spacing: -0.02em; }
.stats .figure__label { margin-top: var(--s-2); color: var(--ink-2); font-size: var(--t-small); }

/* --------------------------------------------------------------------------
   26. Product interlude
   -------------------------------------------------------------------------- */

.interlude { background: var(--paper-sunk); }

.interlude__head { padding-bottom: clamp(1.75rem, 4vw, 2.5rem); }

.interlude__words {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 0.9rem + 2.6vw, 2.5rem);
  line-height: 1.2;
  letter-spacing: -0.016em;
  max-width: 24ch;
}

.interlude__sub { margin-top: var(--s-4); color: var(--ink-2); font-size: var(--t-lede); }

.gallery-strip {
  display: flex;
  gap: clamp(0.5rem, 1.4vw, 1rem);
  padding-left: max(var(--gutter), calc(50vw - var(--shell) / 2 + var(--gutter)));
  padding-right: var(--gutter);
  padding-bottom: var(--s-5);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-strong) transparent;
  /* The strip continues past the frame; say so even where overlay scrollbars
     hide the track. */
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 3.5rem), transparent 100%);
  mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 3.5rem), transparent 100%);
}

.gallery-strip img {
  flex: none;
  width: auto;
  max-width: none;
  height: clamp(13rem, 34vw, 24rem);
  scroll-snap-align: center;
  background: var(--paper);
}

/* --------------------------------------------------------------------------
   27. Retail formats
   -------------------------------------------------------------------------- */

.formats {
  display: grid;
  gap: clamp(1.75rem, 4vw, 2.5rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

@media (min-width: 46em) {
  .formats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.format__media {
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--paper-sunk);
}

.format__media img { width: 100%; height: 100%; object-fit: cover; }

/* A component label, not a link: the accent is reserved for things you can
   act on, so this carries ink and the caps treatment instead. */
.format__name {
  margin-top: var(--s-4);
  font-size: var(--t-fine);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}

.format__size {
  margin-top: var(--s-2);
  font-family: var(--serif);
  font-size: var(--t-place);
  line-height: 1;
  letter-spacing: -0.02em;
}

.format__note { margin-top: var(--s-2); color: var(--ink-2); font-size: var(--t-small); }

/* --------------------------------------------------------------------------
   28. Philosophy
   -------------------------------------------------------------------------- */

.think { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }

@media (min-width: 56.25em) {
  .think { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.3fr); }
  .think__head { position: sticky; top: clamp(4rem, 16vh, 9rem); align-self: start; }
}

.principles > li { padding-block: clamp(1.75rem, 4vw, 2.75rem); border-top: 1px solid var(--rule); }
.principles > li:first-child { border-top: 0; padding-top: 0; }

.principle__n { font-size: var(--t-fine); letter-spacing: 0.14em; color: var(--sect-accent); }

.principle__t {
  margin-top: var(--s-2);
  font-family: var(--serif);
  font-size: clamp(1.5rem, 0.95rem + 2.2vw, 2.25rem);
  line-height: 1.14;
  letter-spacing: -0.018em;
}

.principle__b { margin-top: var(--s-3); max-width: var(--measure); color: var(--ink-2); }

/* --------------------------------------------------------------------------
   29. Technology network
   -------------------------------------------------------------------------- */

.netdiag {
  display: block;
  width: 100%;
  max-width: 53rem;
  height: auto;
  margin: clamp(2rem, 5vw, 3rem) auto 0;
  color: var(--sect-ink);
}

.netdiag__link { stroke: var(--sect-accent); stroke-width: 1; opacity: 0.55; }

.netdiag__dot { fill: var(--sect-ink); opacity: 0.75; }

.netdiag__text {
  fill: var(--sect-ink);
  font-family: var(--sans);
  font-size: 12.5px;
  letter-spacing: 0.13em;
  opacity: 0.82;
}

.netdiag__ring { fill: none; stroke: var(--sect-accent); stroke-width: 1; opacity: 0.35; }
.netdiag__ring--in { opacity: 0.7; }

.netdiag__coretext {
  fill: var(--sect-ink);
  font-family: var(--serif);
  font-size: 17px;
  letter-spacing: 0.04em;
}

.os-nodes { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* Below the tablet breakpoint the drawing would be smaller than its own
   labels, so the narrow layout drops it and shows the seven functions as the
   list they already are in the markup. Same content, legible at 375px. */
@media (max-width: 46em) {
  .netdiag { display: none; }

  .os-nodes {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }

  p.os-nodes {
    margin-top: clamp(2rem, 6vw, 2.5rem);
    color: var(--ink-2);
    font-size: var(--t-small);
    letter-spacing: 0.02em;
  }

  ul.os-nodes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--s-5);
    margin-top: var(--s-4);
    border-top: 1px solid var(--rule);
  }

  ul.os-nodes li {
    padding-block: var(--s-3);
    border-bottom: 1px solid var(--rule);
    font-size: var(--t-fine);
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }
}

/* --------------------------------------------------------------------------
   30. Leadership
   -------------------------------------------------------------------------- */

.lead { display: grid; gap: clamp(1.75rem, 4vw, 3rem); margin-top: clamp(2.5rem, 5vw, 3.5rem); }

@media (min-width: 46em) {
  .lead { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); align-items: start; }
}

/* The floor is a readable card, not a thumbnail: 9.5rem tracks produced
   155px cards carrying 13px bios at a ~22-character measure. 15rem keeps
   every bio at or above ~45 characters per line. */
.team-grid {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

/* The grid sits at full shell width below its .row introduction, so it needs
   the air a margin heading would otherwise have given it. */
.row + .team-grid { margin-top: clamp(2rem, 4vw, 3rem); }

/* The grid cards are <figure>s: without this they keep the UA's 40px side
   margins and sit 80px narrower than their tracks. */
.team-card { margin: 0; }

.team-card__photo {
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
}

/* One treatment across the whole set: the portraits were shot on a cool grey
   backdrop and this page is warm paper, so colour would put seven cold
   rectangles on a beige page. Monochrome makes them one series. */
.team-card__photo img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) contrast(1.03); }

/* One source was shot high-key against a brighter backdrop; pull its black
   point toward the rest of the set until the asset itself is regraded. */
.team-card__photo img[src$="/aga.jpg"] { filter: grayscale(1) contrast(1.18) brightness(0.88); }

.team-card__name { margin-top: var(--s-3); font-family: var(--serif); font-size: var(--t-h3); letter-spacing: -0.006em; }

.team-card__role { margin-top: var(--s-1); color: var(--ink-3); font-size: var(--t-small); }

.team-card__bio {
  margin-top: var(--s-2);
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--ink-2);
}

.lead__bio { margin-top: var(--s-4); max-width: var(--measure); color: var(--ink-2); }

/* --------------------------------------------------------------------------
   31. Partners
   -------------------------------------------------------------------------- */

.partners {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.25rem, 3vw, 2.5rem) clamp(2rem, 6vw, 4.5rem);
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  border-top: 1px solid var(--rule);
}

.partners li {
  font-family: var(--serif);
  font-size: clamp(1.25rem, 0.9rem + 1.4vw, 1.875rem);
  line-height: 1.1;
  letter-spacing: -0.012em;
  color: var(--ink);
}

.partners__role {
  display: block;
  margin-top: var(--s-2);
  font-family: var(--sans);
  font-size: var(--t-fine);
  line-height: 1.45;
  letter-spacing: normal;
  color: var(--ink-3);
}

/* --------------------------------------------------------------------------
   32. Ambition
   -------------------------------------------------------------------------- */

.ambition { display: grid; gap: clamp(2rem, 5vw, 3.5rem); margin-top: clamp(2.5rem, 6vw, 4rem); }

@media (min-width: 62em) {
  .ambition { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.28fr); align-items: start; }
  .ambition__map { position: sticky; top: clamp(4rem, 14vh, 8rem); order: 2; }
  .phase { min-height: 42vh; display: flex; flex-direction: column; justify-content: center; }
}

.phase {
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--rule);
  opacity: 0.32;
  transition: opacity 600ms ease;
}

.phase.is-on { opacity: 1; }

.phase__n { font-size: var(--t-fine); letter-spacing: 0.14em; color: var(--sect-accent); }

.phase__name {
  margin-top: var(--s-2);
  font-family: var(--serif);
  font-size: var(--t-h1);
  line-height: 1.1;
  letter-spacing: -0.018em;
}

.phase__note { margin-top: var(--s-2); color: var(--ink-2); }

.euromap { display: block; width: 100%; height: auto; color: var(--sect-accent); }

.euromap__dots { fill: none; stroke: #45403A; stroke-width: 3.4; stroke-linecap: round; }

.euromap__poland {
  fill: var(--sect-accent);
  fill-opacity: 0;
  stroke: var(--sect-accent);
  stroke-width: 1.2;
  stroke-opacity: 0.45;
  transition: fill-opacity 800ms ease, stroke-opacity 800ms ease;
}

.euromap__region { opacity: 0; transition: opacity 900ms ease; }

.euromap__city { fill: var(--sect-ink); }

.euromap__pulse { fill: none; stroke: var(--sect-ink); stroke-width: 1; opacity: 0; }

[data-step="1"] .euromap__poland,
[data-step="2"] .euromap__poland { fill-opacity: 0.85; stroke-opacity: 1; }

[data-step="2"] .euromap__region { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  [data-step="0"] .euromap__pulse { animation: ping 2.6s ease-out infinite; }
}

@keyframes ping {
  0%   { opacity: 0.7; r: 4.4; }
  70%  { opacity: 0;   r: 26; }
  100% { opacity: 0;   r: 26; }
}

/* --------------------------------------------------------------------------
   33. Closing manifesto
   -------------------------------------------------------------------------- */

.closing {
  position: relative;
  display: flex;
  align-items: center;
  min-height: min(74svh, 40rem);
  padding: 0;
  overflow: hidden;
  background: var(--ink-section);
  color: var(--sect-ink);

  --paper:       var(--ink-section);
  --ink:         var(--sect-ink);
  --ink-2:       #D6CFC0;
  --ink-3:       var(--sect-ink-2);
  --rule-strong: #6C6459;
  --accent:      var(--sect-accent);
  --accent-deep: var(--sect-accent);
}

.closing::before { display: none; }

.closing__media { position: absolute; inset: 0; }
.closing__media img { width: 100%; height: 100%; object-fit: cover; }

.closing__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(12, 10, 8, 0.66);
}

.closing__body {
  position: relative;
  width: 100%;
  padding-block: clamp(3.5rem, 9vw, 6rem);
  text-align: center;
}

.closing .display { max-width: 20ch; margin-inline: auto; }
.closing .display span { color: var(--sect-ink); opacity: 0.72; }

.closing__mark {
  margin-top: clamp(2rem, 5vw, 3rem);
  font-size: var(--t-fine);
  letter-spacing: 0.18em;
}

.closing__places { margin-top: var(--s-2); color: var(--sect-ink-2); font-size: var(--t-small); letter-spacing: 0.08em; }

.closing .btnrow { justify-content: center; }

/* --------------------------------------------------------------------------
   34. Contact strip
   -------------------------------------------------------------------------- */

.routes {
  display: grid;
  gap: 0;
  margin-top: clamp(2rem, 5vw, 3rem);
  border-top: 1px solid var(--rule);
}

@media (min-width: 46em) {
  .routes { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(2rem, 5vw, 4rem); }
}

.routes li {
  padding-block: clamp(0.875rem, 2vw, 1.25rem);
  border-bottom: 1px solid var(--rule);
  font-family: var(--serif);
  font-size: var(--t-h3);
  letter-spacing: -0.006em;
}

/* --------------------------------------------------------------------------
   35. Reveals

   One transition, used everywhere. Reduced motion and a page without
   JavaScript both get the finished state, never an empty one.
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 760ms ease, transform 760ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.reveal.is-in { opacity: 1; transform: none; }

.cities .reveal:nth-child(1) { transition-delay: 0ms; }
.cities .reveal:nth-child(2) { transition-delay: 90ms; }
.cities .reveal:nth-child(3) { transition-delay: 180ms; }
.cities .reveal:nth-child(4) { transition-delay: 270ms; }
.cities .reveal:nth-child(5) { transition-delay: 360ms; }

@media (prefers-reduced-motion: reduce), (scripting: none) {
  .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
  /* Every device whose resting state is faded gets its end state here too:
     with reduced motion the script jumps straight to it anyway, and without
     scripting nothing else ever would. */
  .hubs__gist span { opacity: 1; }
  .hub-card { opacity: 1; }
  .phase { opacity: 1; }
}

/* Without scripting the network drawing never appears; show the seven
   functions as the list they already are, at any width. */
@media (scripting: none) {
  .os-nodes {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }

  p.os-nodes {
    margin-top: clamp(2rem, 6vw, 2.5rem);
    color: var(--ink-2);
    font-size: var(--t-small);
    letter-spacing: 0.02em;
  }

  ul.os-nodes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--s-5);
    margin-top: var(--s-4);
    border-top: 1px solid var(--rule);
  }

  ul.os-nodes li {
    padding-block: var(--s-3);
    border-bottom: 1px solid var(--rule);
    font-size: var(--t-fine);
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }
}
