/* ==========================================================================
   Tures — utility classes
   Small, reusable, single-purpose classes. If a rule appears on more than one
   element it belongs here; if it describes one block's anatomy it belongs in
   that component's stylesheet instead.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Layout
   ONE content width for every section on the site. A section that needs to
   bleed keeps this container and bleeds *behind* it — never widen it.
   -------------------------------------------------------------------------- */
.u-container {
  inline-size: 100%;
  max-inline-size: var(--container-max);
  margin-inline: auto;
  padding: var(--container-pad);
}

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

.u-section--tight {
  padding-block: var(--padding-block-section-s);
}

.u-stack {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--stack-gap, var(--space-s));
}

.u-stack--loose { --stack-gap: var(--space-m); }

.u-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cluster-gap, var(--space-xs));
}

/* <figure> carries a UA margin that never suits a framed image. */
.u-figure {
  margin: 0;
}

.u-center {
  align-items: center;
  text-align: center;
}

.u-relative { position: relative; }
.u-clip { overflow: clip; }
.u-full { inline-size: 100%; }

/* Every component that responds to its own width opts in here. */
.u-container-query {
  container-type: inline-size;
}

/* Two equal columns that stack when their own container gets narrow. Used by
   the menu panels and the contact block, so it lives here rather than in one
   component's stylesheet. */
.u-two-col {
  display: grid;
  grid-template-columns: repeat(var(--two-col-count, 2), minmax(0, 1fr));
  align-items: start;
  gap: var(--space-m);
  inline-size: 100%;
}

.u-two-col__col {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-m);
  min-inline-size: 0;
}

@container (max-width: 44rem) {
  .u-two-col {
    --two-col-count: 1;
  }
}

/* --------------------------------------------------------------------------
   Definition rows — label on the left, value on the right. The opening hours,
   the phone and mail lines, and the legal page's contact block all use it, so
   it is a utility rather than a component of its own.
   -------------------------------------------------------------------------- */
.u-def-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  inline-size: 100%;
  margin: 0;
}

.u-def-list__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-s);
  font-size: var(--text-large-font-size);
  line-height: var(--line-height-1-1);
}

.u-def-list__term {
  margin: 0;
  font-weight: var(--font-primary-bold);
}

.u-def-list__value {
  margin: 0;
  text-align: end;
  font-weight: var(--font-primary-regular);
}

.u-def-list__value a {
  text-decoration: none;
  text-underline-offset: 0.2em;
}

.u-def-list__value a:hover,
.u-def-list__value a:focus-visible {
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Type scale
   -------------------------------------------------------------------------- */
.u-text-display,
.u-text-h1,
.u-text-h2,
.u-text-h3,
.u-text-h4,
.u-text-h5,
.u-text-h6 {
  font-family: var(--heading-font-family);
  font-weight: var(--heading-font-weight);
  letter-spacing: var(--letter-spacing-0);
}

.u-text-display { font-size: var(--display-font-size); line-height: var(--line-height-1); }
.u-text-h1 { font-size: var(--h1-font-size); line-height: var(--line-height-1); }
.u-text-h2 { font-size: var(--h2-font-size); line-height: var(--line-height-1); }
.u-text-h3 { font-size: var(--h3-font-size); line-height: var(--line-height-1-1); }
.u-text-h4 { font-size: var(--h4-font-size); line-height: var(--line-height-1-3); }
.u-text-h5 { font-size: var(--h5-font-size); line-height: var(--line-height-1-3); }
.u-text-h6 { font-size: var(--h6-font-size); line-height: var(--line-height-1-3); }

.u-text-large,
.u-text-main,
.u-text-small {
  font-family: var(--font-body);
  letter-spacing: var(--letter-spacing-0-02);
  font-weight: var(--font-primary-regular);
}

.u-text-large { font-size: var(--text-large-font-size); line-height: var(--line-height-1-1); }
.u-text-main { font-size: var(--text-main-font-size); line-height: var(--line-height-1-3); }
.u-text-small { font-size: var(--text-small-font-size); line-height: var(--line-height-1-3); }

.u-weight-regular { font-weight: var(--font-primary-regular); }
.u-weight-bold { font-weight: var(--font-primary-bold); }
.u-uppercase { text-transform: uppercase; }
.u-align-center { text-align: center; }

.u-text-brand { color: var(--theme-brand); }
.u-text-muted { color: var(--theme-text-muted); }

.u-measure { max-inline-size: var(--measure-prose); }
.u-measure-long { max-inline-size: var(--measure-long-form); }

/* --------------------------------------------------------------------------
   Surfaces and frames — the signature Tures device
   .u-frame        one thick rule
   .u-frame-double the brand's pair: thick outer rule, a gap of padding, then
                   a hairline inner rule hugging the content. Retint both by
                   setting --frame-color on the element.
   -------------------------------------------------------------------------- */
.u-frame {
  border: var(--border-width-main) solid var(--frame-color, var(--theme-border));
}

/* The signature pair: a thick outer rule, a gap of padding, then a hairline
   inner rule hugging the content. Two elements rather than a pseudo, so the
   content actually sits inside the inner rule instead of under it. */
.u-frame-double {
  border: var(--border-width-main) solid var(--frame-color, var(--theme-border));
  padding: var(--frame-gap, var(--space-xs));
  background-color: var(--frame-fill, transparent);
}

.u-frame-double__inner {
  border: var(--border-width-control) solid var(--frame-color, var(--theme-border));
  padding: var(--frame-pad, var(--space-s));
}

.u-surface-brand { background-color: var(--swatch-primary); }
.u-surface-light { background-color: var(--swatch-neutral-50); }
.u-surface-dark { background-color: var(--swatch-neutral-950); }

.u-shadow-soft { box-shadow: var(--shadow-soft); }
.u-shadow-supersoft { box-shadow: var(--shadow-supersoft); }

/* Aspect ratios for framed media */
.u-ratio-square { aspect-ratio: 1; }
.u-ratio-3x2 { aspect-ratio: 3 / 2; }
.u-ratio-16x9 { aspect-ratio: 16 / 9; }

.u-cover {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

/* --------------------------------------------------------------------------
   Paper-grain overlay — sits absolutely inside any brand-coloured surface.
   Purely decorative, so it is a background image on an aria-hidden span
   rather than an <img> that would need alt text.
   -------------------------------------------------------------------------- */
.u-texture {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: var(--texture-image);
  background-position: 50%;
  background-repeat: repeat;
  background-size: var(--texture-size, 28rem);
  opacity: var(--texture-opacity);
  mix-blend-mode: var(--texture-blend);
}

/* --------------------------------------------------------------------------
   Rich text — the only place where descendant selectors are allowed, because
   the markup inside comes from prose rather than from a component.
   -------------------------------------------------------------------------- */
.u-rich-text {
  max-inline-size: var(--measure-prose);
  color: inherit;
}

.u-rich-text > :first-child { margin-block-start: 0; }
.u-rich-text > :last-child { margin-block-end: 0; }

.u-rich-text p {
  margin-block: var(--space-xs);
  font-size: var(--text-large-font-size);
  line-height: var(--line-height-1-3);
}

.u-rich-text h2,
.u-rich-text h3,
.u-rich-text h4 {
  margin-block: var(--space-s) var(--space-xs);
}

.u-rich-text ul {
  margin-block: var(--space-xs);
  padding-inline-start: var(--size-1-25);
  list-style-type: disc;
}

.u-rich-text ol {
  margin-block: var(--space-xs);
  padding-inline-start: var(--size-1-25);
  list-style-type: decimal;
}

.u-rich-text li { margin-block: var(--space-3xs); }

.u-rich-text a {
  color: var(--theme-brand);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* --------------------------------------------------------------------------
   Buttons — ONE contract, three variants, two sizes, nothing else.

     .u-btn              green fill, no rule, cream label  → hover: near-black
     .u-btn--outline     no fill, hairline rule + ink label → hover: near-black
     .u-btn--ghost       no fill, no rule, ink label        → hover: brand label

   Control borders are always --border-width-control. The thick
   --border-width-main weight belongs to frames and cards; on a button it reads
   as a slab. Square corners always, label uppercase Raleway.

   .u-btn--on-brand retints for a green or near-black ground: rule and label go
   cream, and hover inverts to a cream fill with a green label.

   Anything that should look like a button IS this class — never hand-roll a
   bordered <a> or a bespoke padded <button>.
   -------------------------------------------------------------------------- */
.u-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: var(--size-0-5) var(--size-1);
  border: var(--border-width-control) solid transparent;
  border-radius: var(--radius-none);
  font-family: var(--font-body);
  font-size: var(--text-large-font-size);
  line-height: var(--line-height-1-1);
  letter-spacing: var(--letter-spacing-0-02);
  font-weight: var(--font-primary-bold);
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition:
    color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    background-color var(--duration-fast) var(--ease-standard);
}

.u-btn--small {
  padding: var(--size-0-25) var(--size-0-75);
  font-size: var(--text-small-font-size);
}

.u-btn--solid {
  background-color: var(--theme-brand);
  color: var(--theme-on-brand);
  border-color: transparent;
}

.u-btn--outline {
  background-color: transparent;
  border-color: var(--theme-text);
  color: var(--theme-text);
}

.u-btn--ghost {
  padding-inline: 0;
  background-color: transparent;
  border-color: transparent;
  color: var(--theme-text);
}

.u-btn--solid:hover,
.u-btn--solid:focus-visible,
.u-btn--outline:hover,
.u-btn--outline:focus-visible {
  background-color: var(--swatch-neutral-950);
  border-color: transparent;
  color: var(--swatch-neutral-50);
}

.u-btn--ghost:hover,
.u-btn--ghost:focus-visible {
  background-color: transparent;
  color: var(--theme-brand);
}

/* Retint for a green ground. Names the swatches directly rather than the
   theme aliases: inside .u-theme-brand those aliases flip, and "the button on
   the green" needs to mean the same thing in both places. */
.u-btn--on-brand {
  background-color: transparent;
  border-color: var(--swatch-secondary);
  color: var(--swatch-secondary);
}

.u-btn--on-brand:hover,
.u-btn--on-brand:focus-visible {
  background-color: var(--swatch-secondary);
  border-color: transparent;
  color: var(--swatch-primary);
}

.u-btn[aria-disabled="true"],
.u-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Stroke frame — the brand's one hover flourish.

   Two strokes leave the top and bottom centres and run out to the edges, then
   the sides drop in to close the frame. Drawn with four gradients on two
   pseudo-elements so the gesture needs no extra markup and no JavaScript, and
   so it fires on :focus-visible as well as :hover — the keyboard user sees the
   same affordance as the mouse user.

   The design system's original six-segment version staggers top → sides →
   bottom; this collapses to two stages (horizontals, then verticals) to stay
   markup-free. Set --stroke-frame-color to retint.
   -------------------------------------------------------------------------- */
.u-stroke-frame {
  position: relative;
  isolation: isolate;
}

.u-stroke-frame::before,
.u-stroke-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(var(--stroke-frame-color, var(--theme-brand)) 0 100%),
    linear-gradient(var(--stroke-frame-color, var(--theme-brand)) 0 100%);
  background-repeat: no-repeat;
  transition: background-size var(--duration-base) var(--ease-circ);
}

/* Horizontals: top and bottom rules, growing outward from the centre. */
.u-stroke-frame::before {
  background-position: top center, bottom center;
  background-size: 0% var(--border-width-control);
  transition-delay: calc(var(--duration-base) * 0.9);
}

/* Verticals: left and right rules, dropping in from the top. */
.u-stroke-frame::after {
  background-position: left top, right top;
  background-size: var(--border-width-control) 0%;
  transition-delay: 0s;
}

.u-stroke-frame:hover::before,
.u-stroke-frame:focus-visible::before {
  background-size: 100% var(--border-width-control);
  transition-delay: 0s;
}

.u-stroke-frame:hover::after,
.u-stroke-frame:focus-visible::after {
  background-size: var(--border-width-control) 100%;
  transition-delay: calc(var(--duration-base) * 0.9);
}

/* --------------------------------------------------------------------------
   Accessibility helpers
   -------------------------------------------------------------------------- */
.u-visually-hidden:not(:focus):not(:active) {
  position: absolute;
  inline-size: 1px;    /* hairline — intentionally sub-pixel, not layout */
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.u-skip-link {
  position: absolute;
  inset-block-start: var(--space-2xs);
  inset-inline-start: var(--space-2xs);
  z-index: 100;
  padding: var(--space-2xs) var(--space-xs);
  background-color: var(--swatch-neutral-50);
  color: var(--swatch-primary);
  font-family: var(--font-body);
  font-size: var(--text-small-font-size);
  font-weight: var(--font-primary-bold);
  text-transform: uppercase;
  box-shadow: var(--shadow-soft);
  transform: translateY(-200%);
  transition: transform var(--duration-fast) var(--ease-standard);
}

.u-skip-link:focus {
  transform: none;
}

/* --------------------------------------------------------------------------
   Animation library
   One set of entry motions, shared duration and easing tokens, one opt-out.

   Progressive enhancement: nothing is hidden by CSS alone. The reveal script
   marks an element [data-reveal] AND adds .is-armed, so if the script never
   runs the content is simply visible. Longhands only — a var() inside the
   `animation` shorthand becomes a pending-substitution value and silently
   drops the whole declaration.
   -------------------------------------------------------------------------- */
@keyframes u-reveal-up {
  from { opacity: 0; transform: translateY(var(--reveal-shift)); }
  to { opacity: 1; transform: none; }
}

@keyframes u-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes u-lift-in {
  from { opacity: 0; transform: translateY(var(--space-3xs)); }
  to { opacity: 1; transform: none; }
}

[data-reveal].is-armed { opacity: 0; }

[data-reveal].is-in {
  opacity: 1;
  animation-name: u-reveal-up;
  animation-duration: var(--duration-reveal);
  animation-timing-function: var(--ease-out-expo);
  animation-fill-mode: both;
  animation-delay: var(--reveal-delay, 0s);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  [data-reveal].is-armed,
  [data-reveal].is-in {
    opacity: 1;
    animation-name: none;
    transform: none;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}


/* --------------------------------------------------------------------------
   u-wordmark — the logo, upgraded in place
   The static SVG is the wordmark and keeps driving layout; it is only hidden
   once the Lottie has actually mounted, so every failure path leaves the logo
   exactly as it shipped. visibility rather than display, because the player is
   absolutely positioned against the space the static one still occupies.
   -------------------------------------------------------------------------- */
.u-wordmark {
  position: relative;
  display: block;
}

.u-wordmark__static {
  display: block;
  inline-size: 100%;
  block-size: auto;
}

.u-wordmark[data-wordmark-ready="true"] .u-wordmark__static {
  visibility: hidden;
}

.u-wordmark__player {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.u-wordmark__player svg {
  display: block;
  inline-size: 100%;
  block-size: 100%;
}
