/* =========================================================================
   LONDON FASHION DAY - LAYOUT PRIMITIVES
   Full-width sections, containers, the editorial grid, responsive gutters,
   vertical rhythm and safe mobile spacing. Opt-in classes only - nothing here
   styles a bare element, and nothing overrides Manon's .edgtf-container,
   .edgtf-grid or .edgtf-full-width, which keep owning existing page content.

   MODERN CSS, USED DELIBERATELY
   - Grid and Flexbox for structure; no float, no framework.
   - clamp() for fluid gutters and rhythm, so the four breakpoints carry
     structural change only, not resizing.
   - Logical properties (inline-size, padding-inline, margin-block) throughout.
     They behave identically in the site's ltr context and mean the layer is
     already correct if a rtl language is ever added.
   - Container queries for components that must respond to the column they are
     placed in rather than the viewport - the case that actually bites when the
     same card appears in a 3-up grid and a sidebar rail.

   BREAKPOINTS
   Custom properties cannot be used inside a media query, so the four canonical
   widths are written as literals here and kept in sync with --lfd-bp-* in
   tokens.css. tests/test_design_system.py asserts that every literal width in
   a media query in this layer is one of those four.
   ========================================================================= */

/* ---- Section: the full-width band ---------------------------------------
   A section is full-bleed; its inner container is what is measured. Vertical
   padding is fluid, so the rhythm compresses on a phone without a breakpoint. */

.lfd-section {
  position: relative;
  inline-size: 100%;
  padding-block: var(--lfd-space-section);
}

.lfd-section-lg { padding-block: var(--lfd-space-section-lg); }

.lfd-section-flush { padding-block: 0; }

.lfd-section-tight { padding-block: var(--lfd-space-lg); }

/* Grounds. A section says what it sits on; components inside it do not. */
.lfd-section-paper { background-color: var(--lfd-color-paper); color: var(--lfd-color-ink-deep); }

.lfd-section-mist { background-color: var(--lfd-color-mist); color: var(--lfd-color-ink-deep); }

.lfd-section-warm { background-color: var(--lfd-color-paper-warm); color: var(--lfd-color-ink-deep); }

.lfd-section-dark { background-color: var(--lfd-color-ink-deep); color: var(--lfd-color-paper); }

/* Hairline rules as structure - the device the whole design is built on. */
.lfd-section-ruled-top { border-block-start: var(--lfd-border-rule); }

.lfd-section-ruled-bottom { border-block-end: var(--lfd-border-rule); }

.lfd-section-dark.lfd-section-ruled-top { border-block-start: var(--lfd-border-on-dark); }

.lfd-section-dark.lfd-section-ruled-bottom { border-block-end: var(--lfd-border-on-dark); }

/* ---- Container ----------------------------------------------------------
   The canonical LFD line: min(1560px, 100% - 56px). Written as a max width
   plus a gutter rather than a calc(), so the gutter is a token a component can
   read and match. */

.lfd-container,
.lfd-container-wide,
.lfd-container-text {
  inline-size: 100%;
  margin-inline: auto;
  padding-inline: var(--lfd-space-gutter);
}

.lfd-container { max-inline-size: calc(var(--lfd-width-content) + (var(--lfd-space-gutter) * 2)); }

.lfd-container-wide { max-inline-size: calc(var(--lfd-width-wide) + (var(--lfd-space-gutter) * 2)); }

.lfd-container-text { max-inline-size: calc(var(--lfd-width-text) + (var(--lfd-space-gutter) * 2)); }

/* Full-bleed content INSIDE a container, without closing and reopening it. */
.lfd-container-bleed {
  margin-inline: calc(var(--lfd-space-gutter) * -1);
  inline-size: calc(100% + (var(--lfd-space-gutter) * 2));
}

/* Safe mobile spacing: the gutter narrows, it never disappears. Below 520px a
   28px gutter on a 320px screen leaves 264px of content, which is too little
   for a two-line tracked label. */
@media (max-width: 520px) {

  .lfd-container,
  .lfd-container-wide,
  .lfd-container-text {
    padding-inline: max(var(--lfd-space-gutter-sm), env(safe-area-inset-left, 0px));
  }

  .lfd-container-bleed {
    margin-inline: calc(var(--lfd-space-gutter-sm) * -1);
    inline-size: calc(100% + (var(--lfd-space-gutter-sm) * 2));
  }
}

/* ---- Editorial grid -----------------------------------------------------
   A 12-column grid for editorial composition, and a set of auto-fitting grids
   for card rows. Every grid child gets min-inline-size: 0, because a grid or
   flex child defaults to min-content - which is the widest image inside it -
   and that is what pushes a track wider than the viewport and scrolls the page
   sideways on a phone. The canonical CSS fixes this by hand in six places. */

.lfd-grid,
.lfd-grid-2,
.lfd-grid-3,
.lfd-grid-4,
.lfd-grid-5,
.lfd-grid-auto {
  display: grid;
  gap: var(--lfd-space-gap);
}

.lfd-grid > *,
.lfd-grid-2 > *,
.lfd-grid-3 > *,
.lfd-grid-4 > *,
.lfd-grid-5 > *,
.lfd-grid-auto > *,
.lfd-cluster > *,
.lfd-rail-layout > * {
  min-inline-size: 0;
}

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

/* Card rows. They collapse by content width rather than by breakpoint, which
   is what keeps a 5-up gallery strip honest inside a narrow column. */
.lfd-grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }

.lfd-grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }

.lfd-grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13.5rem), 1fr)); }

.lfd-grid-5 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); }

.lfd-grid-auto { grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); }

.lfd-grid-gap-lg { gap: var(--lfd-space-gap-lg); }

.lfd-grid-gap-sm { gap: var(--lfd-space-sm); }

.lfd-grid-gap-none { gap: 0; }

/* Column spans on the 12-column grid. Below 767px everything is one column -
   that is the one breakpoint the editorial grid needs. */
.lfd-col-2 { grid-column: span 2; }

.lfd-col-3 { grid-column: span 3; }

.lfd-col-4 { grid-column: span 4; }

.lfd-col-5 { grid-column: span 5; }

.lfd-col-6 { grid-column: span 6; }

.lfd-col-7 { grid-column: span 7; }

.lfd-col-8 { grid-column: span 8; }

.lfd-col-9 { grid-column: span 9; }

.lfd-col-10 { grid-column: span 10; }

.lfd-col-12 { grid-column: span 12; }

@media (max-width: 767px) {

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

  .lfd-col-2,
  .lfd-col-3,
  .lfd-col-4,
  .lfd-col-5,
  .lfd-col-6,
  .lfd-col-7,
  .lfd-col-8,
  .lfd-col-9,
  .lfd-col-10,
  .lfd-col-12 {
    grid-column: span 1;
  }
}

/* ---- Rail layout --------------------------------------------------------
   The sticky left rail beside a content column - news archive, news article,
   gallery entry. Three of the five canonical templates use this shape. */

.lfd-rail-layout {
  display: grid;
  grid-template-columns: var(--lfd-width-rail) minmax(0, 1fr);
  gap: var(--lfd-space-gap-lg);
  align-items: start;
}

.lfd-rail-layout-lg { grid-template-columns: var(--lfd-width-rail-lg) minmax(0, 1fr); }

.lfd-rail-layout-end { grid-template-columns: minmax(0, 1fr) var(--lfd-width-rail); }

.lfd-rail-sticky {
  position: sticky;
  inset-block-start: var(--lfd-space-md);
}

/* The rail stacks before the content gets too narrow to hold a headline. */
@media (max-width: 1024px) {

  .lfd-rail-layout,
  .lfd-rail-layout-lg,
  .lfd-rail-layout-end {
    grid-template-columns: minmax(0, 1fr);
  }

  .lfd-rail-sticky {
    position: static;
  }
}

/* ---- Stack and cluster --------------------------------------------------
   Vertical rhythm as a layout primitive rather than a margin on every element.
   A stack owns the space between its children; its children own none. That is
   what stops margin collapse debugging. */

.lfd-stack { display: flex; flex-direction: column; gap: var(--lfd-space-md); }

.lfd-stack-3xs { gap: var(--lfd-space-3xs); }

.lfd-stack-2xs { gap: var(--lfd-space-2xs); }

.lfd-stack-xs { gap: var(--lfd-space-xs); }

.lfd-stack-sm { gap: var(--lfd-space-sm); }

.lfd-stack-lg { gap: var(--lfd-space-lg); }

.lfd-stack-xl { gap: var(--lfd-space-xl); }

.lfd-stack-2xl { gap: var(--lfd-space-2xl); }

.lfd-stack > * { margin-block: 0; }

/* A horizontal group that wraps - tag rows, chip filters, meta lines,
   button pairs. */
.lfd-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--lfd-space-2xs);
}

.lfd-cluster-sm { gap: var(--lfd-space-3xs); }

.lfd-cluster-md { gap: var(--lfd-space-sm); }

.lfd-cluster-lg { gap: var(--lfd-space-md); }

.lfd-cluster-between { justify-content: space-between; }

.lfd-cluster-end { justify-content: flex-end; }

.lfd-cluster-baseline { align-items: baseline; }

/* Pushes what follows to the far edge of a cluster. */
.lfd-cluster-push { margin-inline-start: auto; }

/* ---- Media --------------------------------------------------------------
   Fixed-ratio frames, so a card row cannot be ragged because one photograph
   is a different shape. The canonical ratios are measured from the approved
   gallery: 207:415 for the five-up strip, 322:350 for the three-up grid. */

.lfd-frame {
  position: relative;
  display: block;
  overflow: hidden;
  max-inline-size: 100%;
  background-color: var(--lfd-color-mist);
}

.lfd-frame > img,
.lfd-frame > video,
.lfd-frame > picture > img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}

.lfd-frame-portrait { aspect-ratio: 207 / 415; }

.lfd-frame-tile { aspect-ratio: 322 / 350; }

.lfd-frame-square { aspect-ratio: 1 / 1; }

.lfd-frame-landscape { aspect-ratio: 3 / 2; }

.lfd-frame-wide { aspect-ratio: 16 / 9; }

.lfd-frame-poster { aspect-ratio: 2 / 3; }

/* ---- Container queries --------------------------------------------------
   A component asks how wide ITS COLUMN is, not how wide the window is. Put
   .lfd-cq on the wrapper a component is placed in; the component then has
   .lfd-cq-* available without knowing anything about the page. */

.lfd-cq { container-type: inline-size; }

.lfd-cq-card { container: lfd-card / inline-size; }

@container (max-width: 22rem) {

  .lfd-cq-stack { display: flex; flex-direction: column; gap: var(--lfd-space-sm); }

  .lfd-cq-hide { display: none; }
}

/* ---- Utilities ----------------------------------------------------------
   The small set a layout genuinely needs. Not a utility framework. */

.lfd-u-relative { position: relative; }

.lfd-u-block { display: block; }

.lfd-u-inline-block { display: inline-block; }

.lfd-u-flex { display: flex; }

.lfd-u-grid { display: grid; }

.lfd-u-hidden { display: none; }

.lfd-u-full { inline-size: 100%; }

.lfd-u-min-0 { min-inline-size: 0; }

.lfd-u-fill { block-size: 100%; }

.lfd-u-mb-0 { margin-block-end: 0; }

.lfd-u-mt-0 { margin-block-start: 0; }

.lfd-u-rule-top { border-block-start: var(--lfd-border-rule); }

.lfd-u-rule-bottom { border-block-end: var(--lfd-border-rule); }

/* The skip link. A new page shell needs one and the current design has none. */
.lfd-skip-link {
  position: absolute;
  inset-inline-start: var(--lfd-space-sm);
  inset-block-start: -100px;
  z-index: var(--lfd-z-skip-link);
  padding: var(--lfd-space-xs) var(--lfd-space-md);
  background-color: var(--lfd-color-ink);
  color: var(--lfd-color-paper);
  text-decoration: none;
}

.lfd-skip-link:focus { inset-block-start: var(--lfd-space-sm); }

/* One focus treatment for everything in the new layer. :focus-visible only,
   so a mouse click never shows a ring but a keyboard tab always does. */
.lfd-focusable:focus-visible,
.lfd-skip-link:focus-visible {
  outline: var(--lfd-border-thick) solid var(--lfd-color-focus);
  outline-offset: 3px;
}
