/* Site-wide stylesheet for every generated site, served at /_shared/material.css.

   THE CLASS CONTRACT. Blocks emit semantic HTML under one semantic class; all styling lives here,
   never per component. Selectors hang off that one class and derive their children, so headings,
   lists, links and cells carry no classes of their own. This file is the vocabulary the Generator
   may use: markup that invents a class name will simply be unstyled.

   Theme via the --kw-* design tokens. A site varies by token values, never by its own CSS. */

:root {
  /* Themeable: mapped from the Site Spec's design-token vocabulary (color.primary ->
     --color-primary, emitted by the renderer onto :root). Fallbacks apply when a site is silent. */
  --kw-font: var(--font-heading, 'Roboto', 'Inter', system-ui, sans-serif);
  --kw-primary: var(--color-primary, #1b3a5b);
  --kw-on-primary: var(--color-on-primary, #ffffff);
  --kw-accent: var(--color-accent, #e8a13a);
  --kw-on-accent: var(--color-on-accent, #ffffff);
  --kw-radius: var(--radius-base, 8px);
  --kw-max-width: var(--layout-max-width, 1100px);

  /* The recessed panel most content blocks sit on. Defaults to the primary colour so a site that
     sets only color.primary still gets a coherent look. */
  --kw-panel: var(--color-panel, var(--kw-primary));
  --kw-on-panel: var(--color-on-panel, var(--kw-on-primary));

  /* Page ground. */
  --kw-page: var(--color-page, #f0eeea);
  --kw-surface: var(--color-surface, #ffffff);
  --kw-text: var(--color-text, #2d2a24);

  /* Fixed system tokens (not per-site). */
  --kw-muted: #5f6b7a;
  --kw-border: #c2ccd6;
  --kw-error: #b3261e;
  --kw-success: #1a7f37;
  --kw-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.18), 0 1px 3px rgba(0, 0, 0, 0.10);
  --kw-elevation-2: 0 8px 32px rgba(0, 0, 0, 0.28);

  /* Derived: a translucent version of the panel's ink, for secondary text on dark panels. */
  --kw-on-panel-dim: color-mix(in srgb, var(--kw-on-panel) 72%, transparent);
}

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

body {
  margin: 0;
  font-family: var(--kw-font);
  color: var(--kw-text);
  background: var(--kw-page);
  line-height: 1.6;
}

h1, h2, h3 { line-height: 1.2; margin: 0 0 0.5rem; }
img { max-width: 100%; height: auto; display: block; }

/* Page content, as a full-bleed grid. Blocks sit in the centre column; the ones that need to span
   edge to edge (hero, cta) opt into the outer columns instead. Doing it in CSS rather than by
   emitting them separately is what keeps blocks in document order, so a closing CTA stays at the
   bottom of the page it closes. */
main {
  display: grid;
  grid-template-columns:
    1fr
    min(var(--kw-max-width), calc(100% - 3rem))
    1fr;
  gap: 3.5rem 0;
  padding-bottom: 3.5rem;
}

main > * { grid-column: 2; }

main > .hero,
main > .cta {
  grid-column: 1 / -1;
}

/* A hero leading the page sits flush against the masthead. */
main > .hero:first-child { margin-top: 0; }

/* Shared action styling, used by hero and cta. */
.button {
  display: inline-block;
  padding: 0.75rem 1.75rem;
  border-radius: var(--kw-radius);
  font-weight: 600;
  text-decoration: none;
  text-align: center;
  border: 2px solid var(--kw-accent);
  background: var(--kw-accent);
  color: var(--kw-on-accent);
  transition: filter 0.2s, transform 0.05s;

  &:hover { filter: brightness(1.08); }
  &:active { transform: translateY(1px); }

  &.button-secondary {
    background: transparent;
    color: currentColor;
    border-color: currentColor;
  }
}

/* --- Masthead: brand identity plus nav derived from the page tree --- */
.masthead {
  background: var(--kw-primary);
  color: var(--kw-on-primary);
  box-shadow: var(--kw-elevation-1);
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.75rem 1.5rem;

  & .masthead-brand img { width: 50px; height: 50px; border-radius: 50%; }

  & .masthead-identity {
    display: flex;
    flex-direction: column;
    margin-right: auto;

    & strong { font-size: 1.15rem; letter-spacing: 0.5px; }
    & span { font-size: 0.8rem; opacity: 0.8; }
  }

  /* The toggle only exists at phone width; <kw-nav> flips :state(open) and aria-expanded. */
  & .nav-toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: var(--kw-radius);
    background: transparent;
    cursor: pointer;

    & span { display: block; height: 2px; width: 22px; margin: 0 auto; background: var(--kw-on-primary); }
    &:hover, &[aria-expanded='true'] { background: color-mix(in srgb, var(--kw-on-primary) 15%, transparent); }
  }

  & nav ul {
    list-style: none;
    display: flex;
    gap: 0.25rem;
    margin: 0;
    padding: 0;
    flex-wrap: wrap;
  }

  & nav a {
    display: block;
    padding: 0.5rem 1rem;
    border-radius: var(--kw-radius);
    color: inherit;
    text-decoration: none;
    font-weight: 500;

    &:hover { background: color-mix(in srgb, var(--kw-on-primary) 15%, transparent); }
    &[aria-current='page'] { background: var(--kw-accent); color: var(--kw-on-accent); }
  }
}

/* --- Hero: full-bleed banner, optionally with a logo alongside --- */
.hero {
  background: linear-gradient(135deg, var(--kw-primary) 0%,
              color-mix(in srgb, var(--kw-primary) 82%, white) 100%);
  color: var(--kw-on-primary);
  padding: 4rem 1.5rem;

  display: flex;
  align-items: center;
  gap: 3rem;
  flex-wrap: wrap;
  justify-content: center;

  & .hero-media { width: 240px; flex-shrink: 0; }

  & .hero-body {
    max-width: 640px;
    flex: 1 1 20rem;
  }

  & h1 { font-size: clamp(2rem, 5vw, 3.25rem); line-height: 1.15; }
  & p { margin: 0 0 1.5rem; opacity: 0.9; font-size: 1.1rem; }

  & .hero-actions {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    margin: 0;
  }
}

/* Every content block shares one heading treatment, so sections read as one system. */
.prose, .cards, .metrics, .list-detail, .price-table, .steps,
.gallery, .reviews, .credentials, .opening-hours, .contact-details {
  & > h2 {
    color: var(--kw-primary);
    font-size: 1.5rem;
    padding-bottom: 0.5rem;
    border-bottom: 3px solid var(--kw-accent);
    display: inline-block;
    margin-bottom: 1.5rem;
  }
}

/* --- Prose --- */
.prose p {
  max-width: 70ch;
  margin: 0 0 1rem;
}

/* --- Cards: equal-weight grid --- */
.cards .card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.5rem;
}

.cards .card {
  background: var(--kw-panel);
  color: var(--kw-on-panel);
  padding: 2rem;
  border-radius: var(--kw-radius);
  text-decoration: none;
  transition: transform 0.2s, box-shadow 0.2s;

  & h3 { font-size: 1.15rem; }
  & p { color: var(--kw-on-panel-dim); font-size: 0.95rem; margin: 0; }
}

.cards a.card:hover { transform: translateY(-4px); box-shadow: var(--kw-elevation-2); }

/* --- Metrics: number over label --- */
.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 2rem;
  text-align: center;
  background: var(--kw-panel);
  color: var(--kw-on-panel);
  border-radius: var(--kw-radius);
  padding: 2.5rem 2rem;

  /* The shared heading rule assumes a light ground; on a panel it needs the panel's ink. */
  & > h2 { grid-column: 1 / -1; color: var(--kw-on-panel); }

  & .metric strong { display: block; font-size: 2.5rem; font-weight: 800; line-height: 1.1; }
  & .metric span { color: var(--kw-on-panel-dim); font-size: 0.95rem; }
}

/* --- List-detail: the services/pricing workhorse --- */

/* Groups a long price list into the shop's own sections ("EPA-paket", "Tillval"). */
.list-detail .detail-group {
  color: var(--kw-primary);
  font-size: 1.15rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 2.5rem 0 1rem;
}

.list-detail .detail-group:first-of-type {
  margin-top: 0;
}

.list-detail .detail-item {
  background: var(--kw-panel);
  color: var(--kw-on-panel);
  border-radius: var(--kw-radius);
  padding: 2.5rem;
  margin-bottom: 1.5rem;

  & h3, & h4 { font-size: 1.25rem; }
  & p { color: var(--kw-on-panel-dim); margin: 0 0 0.75rem; }

  & ul {
    list-style: disc;
    margin: 0.75rem 0 0.75rem 1.5rem;
    color: var(--kw-on-panel-dim);
  }

  & li { margin-bottom: 0.35rem; }

  & .price-hint {
    color: var(--kw-on-panel);
    font-weight: 700;
    font-size: 1.05rem;
    margin: 1rem 0 0;
  }

  & .price-note {
    font-weight: 400;
    font-size: 0.9rem;
    color: var(--kw-on-panel-dim);
  }
}

/* --- Table: flat price list / spec sheet --- */
.price-table {
  & table { width: 100%; border-collapse: collapse; }

  & th, & td {
    text-align: left;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--kw-border);
  }

  & th {
    background: var(--kw-panel);
    color: var(--kw-on-panel);
    font-size: 0.9rem;
  }

  & tbody tr:nth-child(even) { background: var(--kw-surface); }

  & .table-footnote {
    margin: 0.75rem 0 0;
    font-size: 0.9rem;
    color: var(--kw-muted);
  }
}

/* --- Steps: numbered process --- */
.steps ol {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem;
}

.steps .step {
  counter-increment: step;
  background: var(--kw-panel);
  color: var(--kw-on-panel);
  border-radius: var(--kw-radius);
  padding: 2rem;

  &::before {
    content: counter(step);
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background: var(--kw-accent);
    color: var(--kw-on-accent);
    font-weight: 800;
    margin-bottom: 1rem;
  }

  & h3 { font-size: 1.1rem; }
  & p { color: var(--kw-on-panel-dim); font-size: 0.95rem; margin: 0; }
}

/* --- Gallery: grid by default, alternating for the storytelling layout --- */
.gallery .gallery-item {
  background: var(--kw-panel);
  color: var(--kw-on-panel);
  border-radius: var(--kw-radius);
  overflow: hidden;
  margin: 0;

  & img { width: 100%; object-fit: cover; }
  & figcaption { padding: 1.25rem; }
  & h3 { font-size: 1.1rem; }
  & p { color: var(--kw-on-panel-dim); font-size: 0.95rem; margin: 0; }
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;

  & > h2 { grid-column: 1 / -1; }
  & .gallery-item img { height: 220px; }
}

.gallery-alternating {
  display: grid;
  gap: 2rem;

  & .gallery-item {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
    padding: 1.5rem;
    gap: 2rem;
  }

  & .gallery-item img { height: 260px; border-radius: var(--kw-radius); }

  /* Alternate which side the photo sits on, without reordering the markup. */
  & .gallery-item:nth-of-type(even) { direction: rtl; }
  & .gallery-item:nth-of-type(even) > * { direction: ltr; }
}

/* --- Reviews: quote, attribution, and the link that makes it checkable --- */
.reviews .review {
  background: var(--kw-surface);
  border-left: 4px solid var(--kw-accent);
  border-radius: var(--kw-radius);
  padding: 1.75rem 2rem;
  margin: 0 0 1.5rem;
  box-shadow: var(--kw-elevation-1);

  & p { margin: 0 0 1rem; font-size: 1.05rem; }

  & footer {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.75rem;
    font-size: 0.9rem;
    color: var(--kw-muted);
  }

  & cite { font-style: normal; font-weight: 600; color: var(--kw-text); }
  & .review-rating { font-weight: 600; color: var(--kw-accent); }
  & .review-source { color: var(--kw-muted); margin-left: auto; }
}

/* --- Credentials: the trust bar --- */
.credentials {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;

  & > h2 { grid-column: 1 / -1; }

  & .credential {
    background: var(--kw-surface);
    border: 1px solid var(--kw-border);
    border-radius: var(--kw-radius);
    padding: 1.25rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;

    & strong { color: var(--kw-primary); }
    & span { font-size: 0.9rem; color: var(--kw-muted); }
  }
}

/* --- Opening hours --- */
.opening-hours {
  & dl {
    margin: 0;
    max-width: 26rem;

    & > div {
      display: flex;
      justify-content: space-between;
      gap: 1rem;
      padding: 0.5rem 0;
      border-bottom: 1px solid var(--kw-border);
    }
  }

  & dt { font-weight: 600; }
  & dd { margin: 0; color: var(--kw-muted); }

  & .hours-note { margin: 0.75rem 0 0; font-size: 0.9rem; color: var(--kw-muted); }
}

/* --- Contact details --- */
.contact-details {
  & p { margin: 0 0 0.5rem; }
  & a { color: var(--kw-primary); font-weight: 600; }
  & .contact-area { color: var(--kw-muted); margin-top: 1rem; }
}

/* --- CTA band --- */
.cta {
  background: var(--kw-accent);
  color: var(--kw-on-accent);
  padding: 4rem 1.5rem;
  text-align: center;

  & h2 { font-size: 2rem; }
  & p { margin: 0 0 1.5rem; opacity: 0.92; font-size: 1.1rem; }

  /* On the accent band the button inverts, or it would vanish into the ground. */
  & .button {
    background: var(--kw-on-accent);
    color: var(--kw-accent);
    border-color: var(--kw-on-accent);
  }
}

/* --- Footer --- */
.site-footer {
  background: var(--kw-primary);
  color: var(--kw-on-primary);
  padding: 3rem 1.5rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 2rem;

  & > p { grid-column: 1 / -1; opacity: 0.8; max-width: 60ch; margin: 0; }

  & .footer-column h2 { font-size: 1rem; margin-bottom: 0.75rem; }
  & .footer-column p { font-size: 0.9rem; opacity: 0.8; margin: 0 0 0.35rem; }

  & .footer-social {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;

    & a { color: inherit; opacity: 0.85; font-size: 0.9rem; }
    & a:hover { opacity: 1; }
  }
}

/* --- Material forms (outlined fields). One semantic class; children derive from it. --- */
form.contact-form,
form.booking-form,
form.admin-form {
  display: grid;
  gap: 1rem;
  max-width: 34rem;

  & h2 { margin: 0; color: var(--kw-primary); }

  & p.intro { margin: 0; color: var(--kw-muted); }

  & label {
    display: grid;
    gap: 0.35rem;

    & > span {
      font-size: 0.85rem;
      font-weight: 500;
      color: var(--kw-muted);
    }
  }

  & input,
  & select,
  & textarea {
    font: inherit;
    color: inherit;
    padding: 0.7rem 0.85rem;
    background: var(--kw-surface);
    border: 1px solid var(--kw-border);
    border-radius: var(--kw-radius);
    transition: border-color 0.15s, box-shadow 0.15s;

    &:hover { border-color: var(--kw-muted); }

    &:focus-visible {
      outline: none;
      border-color: var(--kw-primary);
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--kw-primary) 25%, transparent);
    }

    &:user-invalid { border-color: var(--kw-error); }
  }

  & textarea { resize: vertical; min-height: 6rem; }

  /* Material contained button */
  & button {
    justify-self: start;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    padding: 0.65rem 1.5rem;
    border: 0;
    border-radius: var(--kw-radius);
    background: var(--kw-primary);
    color: var(--kw-on-primary);
    box-shadow: var(--kw-elevation-1);
    transition: filter 0.15s, box-shadow 0.15s, transform 0.05s;

    &:hover { filter: brightness(1.08); }
    &:active { transform: translateY(1px); }
    &:disabled { opacity: 0.55; cursor: default; box-shadow: none; }
  }

  & [role="status"] {
    margin: 0;
    font-size: 0.9rem;
    color: var(--kw-muted);

    &:empty { display: none; }
  }

  /* relaxjs FormValidator error summary (its own semantic class) */
  & .error-summary {
    margin: 0;
    padding: 0.65rem 0.85rem;
    border-radius: var(--kw-radius);
    background: color-mix(in srgb, var(--kw-error) 12%, var(--kw-surface));
    color: var(--kw-error);
    font-size: 0.9rem;
  }
}

/* --- Booking picker. Days and times are buttons, not a calendar widget: a shop offers a handful
       of days, and a native control would need a library and still read worse on a phone. --- */
form.booking-form {
  & .booking-note {
    margin: 0;
    color: var(--kw-muted);
    font-size: 0.9rem;

    &:empty { display: none; }
  }

  & .booking-days,
  & .booking-times {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;

    & button {
      justify-self: unset;
      padding: 0.5rem 0.9rem;
      font-weight: 500;
      background: var(--kw-surface);
      color: var(--kw-text);
      border: 1px solid var(--kw-border);
      box-shadow: none;

      &:hover { border-color: var(--kw-primary); filter: none; }

      /* The chosen day or time, not a hover state: it has to survive the finger leaving it. */
      &[aria-pressed='true'] {
        background: var(--kw-primary);
        color: var(--kw-on-primary);
        border-color: var(--kw-primary);
      }
    }
  }

  & .booking-empty {
    margin: 0;
    color: var(--kw-muted);
    font-size: 0.9rem;
  }
}

kw-booking:state(loading) form.booking-form button {
  opacity: 0.55;
  pointer-events: none;
}

kw-booking:state(sent) form.booking-form [role="status"] {
  color: var(--kw-success);
  font-weight: 600;
}

/* --- Component states (ElementInternals.states), keyed on the element --- */
kw-contact:state(loading) form.contact-form button {
  opacity: 0.55;
  pointer-events: none;
  box-shadow: none;
}

kw-contact:state(sent) form.contact-form [role="status"] {
  color: var(--kw-success);
  font-weight: 600;
}

/* --- One breakpoint, matching the source sites' own responsive model --- */
@media (max-width: 768px) {
  main { padding: 2rem 1rem; gap: 2.5rem; }

  .masthead {
    padding: 0.5rem 1rem;

    & .nav-toggle { display: flex; }
    & kw-nav { display: contents; }
    /* Only a defined <kw-nav> hides the menu: without the bundle the nav stays visible. */
    & kw-nav:defined:not(:state(open)) nav { display: none; }
    & nav { flex-basis: 100%; }
    & nav ul { flex-direction: column; gap: 0; padding: 0.25rem 0 0.5rem; }
    & nav a { padding: 0.75rem 1rem; }
  }

  .hero {
    padding: 3rem 1.25rem;
    text-align: center;

    & .hero-media { width: 180px; }
    & .hero-actions { justify-content: center; }
  }

  .list-detail .detail-item { padding: 1.75rem; }

  .gallery-alternating .gallery-item {
    grid-template-columns: 1fr;

    &:nth-of-type(even) { direction: ltr; }
  }

  .reviews .review .review-source { margin-left: 0; }
}
