/* Institut Dental Horta, Pg. Maragall 410 - site stylesheet.
   The only stylesheet written by hand for this site. ds.css, booking.css and
   media.css are shared and load AFTER this file, so anything that has to win
   against them is written at a higher specificity and says why in a comment.

   Design read: a first-presence pitch for a value-led endodontic practice with
   the lowest rating of the eight, with a plain-spoken street-poster language,
   leaning toward concrete grey, hard black bands and burnt oak.

   The page is a vertical stack of full-bleed bands that alternate concrete
   grey and black, each carrying one fact at poster size. That is not a style
   choice pulled out of the air: it is how their own building is composed, a
   sign panel above and a black price banner below. There are no cards on this
   page and no rounded corners anywhere except the form inputs, which get 2px
   so that a tap target still reads as a field. */

/* ---------------------------------------------------------------- tokens --
   :root would lose to booking.css and ds.css, which load later and declare on
   :root themselves. html:root is one specificity step higher, so these values
   hold wherever they have to. */
html:root {
  /* Palette. Nothing is pure black or pure white. Every figure below was
     computed, not estimated. */
  --ground: #DCDEDE;       /* the grey concrete slab their sign is bolted to */
  --ink: #171B1D;          /* 12.84:1 on the ground */
  --muted: #4A5153;        /* 6.00:1 on the ground, so it is body-legible */

  /* Burnt oak, sampled from the blond-oak floor of the surgery in g2
     (#B89577) and darkened until it is legal. 5.45:1 on the ground; the CTA
     label sits on it at 6.95:1. Deliberately NOT their sign cyan: #25ACD9 is
     1.89:1 here and darkening it would produce a corporate trust-blue, which
     is exactly the failure this pass exists to prevent. The cyan appears once
     on this page, inside the hero photograph, where it is true. Measured on
     this ground it is 1.95:1, which is not a text colour under any rule. */
  --accent: #7C4A1C;
  --accent-deep: #683D16;  /* hover. 6.86:1 on the ground, label 8.75:1 on it */
  --accent-ink: #FBF8F4;

  /* The structural black band, with ground-coloured text reversed out of it at
     13.09:1. This is the device their own building uses and it carries the
     plainest facts. */
  --blk: #16191A;
  --blk-ink: #DCDEDE;
  --blk-muted: #A7ACAD;    /* 7.70:1 on the black */
  --blk-line: #3F4547;

  --panel: #E6E8E8;
  --bg-2: #CFD2D2;         /* read by media.css for photo frames */
  --bg-3: #EAECEC;         /* read by booking.css for input fills */
  --line: #8E9494;
  --line-strong: #6E7576;  /* input border: 3.96:1 on the fill, 3.48:1 on the ground */

  /* Error text. booking.css sets --bad on :root and then swaps it to a light
     salmon under prefers-color-scheme: dark. This page is a light grey page
     whatever the system setting is, so that swap would put error text at
     1.48:1 on this ground for every visitor whose phone is in dark mode.
     Pinned here at a specificity that beats a bare :root inside a media
     query. 4.84:1 on the ground, 5.51:1 on the input fill. */
  --bad: #B3261E;

  /* One radius system: zero on every band and panel, 2px on inputs only. */
  --r-s: 2px;

  /* Measured rather than assumed: the language switcher is the tallest thing
     in the header (44px links inside a 2px-padded, 1px-bordered shell, so 50px)
     and the row adds 0.55rem top and bottom, which comes to 67.6px. ds.css
     uses this to keep a focused control from landing under the sticky header,
     and the hero subtracts it to fill exactly one screen. */
  --nav-h: 68px;
  --wrap: 72rem;

  /* Interaction dials, read by ds.css. The flattest of the eight: a poster
     does not animate. */
  --ds-lift: 1px;
  --ds-dur: 0.15s;
}

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: "Barlow", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  font-weight: 400;
  /* Nothing on this page may cause a sideways scroll at 360px. */
  overflow-x: hidden;
}

/* The display face is the one on their own 50% PREUS DE FÀBRICA banner: a tall
   condensed grotesque, set uppercase. A market-poster voice is an honest fit
   for a practice that competes on price. */
h1, h2, h3, .display, .brand b, .foot-brand {
  font-family: "Big Shoulders Display", "Barlow Condensed", "Arial Narrow",
               system-ui, sans-serif;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 0.9;
  margin: 0;
}

p { margin: 0; }
a { color: var(--accent); }
img { max-width: 100%; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: clamp(1.15rem, 4vw, 3rem);
}

/* Icons from assets/social.svg. Always beside a word, never instead of one. */
.si {
  flex: none;
  width: 1em;
  height: 1em;
  fill: currentColor;
}

/* ---------------------------------------------------------------- reveal --
   The floor under motion.js. If Motion never loads this transition is what
   reveals the page; ds.css switches it off when motion.js takes over. Six
   pixels of travel and a third of a second: content appears almost at once, so
   the page reads as printed matter rather than as a product tour. */
.rv {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.35s cubic-bezier(0.22, 0.75, 0.3, 1),
              transform 0.35s cubic-bezier(0.22, 0.75, 0.3, 1);
}
.rv.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .rv { opacity: 1; transform: none; transition: none; }
}

/* --------------------------------------------------------------- buttons -- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.7rem 1.4rem;
  border: 1px solid transparent;
  border-radius: 0;
  font: inherit;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  background: none;
  /* justify-content centres the text BOX; this centres the text inside it.
     Without both, the hero CTA wraps to two lines on a 390px phone and the
     second line hangs off to the left of a centred button. */
  text-align: center;
}

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

.btn-ghost {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.btn-ghost:hover { background: var(--panel); }

/* aria-disabled rather than disabled: site.js leaves the control reachable so
   a reader can still hear why the route is not open yet. */
.btn[aria-disabled="true"] { color: var(--muted); border-color: var(--line); cursor: default; }

/* ---------------------------------------------------------------- header -- */
.site-head {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--ground);
  border-bottom: 1px solid var(--line);
}

.head-row {
  min-height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: clamp(0.7rem, 2vw, 1.75rem);
  padding-block: 0.55rem;
}

.brand {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 44px;
  text-decoration: none;
  color: inherit;
  margin-inline-end: auto;
  min-width: 0;
}
.brand b { font-size: 1.15rem; line-height: 1; }
.brand span {
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.4;
}

.head-nav { display: none; gap: 0.25rem; }
.head-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 0.6rem;
  color: var(--ink);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 500;
}
.head-nav a:hover { color: var(--accent); }

/* The switcher is a control group, so its edge is held to the 3:1 bar for a
   component boundary: --line-strong is 3.48:1 on the ground, --line is 2.28
   and was not visible enough to say where the group starts and stops. */
.lang {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--line-strong);
  background: var(--panel);
}
.lang a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--muted);
}
.lang a:hover { color: var(--ink); }
.lang a[aria-current="true"] { background: var(--ink); color: var(--ground); }

.nav-cta {
  display: none;
  align-items: center;
  min-height: 44px;
  padding: 0 1.1rem;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  font-size: 0.92rem;
  text-decoration: none;
}

/* ----------------------------------------------------------- band shells --
   Two shells and nothing else. Every section on this page is one or the other,
   edge to edge, with zero radius and no shadow. */
.slab { background: var(--ground); padding-block: clamp(3rem, 7vw, 5.5rem); }
.blk {
  background: var(--blk);
  color: var(--blk-ink);
  padding-block: clamp(3rem, 7vw, 5.5rem);
}
.blk a { color: var(--blk-ink); }
.blk h2 { color: var(--blk-ink); }

/* The accent is 2.40:1 on the black, so the focus ring inside a black band is
   drawn in the band's own ink instead. Two selectors deep, which beats the
   bare :focus-visible in ds.css whatever the file order. */
.blk a:focus-visible,
.site-foot a:focus-visible {
  outline: 2px solid var(--blk-ink);
  box-shadow: 0 0 0 5px rgba(220, 222, 222, 0.26);
}

/* One heading treatment, held on every band. The display-to-body ratio is the
   design, so these are set at poster size and the body stays at 1rem. */
.poster {
  font-size: clamp(2.2rem, 1.6rem + 3.2vw, 4.5rem);
  line-height: 0.9;
}

/* ------------------------------------------------------------------ hero --
   The sign photograph full width, the name beneath it on grey. Four text
   elements, the headline broken to two lines by hand at every width, and the
   booking button inside the first screen. */
.marquee {
  min-height: calc(100vh - var(--nav-h));
  min-height: calc(100dvh - var(--nav-h));
  display: grid;
  grid-template-rows: auto 1fr;
}

/* A letterbox strip rather than a tall frame, and the height is measured
   rather than chosen: the whole hero has to fit one screen with the booking
   button on it. At 390x640, the smallest phone this is checked at, the strip
   is 147px and the copy under it is 370px, which leaves 55px of slack under
   the 572px the band is allowed. A banner crop also suits the subject, since
   the sign itself is a banner. */
.marquee-photo {
  height: clamp(140px, 23vh, 380px);
  height: clamp(140px, 23dvh, 380px);
  overflow: hidden;
  background: var(--bg-2);
}
.marquee-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Corrected 2026-09-16 after looking at the rendered page rather than at
     the file name. The sign panel is centred at about half the frame height,
     not in the lower two thirds - anchoring at 68% pushed it off the top edge
     and filled the band with blank concrete. The shop's own name is the whole
     reason this photograph is the hero. */
  object-position: 50% 50%;
}

.marquee-copy {
  align-self: center;
  padding-block: clamp(1.25rem, 3vw, 2rem);
}

.marquee h1 {
  font-size: clamp(3rem, 2.2rem + 5vw, 6.5rem);
  line-height: 0.88;
}

.marquee .lede {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  max-width: 34rem;
  font-size: 1.05rem;
  color: var(--muted);
}

.where {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.1rem 0.7rem;
  margin-top: 0.85rem;
  font-size: 0.88rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}
/* The separator is glued to the following item rather than being an item of
   its own, so it can never be stranded at the end of a wrapped line. */
.where span + span::before {
  content: "\002F";
  margin-inline-end: 0.7rem;
  color: var(--line-strong);
}

.actions {
  margin-top: clamp(1.4rem, 3vw, 2.25rem);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  /* Capped, because the band is 72rem wide and two flexible buttons in it grew
     to 527px each at 1280px, which read as a pair of slabs rather than as
     controls. 30rem is close to the lede's own 34rem measure, so the actions
     sit under the copy column instead of spanning the poster. */
  max-width: 30rem;
}
/* 10rem, not 11: at 390px two 11rem buttons plus the gap came to 364px in a
   354px column and wrapped onto two rows, which pushed the booking button off
   the first screen. Measured, not guessed. */
.actions .btn { flex: 1 1 10rem; }

/* ----------------------------------------------------------------- hours --
   The most useful thing this clinic publishes, and the only place on the page
   set at poster size beside the headings. Seven rules, no box. */
.hours-grid {
  margin: clamp(1.75rem, 4vw, 2.75rem) 0 0;
  display: grid;
}
.hrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0.2rem 1.25rem;
  padding-block: clamp(0.7rem, 1.6vw, 1.05rem);
  border-top: 1px solid var(--blk-line);
}
.hrow:last-child { border-bottom: 1px solid var(--blk-line); }

.hrow dt {
  font-family: "Big Shoulders Display", "Barlow Condensed", "Arial Narrow", sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: clamp(1.2rem, 1rem + 0.8vw, 1.8rem);
  line-height: 1;
}
.hrow dd {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: 0.15rem 1.1rem;
  min-width: 0;
}
.hrow .t {
  font-family: "Big Shoulders Display", "Barlow Condensed", "Arial Narrow", sans-serif;
  font-weight: 700;
  font-size: clamp(1.3rem, 1.05rem + 1vw, 2rem);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
}
/* Never colour alone: the Wednesday row is marked by a hanging rule AND by a
   sentence that says what is different about it. */
.hrow .hnote {
  flex: 1 1 100%;
  text-align: end;
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--blk-muted);
  line-height: 1.4;
}
.hrow.is-through {
  border-inline-start: 4px solid var(--blk-ink);
  padding-inline-start: 0.9rem;
  /* Hangs into the wrap's own gutter so the seven day names stay on one
     vertical line. The gutter is 1.15rem at 360px, which is exactly what this
     claims back, so it can never push the page sideways. */
  margin-inline-start: calc(-0.9rem - 4px);
}

.blk-foot {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  max-width: 52ch;
  color: var(--blk-muted);
  font-size: 0.98rem;
}

/* ----------------------------------------------------------------- rooms --
   A two-up at two different widths and two different shapes, bottom aligned,
   because these are two different rooms photographed on different days and
   presenting them as one continuous interior would be a small lie. */
.gallery {
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: end;
}
.room { margin: 0; }
.room img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--bg-2);
}
.room figcaption {
  margin-top: 0.75rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--muted);
  max-width: 34ch;
}
.room-note {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  max-width: 56ch;
  font-size: 0.98rem;
  color: var(--muted);
}

/* ---------------------------------------------------------- plainest facts --
   The second black band. Address at poster size, then the telephone, which is
   the one route that works whatever else fails. */
.facts { margin-top: clamp(1.75rem, 4vw, 2.75rem); display: grid; gap: clamp(1.25rem, 3vw, 2rem); }
.big-line {
  font-family: "Big Shoulders Display", "Barlow Condensed", "Arial Narrow", sans-serif;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 0.92;
  font-size: clamp(1.9rem, 1.4rem + 2.6vw, 3.6rem);
}
.addr-rest {
  font-style: normal;
  font-size: 1.05rem;
  line-height: 1.5;
  color: var(--blk-muted);
}

.tel-big {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 48px;
  font-family: "Big Shoulders Display", "Barlow Condensed", "Arial Narrow", sans-serif;
  font-weight: 800;
  font-size: clamp(1.7rem, 1.35rem + 1.5vw, 2.5rem);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  border-bottom: 3px solid currentColor;
}
/* The same control on the grey band takes the accent, which is where every
   other booking-route element on this page already is. */
.tel-big.on-slab { color: var(--accent); margin-top: 1.25rem; }
.tel-big.on-slab:hover { color: var(--accent-deep); }

.wa-line { margin-top: 1rem; }
.wa-line a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.wa-line a[href]:hover { border-bottom-color: currentColor; }
/* site.js strips the href from anything the clinic has not confirmed, so the
   label has to read correctly as plain text and is styled as plain text. */
.wa-line a:not([href]) { color: var(--blk-muted); font-weight: 500; }
.wa-line .aside {
  display: block;
  max-width: 46ch;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--blk-muted);
}

/* ----------------------------------------------------------- running text --
   One narrow column. This is where the rating is addressed, in prose, at
   reading size. It is never set large and it is never animated. */
.read .measure { max-width: 68ch; }
.read .poster { margin-bottom: clamp(1.25rem, 3vw, 1.75rem); }
.read p + p { margin-top: 1.1rem; }
.read p { color: var(--muted); }
.read b { color: var(--ink); font-weight: 600; }

/* ------------------------------------------------------------- the form --
   On plain grey and in no box at all. The inputs carry the only 2px radius on
   the page, so that a tap target still reads as a field. */
.book-grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}
.book-aside p { margin-top: 1rem; max-width: 34rem; color: var(--muted); }
.book-aside p.small { font-size: 0.92rem; }

.form {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  /* booking.css gives .form textarea `border-radius: inherit`, so the radius
     the textarea uses is the one declared here. */
  border-radius: var(--r-s);
  min-width: 0;
}
.field label {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.field input,
.field select {
  font: inherit;
  font-size: 1rem;
  min-height: 48px;
  padding: 0.6rem 0.8rem;
  width: 100%;
  min-width: 0;
  color: var(--ink);
  background: var(--bg-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-s);
}
.field select {
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 1.15rem) 55%, calc(100% - 0.8rem) 55%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-inline-end: 2.4rem;
}
.field textarea { width: 100%; }
.field-msg { margin: 0.15rem 0 0; }

.form-error, .form-ok {
  grid-column: 1 / -1;
  display: none;
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
}
.form-error {
  color: var(--bad);
  border-inline-start: 3px solid var(--bad);
  padding-inline-start: 0.8rem;
}
.form-error a { color: var(--bad); font-weight: 700; }
.form-ok {
  color: var(--ink);
  border-inline-start: 3px solid var(--accent);
  padding-inline-start: 0.8rem;
}
.form-error.show, .form-ok.show { display: block; }

.book-note {
  grid-column: 1 / -1;
  margin: 0;
  max-width: 52ch;
  font-size: 0.85rem;
  color: var(--muted);
}

/* booking.css rounds both of these. Zero radius is the system on this page and
   it is held here, at a specificity that wins whatever the file order. */
#book-result { border-radius: 0; margin-top: 1rem; }
#wa-pending-note { border-radius: 0; }

/* --------------------------------------------------------------- footer --
   Black, because the page ends the way their building does. */
.site-foot {
  background: var(--blk);
  color: var(--blk-ink);
  padding-block: clamp(2.5rem, 5vw, 3.5rem);
}
.site-foot a { color: var(--blk-ink); }
.foot-grid {
  display: grid;
  gap: 1.5rem;
  align-items: start;
}
.foot-brand { font-size: 1.6rem; line-height: 1; }
.site-foot address {
  font-style: normal;
  margin-top: 0.4rem;
  font-size: 0.95rem;
  color: var(--blk-muted);
}
.foot-links { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; }
.foot-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.95rem;
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.foot-links a:hover { border-bottom-color: currentColor; }
.demo-notes {
  margin-top: 2rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--blk-line);
  display: grid;
  gap: 0.5rem;
  max-width: 62ch;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--blk-muted);
}

/* ====================================================================== */
/* Every multi-column layout on this page collapses here, in one block, so
   the narrow width is a declared state rather than something hoped for.   */
/* ====================================================================== */

@media (min-width: 46em) {
  .hrow { gap: 0.2rem 2.5rem; padding-block: clamp(0.9rem, 1.8vw, 1.25rem); }
  .hrow .hnote { flex: 0 0 auto; text-align: start; }

  .facts { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
  .facts .big-line { grid-column: 1 / -1; }

  .form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .field.full { grid-column: 1 / -1; }

  /* Two rooms, two shapes, bottoms aligned. The portrait gets the narrower
     column so the two frames end up roughly the same height. */
  .gallery { grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr); }
}

@media (min-width: 62em) {
  .head-nav { display: flex; }
  .nav-cta { display: inline-flex; }

  .marquee-photo { height: clamp(180px, 24vh, 380px); height: clamp(180px, 24dvh, 380px); }

  .book-grid { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); }

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

/* Only on a genuinely narrow phone do the three items in the hero location
   line each take their own row. Above this they wrap as a row, which costs two
   lines instead of three and keeps the booking button on the first screen. The
   separator is glued to the span that follows it, so wrapping can never strand
   one at the end of a line. */
@media (max-width: 22em) {
  .where { flex-direction: column; gap: 0.1rem; }
  .where span + span::before { content: none; }
}
