/* Reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --black: #0a0a0a;
  --panel: #141414;
  --white: #ffffff;
  --muted: #9b9b9b;
  --text: #1a1a1a;
  --copy: #333333;
  --text-secondary: #555555;
  --text-tertiary: #666666;
  --border: #e2e2e2;
  --surface: #fafafa;
  --accent: #c62828;
  --display: "Pridi", Georgia, serif;
  --body: "Manrope", system-ui, sans-serif;
  /* The mark a hero slide may carry, and the gap between it and the copy. A
     slide with no mark drops its copy by half of each, which is exactly where
     the copy sits on a slide that has one - whatever the slide's height or the
     length of the slide's own text. Both values live here, beside the mark they
     describe, and the phone breakpoint lowers the mark to match. */
  --hero-mark-h: 220px;
  --hero-copy-gap: clamp(18px, 3vh, 30px);
  /* The top bar keeps its own height in one place, so the surface switch and the
     anchors that scroll under it can never drift apart. */
  --bar-h: 72px;
}

html { scroll-behavior: smooth; }
/* Per-font root size: the display typeface sets the page's rhythm. The default
   (Pridi) keeps the browser default; Italiana is thin and high-contrast, so a
   slightly larger root keeps headings from looking spindly. */
html[data-font="Italiana"] { font-size: 17px; }
/* Italiana is a tight, single-weight display face; a touch of letter-spacing
   improves legibility without breaking the elegance. */
html[data-font="Italiana"]:not([lang="ar"]) .hero-overlay h1,
html[data-font="Italiana"]:not([lang="ar"]) .page-heading h1,
html[data-font="Italiana"]:not([lang="ar"]) .section-title,
html[data-font="Italiana"]:not([lang="ar"]) .cta-band-title,
html[data-font="Italiana"]:not([lang="ar"]) .static-page h1,
html[data-font="Italiana"]:not([lang="ar"]) .service-detail h1,
html[data-font="Italiana"]:not([lang="ar"]) .project-info h1 { letter-spacing: .02em; }
/* Arabic: Cairo reads as the Arabic companion of the Manrope body - a modern
   sans with an even colour - and one family carries both the display and the
   body text, so an Arabic page downloads one face instead of two.
   Scoped to lang=ar so the Latin typography is untouched; the logo is the one
   exception and keeps its own face in every language (see .brand-name). */
:root[lang="ar"] { --display: "Cairo", "Manrope", system-ui, sans-serif; --body: "Cairo", "Manrope", system-ui, sans-serif; }
body {
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.7;
  color: var(--text);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}
/* Anchored sections land below the sticky header when smooth-scrolling. */
[id] { scroll-margin-top: 88px; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
/* A photograph arrives through a soft fade instead of popping in at full strength
   while the rest of the page has already settled. The script marks an image
   `.img-loading` until its bytes are there and `.img-settled` after, and it holds
   the loading state for a frame before settling: a transition needs a painted
   starting value, and without that frame an image the browser already has would
   simply switch on. Only opacity moves, never a transform: the card cycler owns
   each card image's transform. */
img { transition: opacity .5s ease; }
/* A photograph that has not arrived is not painted at all: an image carries its
   own dimming in a few places (the plan thumbnails), and none of those may show a
   picture the browser does not have yet. */
img.img-loading { opacity: 0 !important; }
img.img-settled { opacity: 1; }
/* Titles are set tight, the way display type is: at these sizes the body's 1.7
   leading reads as a gap between two lines rather than as one title, which is what
   makes a long card name or slide title look broken apart. The leading eases as the
   type gets smaller, which is where more air belongs. Body copy keeps its own. */
h1, h2, h3 { font-family: var(--display); font-weight: 500; }
h1 { line-height: 1.1; }
h2 { line-height: 1.15; }
h3 { line-height: 1.25; }
/* Uppercase belongs to the logo: the brand lockup in the hero wears it, exactly
   like the bar's wordmark. Every other title is set in the case the operator
   wrote it in, the way the CTA band's title always was. */
.hero-overlay h1.brand-lockup { font-family: "Pridi", Georgia, serif; text-transform: uppercase; }

/* Visually hidden (clip-based, direction-safe - unlike left:-9999px which
   widens the scrollable area in RTL layouts) */
.honeypot {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Keyboard focus: visible for keyboard users only, matching the accent */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Header */
/* The bar is the brand's black, in every section and on every page: over the
   dark hero it merges with the slide, so the hero reads as full height, and over
   the light sections the same black keeps the white type legible without the bar
   repainting itself. What does change is the seam - the bar carries a soft shadow
   once it has left the hero - and the script decides that at the exact pixel a
   boundary crosses the bar's bottom edge (going down) or its top edge (going up),
   never when a scroll animation starts. */
.site-header {
  position: sticky; top: 0; z-index: 100; background: var(--black);
  transition: box-shadow .35s ease;
}
.site-header.on-light { box-shadow: 0 10px 24px -14px rgba(0,0,0,.55); }
.header-inner {
  max-width: 1200px; margin: 0 auto; padding: 0 24px;
  display: flex; align-items: center; justify-content: space-between;
  height: var(--bar-h); color: var(--white);
}
.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.brand-mark { height: 48px; width: auto; transition: transform .2s ease, opacity .5s ease; }
.brand:hover .brand-mark { transform: scale(1.04); }
/* The wordmark is the logo, not a display heading: it keeps Pridi in every
   language (Arabic sets its display type in Cairo) and under every display-font
   setting, so the brand looks the same wherever it is shown. */
.brand-name {
  font-family: "Pridi", Georgia, serif; font-weight: 500; font-size: 1rem;
  text-transform: uppercase; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.nav-desktop { display: flex; gap: 26px; font-family: var(--display); font-size: .85rem; }
.nav-desktop a, .lang-btn { color: var(--white); transition: color .2s; }
.nav-desktop .nav-langs { display: none; }
.nav-desktop .nav-cta { display: none; }
.nav-desktop .nav-socials { display: none; }
.nav-desktop a:hover, .lang-btn:hover { color: var(--accent); }
/* Top bar menu items are uppercase as an artistic choice; the contact CTA is
   excluded so it stays sentence case like the other buttons. */
.nav-desktop > a:not(.nav-cta) { text-transform: uppercase; letter-spacing: .04em; }

/* Mobile nav toggle (hamburger) */
.nav-toggle {
  display: none; flex-direction: column; justify-content: center; gap: 5px;
  width: 44px; height: 44px; padding: 0;
  background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.18);
  border-radius: 4px; cursor: pointer; flex: none;
}
.nav-toggle-bar {
  display: block; width: 20px; height: 2px; margin: 0 auto;
  background: var(--white); border-radius: 1px; transition: transform .22s ease, opacity .22s ease;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Language switcher dropdown */
.header-actions { display: flex; align-items: center; gap: 12px; flex: none; }
.lang-switcher { position: relative; font-family: var(--body); font-size: .8rem; }
.lang-btn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 38px; padding: 0 14px; background: rgba(255,255,255,.08);
  border: 1px solid rgba(255,255,255,.18); border-radius: 4px;
  cursor: pointer; font: inherit; font-family: var(--display); font-size: .8rem;
}
.lang-menu {
  position: absolute; top: calc(100% + 8px); inset-inline-end: 0; min-width: 150px;
  margin: 0; padding: 6px 0; list-style: none;
  background: var(--panel); border: 1px solid #2a2a2a; border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0,0,0,.35), 0 16px 40px -8px rgba(0,0,0,.5);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
  z-index: 120;
}
.lang-menu.open { opacity: 1; visibility: visible; transform: translateY(0); }
.lang-menu a { display: block; padding: 9px 16px; color: var(--white); }
.lang-menu a:hover { background: var(--accent); color: var(--white); text-decoration: none; }

/* Hero slider */
.hero { position: relative; height: calc(100vh - 72px); min-height: 560px; overflow: hidden; background: #111; }
.hero-slide {
  position: absolute; inset: 0;
  /* Slide (translate) between slides instead of cross-fading */
  transform: translateX(100%);
  transition: transform .7s ease;
  overflow: hidden;
}
.hero-slide.active { transform: translateX(0); }
.hero-slide.prev { transform: translateX(-100%); }
/* Used transiently when going backwards: park the incoming slide on the left
   so it slides in from the correct side. */
.hero-slide.from-left { transform: translateX(-100%); }
/* .active is declared after .from-left so it always resolves a slide to its
   resting position, even while a transient from-left/prev is still applied. */
.hero-slide.no-anim { transition: none; }
/* The cover image lives on ::before so it can breathe (zoom) independently of
   the translate that slides the slide element itself. */
.hero-slide::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: var(--hero-img, none);
  background-size: cover; background-position: center;
  will-change: transform;
}
.hero-slide.active::before { animation: hero-zoom 26s ease-in-out infinite alternate; }
/* scale3d, not scale: Firefox rasterises a 2D scale on the CPU and rebuilds the
   photograph every frame, which is the jitter; a 3D transform hands the layer to
   the compositor, where the zoom costs nothing and cannot stutter. The longer
   duration turns the movement into a slow drift instead of a pulse. */
@keyframes hero-zoom {
  from { transform: scale3d(1, 1, 1); }
  to { transform: scale3d(1.18, 1.18, 1); }
}
.hero-slide::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.62));
}
.hero-overlay {
  position: relative; height: 100%; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  padding: 40px 24px; text-align: center; color: var(--white);
}
.hero-content { max-width: 760px; display: flex; flex-direction: column; align-items: center; gap: var(--hero-copy-gap); }
.hero-slide-media {
  /* Show the slide's featured image plainly: no card treatment, no border,
     radius, shadow or ring - just the image against the slide background. */
  max-height: 220px; width: auto;
}
/* A slide with no mark of its own keeps the place the mark would have taken, so
   its copy sits where the copy sits on a slide that has one. */
.hero-slide:not(.has-media) .hero-content { transform: translateY(calc((var(--hero-mark-h) + var(--hero-copy-gap)) / 2)); }
.hero-overlay h1 { font-size: 2.6rem; text-shadow: 0 2px 12px rgba(0,0,0,.45); margin: 0; }
/* A slide whose title is the brand itself is the logo lockup, so it keeps the
   logo's face in every language - Arabic sets its display type in Cairo. */
.hero-slide-desc { max-width: 580px; margin: 0; color: rgba(255,255,255,.88); font-size: 1.05rem; line-height: 1.7; }
.hero-slide-links { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; }
.hero-link {
  padding: 12px 28px; border: 1px solid rgba(255,255,255,.75); border-radius: 6px;
  color: var(--white); font-family: var(--display); font-size: .8rem;
  transition: background .2s, color .2s, border-color .2s, transform .15s;
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.hero-link:hover { background: var(--white); color: var(--black); text-decoration: none; transform: translateY(-1px); }
.hero-link-scroll { border-color: var(--accent); background: var(--accent); }
.hero-link-scroll:hover { background: transparent; color: var(--white); }
.hero-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 46px; height: 46px; padding: 0; border: 1px solid rgba(255,255,255,.35); border-radius: 50%;
  background: rgba(0,0,0,.25); color: var(--white); line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transition: background .2s, border-color .2s, transform .15s;
}
.hero-arrow svg { width: 22px; height: 22px; display: block; }
.hero-arrow:hover { background: var(--accent); border-color: var(--accent); transform: translateY(-50%) scale(1.08); }
.hero-arrow:active { transform: translateY(-50%) scale(.95); }
.hero-arrow-prev { left: 20px; }
.hero-arrow-next { right: 20px; }
/* Scroll hint: a single bouncing chevron signalling there is content
   below the hero, replacing the old slide dots and mouse outline. */
.hero-scroll-hint {
  position: absolute; bottom: 28px; left: 50%; transform: translateX(-50%);
  z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 8px;
  color: rgba(255,255,255,.75); pointer-events: none;
}
.hero-scroll-chevron {
  width: 20px; height: 20px; opacity: .8;
  animation: scroll-bounce 1.6s ease-in-out infinite;
}
@keyframes scroll-bounce {
  0%, 100% { transform: translateY(0); opacity: .5; }
  50% { transform: translateY(4px); opacity: 1; }
}
.hero-fallback { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; text-align: center; }

/* Sections */
/* The landing page's section headings are the listing pages' page headings: the
   same scale, the same uppercase treatment, the same air under them, so moving
   between a landing section and its own page changes nothing about the type. */
.section-title { text-align: center; font-size: 2.2rem; margin: 0 0 40px; }
/* Empty state shown when a section has no content yet (no seeded data). */
.empty-state { color: var(--muted); text-align: center; font-size: 1.05rem; margin: 8px 0 64px; }
.page-heading { text-align: center; padding: 56px 24px 0; }
.page-heading h1 { font-size: 2.2rem; }
.projects-section { max-width: 1200px; margin: 0 auto; padding: 48px 24px; }

.project-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;
}
.project-card {
  position: relative; overflow: hidden; border-radius: 10px;
  aspect-ratio: 4 / 3; background: #e5e5e5;
  transition: box-shadow .3s ease, transform .3s ease;
}
.project-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 32px -8px rgba(0,0,0,.18), 0 4px 12px rgba(0,0,0,.08);
}
/* Shared multi-image media stack used by project and collection cards.
   Images slide (translate) when cycling, and the whole stack breathes. The
   zoom lives on .card-media (transform:scale) while the slide lives on the
   individual .card-img (transform:translateX), so the two transforms never
   fight each other on the same element. */
.card-media { position: absolute; inset: 0; animation: card-zoom 26s ease-in-out infinite alternate; will-change: transform; }
.card-media .card-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; transform: translateX(100%);
  transition: transform .7s ease, opacity .5s ease;
}
.card-media .card-img.is-active { transform: translateX(0); }
.card-media .card-img.is-prev { transform: translateX(-100%); }
.card-media .card-img.no-anim { transition: none; }
@keyframes card-zoom {
  from { transform: scale3d(1, 1, 1); }
  to { transform: scale3d(1.15, 1.15, 1); }
}
.project-card-overlay {
  position: absolute; inset: 0; display: flex; align-items: flex-end; padding: 20px;
  color: var(--white); font-family: var(--display); font-size: 1.15rem;
  line-height: 1.2;
  background: linear-gradient(transparent 40%, rgba(0,0,0,.62) 100%);
}

/* Project detail */
.breadcrumb { max-width: 1200px; margin: 0 auto; padding: 32px 24px 0; font-size: .8rem; color: #999; }
.breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; list-style: none; }
.breadcrumb li { display: inline-flex; align-items: center; }
.breadcrumb li + li::before { content: "›"; margin: 0 6px; color: #bbb; }
.breadcrumb a { color: #777; transition: color .2s; }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb span[aria-current="page"] { color: #999; }

.project-detail { max-width: 1200px; margin: 0 auto; padding: 24px 24px 0; display: grid; grid-template-columns: 1fr; gap: 40px; }
.project-gallery { display: grid; grid-template-columns: 1fr; gap: 12px; min-width: 0; }
.project-figure { order: 1; cursor: zoom-in; }
.project-figure img {
  width: 100%; height: auto; border-radius: 10px;
  box-shadow: 0 4px 16px rgba(0,0,0,.08), 0 1px 3px rgba(0,0,0,.05);
  transition: transform .3s ease, opacity .5s ease;
}
.project-figure img.switching { transform: translateX(28px); }
.project-thumbs { display: flex; flex-wrap: wrap; gap: 8px; order: 2; }
.project-thumb {
  display: block; width: 56px; height: 56px; padding: 0;
  border: 2px solid transparent; border-radius: 8px; overflow: hidden;
  opacity: .6; transition: opacity .2s, border-color .2s, transform .2s;
}
.project-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.project-thumb.active { opacity: 1; border-color: var(--accent); }
.project-thumb:hover { opacity: 1; transform: translateY(-1px); }
.project-info { display: flex; flex-direction: column; gap: 16px; }
.project-info h1 { font-size: 2.2rem; }
/* A long unbroken word - a pasted URL, an encoded blob - must not widen the page.
   `anywhere` also shrinks the min-content width, which is what keeps the flex
   breadcrumb from pushing the layout past the viewport. */
.project-info h1, .breadcrumb, .breadcrumb li, .project-description { overflow-wrap: anywhere; }
.project-meta { display: flex; flex-wrap: wrap; gap: 24px; }
.project-meta dt { font-size: .78rem; color: var(--muted); }
.project-meta dd { font-family: var(--display); }
.project-meta dd a { color: var(--accent); text-decoration: none; transition: color .2s; }
.project-meta dd a:hover { filter: brightness(.92); text-decoration: underline; }
.project-description { color: var(--text-secondary); }
.tag-chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* Rectangle chips matching the filter buttons in the design system
   (border-radius 4px, accent border + text on hover). They are links, so
   pointer + focus styling applies too. */
.tag-chips a {
  display: inline-flex; align-items: center; min-height: 30px;
  padding: 5px 14px; border: 1px solid var(--border); border-radius: 4px;
  font-size: .8rem; color: var(--text-secondary); background: var(--surface);
  text-decoration: none; transition: border-color .2s, color .2s, background .2s;
}
.tag-chips a:hover, .tag-chips a:focus-visible { border-color: var(--accent); color: var(--accent); }
.plans-section { margin: 4px 0 8px; }
.plans-section h2 { font-size: .95rem; margin-bottom: 10px; }
.plans-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 10px; }
.plans-thumb { padding: 0; border: 0; background: none; cursor: zoom-in; }
.plans-thumb img { width: 100%; height: auto; display: block; border-radius: 4px; opacity: .8; transition: opacity .25s ease; }
.plans-thumb:hover img { opacity: 1; }
.back-link { margin-top: auto; padding-top: 16px; color: var(--accent); font-family: var(--display); font-size: .9rem; display: inline-flex; align-items: center; gap: 6px; transition: gap .2s; }
.back-link:hover { gap: 9px; }
.project-nav { max-width: 1200px; margin: 40px auto 0; padding: 24px 24px 80px; display: flex; justify-content: space-between; border-top: 1px solid #eee; }
.project-nav a { color: var(--text-tertiary); font-family: var(--display); font-size: .9rem; display: inline-flex; align-items: center; gap: 6px; transition: color .2s, gap .2s; }
.project-nav a:hover { color: var(--accent); }
.project-nav .prev:hover, .project-nav .next:hover { gap: 9px; }
.chevron { width: 14px; height: 14px; flex: none; }
.section-more a { color: var(--accent); font-family: var(--display); font-size: .82rem; display: inline-flex; align-items: center; gap: 6px; transition: gap .2s; }
.section-more a:hover { gap: 9px; text-decoration: none; }

.lightbox { position: fixed; inset: 0; background: rgba(0,0,0,.92); display: none; align-items: center; justify-content: center; z-index: 300; }
.lightbox.active { display: flex; }
.lightbox img { max-width: 90vw; max-height: 88vh; border-radius: 8px; box-shadow: 0 32px 80px -16px rgba(0,0,0,.8); }
.lightbox-close {
  position: absolute; top: 16px; right: 24px; width: 44px; height: 44px;
  font-size: 1.4rem; color: #fff; background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.2); border-radius: 50%; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .2s, transform .15s;
}
.lightbox-close:hover { background: var(--accent); border-color: var(--accent); transform: rotate(90deg); }

@media (min-width: 768px) {
  .project-detail { grid-template-columns: 1.2fr 1fr; align-items: start; padding-top: 32px; }
  .project-gallery { grid-template-columns: auto 1fr; }
  .project-thumbs { flex-direction: column; order: -1; }
  .project-figure { order: 0; }
}

/* Static page */
.static-page { max-width: 760px; margin: 0 auto; padding: 56px 24px 100px; }
.static-page h1 { font-size: 2.2rem; margin-bottom: 24px; }
.static-page-body { color: var(--copy); }
.static-page-body p { margin-bottom: 16px; }

/* 404 */
.notfound { max-width: 560px; margin: 0 auto; padding: 80px 24px 120px; text-align: center; }
.notfound-code {
  font-family: var(--display); font-size: 5rem; line-height: 1; color: var(--accent);
  margin-bottom: 8px;
}
.notfound h1 { font-size: 1.6rem; margin-bottom: 12px; }
.notfound-text { color: var(--text-tertiary); margin-bottom: 28px; }
.notfound-link {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 12px 26px; background: var(--black); color: var(--white);
  border-radius: 4px; font-size: .85rem;
}
.notfound-link:hover { background: var(--accent); }
.notfound-link .chevron { width: 14px; height: 14px; }

/* Services */
.services-section { max-width: 1200px; margin: 0 auto; padding: 48px 24px; }
.services-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
.service-card {
  position: relative; overflow: hidden; border-radius: 10px;
  aspect-ratio: 4 / 3; background: linear-gradient(160deg, #1c1c1c, #0a0a0a);
  display: block;
  transition: box-shadow .3s ease, transform .3s ease;
}
.service-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 32px -8px rgba(0,0,0,.18), 0 4px 12px rgba(0,0,0,.08);
}
.service-card img { width: 100%; height: 100%; object-fit: cover; animation: card-zoom 26s ease-in-out infinite alternate; will-change: transform; }
.service-card-overlay {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 5px;
  padding: 22px; color: var(--white);
  background: linear-gradient(transparent 40%, rgba(0,0,0,.72) 100%);
}
.service-card-name {
  font-family: var(--display); font-size: 1.3rem; line-height: 1.2;
}
.service-card-desc { font-size: .84rem; color: rgba(255,255,255,.78); }
.service-card-desc p { margin: 0; }

/* A photograph that has not arrived yet is a hole in the page. Its container keeps
   its size and shows a slow sweep of light, so the page reads as busy instead of
   broken and nothing moves when the image lands. The sweep sits behind the image,
   which fades in over it; a dark card gets a dark sweep, because a light one would
   flash. */
.project-card, .collection-card, .service-card, .project-figure, .project-thumb, .plans-thumb { position: relative; }
.project-card:has(img.img-loading)::before,
.collection-card:has(img.img-loading)::before,
.project-figure:has(img.img-loading)::before,
.project-thumb:has(img.img-loading)::before,
.plans-thumb:has(img.img-loading)::before {
  content: ''; position: absolute; inset: 0; z-index: 0; border-radius: inherit;
  background: linear-gradient(100deg, #e9e9e9 25%, #f7f7f7 45%, #e9e9e9 65%);
  background-size: 240% 100%; animation: skeleton-sweep 1.5s linear infinite;
}
.service-card:has(img.img-loading)::before {
  content: ''; position: absolute; inset: 0; z-index: 0; border-radius: inherit;
  background: linear-gradient(100deg, #141414 25%, #232323 45%, #141414 65%);
  background-size: 240% 100%; animation: skeleton-sweep 1.5s linear infinite;
}
@keyframes skeleton-sweep {
  from { background-position: 120% 0; }
  to { background-position: -20% 0; }
}
/* And the space behind a fading photograph holds the tone the sweep left, so the
   settle reads as the image arriving rather than as a white blink. */
.project-figure, .project-thumb, .plans-thumb { background: #ededed; }

/* Service detail */
.service-hero { max-width: 1200px; margin: 0 auto; padding: 32px 24px 0; }
.service-hero img { width: 100%; height: auto; max-height: 480px; object-fit: cover; border-radius: 10px; }
/* The service photograph is context, not the subject: on a desktop it shows its
   top half and dissolves into the page, so the copy below arrives sooner. A
   phone keeps the whole image, where the column is narrow and the photograph is
   already modest. */
@media (min-width: 768px) {
  .service-hero img {
    max-height: 240px; object-position: center top;
    -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 45%, transparent 100%);
  }
}
.service-detail-wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px 100px; }
.service-detail { max-width: 760px; }
.service-detail h1 { font-size: 2.2rem; margin: 24px 0 16px; }
.service-content { color: var(--copy); }
.service-content p { margin-bottom: 16px; }
.service-projects { margin-top: 44px; }
.service-projects h2 { font-size: 1.1rem; margin-bottom: 20px; }

/* Social links */
.social-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
.social-link {
  display: inline-flex; width: 38px; height: 38px; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,.18); border-radius: 4px; color: var(--white);
  background: rgba(255,255,255,.08);
  transition: border-color .2s, background .2s, color .2s, transform .2s;
}
.social-link:hover { border-color: var(--accent); background: var(--accent); color: var(--white); transform: translateY(-2px); }
.social-icon { width: 20px; height: 20px; display: block; }
.header-social {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; color: var(--white);
  border: 1px solid rgba(255,255,255,.18); border-radius: 4px;
  background: rgba(255,255,255,.08);
  transition: color .2s, border-color .2s, background .2s;
}
.header-social:hover { border-color: var(--accent); background: var(--accent); color: var(--white); }
.header-cta {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 38px; padding: 0 14px; border-radius: 4px;
  border: 1px solid var(--accent); background: var(--accent); color: var(--white);
  font-family: var(--display); font-size: .8rem; font-weight: 600;
  transition: background .2s, color .2s, transform .15s;
  text-decoration: none;
}
.header-cta:hover { background: transparent; color: var(--accent); border-color: var(--accent); transform: translateY(-1px); }
.header-cta .cta-icon, .nav-cta .cta-icon { width: 16px; height: 16px; flex: none; display: block; }
.lang-btn .lang-icon { width: 16px; height: 16px; flex: none; display: block; }

/* Footer tag cloud */
.footer-tags {
  max-width: 1200px; margin: 0 auto; padding: 0 24px 44px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
}
.footer-tags-label { font-family: var(--display); font-size: .8rem; color: var(--muted); margin-inline-end: 6px; }
.footer-tags a {
  padding: 6px 14px; border: 1px solid #333; border-radius: 999px;
  font-family: var(--display); font-size: .8rem; color: #ccc;
  transition: border-color .2s, color .2s, transform .2s;
}
.footer-tags a:hover { border-color: var(--accent); color: var(--white); transform: translateY(-1px); }

/* Collections */
.collections-section { max-width: 1200px; margin: 0 auto; padding: 48px 24px; }
.collection-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;
}
.collection-card {
  position: relative; overflow: hidden; border-radius: 10px;
  aspect-ratio: 16 / 10; background: #e5e5e5; display: block;
  transition: box-shadow .3s ease, transform .3s ease;
}
.collection-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 32px -8px rgba(0,0,0,.18), 0 4px 12px rgba(0,0,0,.08);
}
.collection-card .card-img { width: 100%; height: 100%; object-fit: cover; }
.collection-card-overlay {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 5px;
  padding: 22px; color: var(--white);
  background: linear-gradient(transparent 40%, rgba(0,0,0,.72) 100%);
}
.collection-card-name {
  font-family: var(--display); font-size: 1.3rem; line-height: 1.2;
}
.collection-card-count {
  font-size: .78rem; color: rgba(255,255,255,.75);
}
/* Image-less cards (e.g. the tags index) render as a compact centered tile
   instead of an empty 16:10 box. :has() is supported across modern browsers;
   older engines drop the rule and keep the default card treatment. */
.collection-card:not(:has(.card-media)) {
  aspect-ratio: auto; min-height: 160px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, #1b1b1b, #0e0e0e);
}
.collection-card:not(:has(.card-media)) .collection-card-overlay {
  position: static; align-items: center; justify-content: center;
  text-align: center; background: none; padding: 20px;
}
.section-more { text-align: center; margin-top: 30px; }

/* Footer map */
.footer-map { margin-top: 24px; }
.map-canvas { height: 220px; border-radius: 10px; overflow: hidden; background: #e5e5e5; }
.gmaps-link { display: inline-flex; align-items: center; gap: 8px; margin-top: 10px; font-size: .9rem; color: var(--white); transition: color .2s; }
.gmaps-link:hover { color: var(--accent); }
.gmaps-icon { width: 18px; height: 18px; flex: none; }

/* Filters */
.filter-bar {
  max-width: 1200px; margin: 48px auto 0; padding: 0 24px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
}
.filter-dropdown { position: relative; }
.filter-btn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 38px; padding: 0 14px; border-radius: 4px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); font-family: var(--display); font-size: .85rem;
  cursor: pointer; transition: border-color .2s, color .2s, background .2s;
}
.filter-btn:hover, .filter-dropdown.open .filter-btn { border-color: var(--accent); color: var(--accent); }
.filter-btn-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: var(--accent); color: var(--white); font-size: .68rem; font-weight: 600;
}
.filter-chevron { width: 14px; height: 14px; flex: none; opacity: .7; }
.filter-menu {
  position: absolute; top: calc(100% + 8px); left: 0; min-width: 210px;
  margin: 0; padding: 6px 0; list-style: none;
  background: var(--white); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 10px 28px rgba(0,0,0,.14);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
  z-index: 120; max-height: 320px; overflow: auto;
}
/* The bar can be opened by a click or simply by pointing at it, and the panel
   floats a few pixels below the bar: without a bridge over that gap the pointer
   leaves the dropdown on its way to the panel and the menu closes under it.
   The bridge is part of the dropdown's own box, so the pointer never leaves. */
.filter-dropdown::after {
  content: ''; position: absolute; inset-inline: 0; top: 100%; height: 8px;
}
.filter-dropdown:hover .filter-menu,
.filter-dropdown.open .filter-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.filter-option {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 14px; color: var(--text-secondary);
  font-family: var(--display); font-size: .88rem; line-height: 1.35;
  white-space: nowrap;
  transition: background .15s, color .15s;
}
.filter-option:hover { background: var(--accent); color: var(--white); text-decoration: none; }
.filter-check {
  width: 16px; height: 16px; flex: none; border: 1px solid #ccc; border-radius: 4px;
  background: transparent; position: relative; transition: background .15s, border-color .15s;
}
.filter-option.is-selected .filter-check { border-color: var(--accent); background: var(--accent); }
.filter-option.is-selected .filter-check::after {
  content: ""; position: absolute; left: 4px; top: 1px; width: 5px; height: 9px;
  border: solid var(--white); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.filter-reset {
  padding: 7px 14px; border-radius: 4px; border: 1px solid var(--border);
  color: var(--muted); font-family: var(--display); font-size: .82rem;
  text-decoration: none; transition: color .2s, border-color .2s;
}
.filter-reset:hover { color: var(--accent); border-color: var(--accent); }

/* Gallery */
.gallery-section { max-width: 1200px; margin: 0 auto; padding: 48px 24px; }
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.gallery-grid img { width: 100%; height: 180px; object-fit: cover; border-radius: 10px; }

/* Footer */
.site-footer { background: var(--black); color: var(--white); }
.footer-inner {
  max-width: 1200px; margin: 0 auto; padding: 64px 24px 40px;
  display: grid; grid-template-columns: 1.1fr 0.9fr 1.3fr; gap: 48px;
}
.footer-nav { display: flex; flex-direction: column; gap: 10px; }
.footer-nav a { color: rgba(255,255,255,.72); font-size: .92rem; transition: color .2s; }
.footer-nav a:hover { color: var(--accent); }
.footer-brand {
  display: flex; align-items: center; gap: 12px; margin-bottom: 12px;
}
.footer-brand img { height: 44px; width: auto; }
.footer-brand-name {
  font-family: "Pridi", Georgia, serif; font-weight: 500; font-size: .88rem;
  text-transform: uppercase; color: var(--white);
}
.footer-tagline { color: var(--muted); }
.footer-col h3 { margin-bottom: 16px; }
.contact-form label { display: block; margin-bottom: 12px; color: #ccc; }
/* While the form is in flight the button says so, and cannot be pressed twice. */
.contact-form button[disabled] { opacity: .6; cursor: progress; }
.contact-form input, .contact-form textarea {
  width: 100%; margin-top: 4px; padding: 11px 13px; border: 1px solid #333;
  background: #111; color: var(--white); font: inherit; border-radius: 8px;
  transition: border-color .2s, box-shadow .2s, background .2s;
}
.contact-form input:focus, .contact-form textarea:focus {
  outline: none; border-color: var(--accent); background: #171717;
  box-shadow: 0 0 0 3px rgba(198,40,40,.18);
}
.contact-form button {
  padding: 12px 24px; border: 0; border-radius: 8px; cursor: pointer;
  background: var(--accent); color: var(--white); font: inherit;
  font-family: var(--display);
  transition: background .2s, transform .15s;
}
.contact-form button:hover { background: var(--accent); filter: brightness(1.1); }
.contact-form button:active { transform: translateY(1px); }

/* Contextual call-to-action band at the end of content pages. Only one CTA
   per page, placed after the reader has consumed the content (the research
   consensus for the highest-intent conversion point). */
.cta-band {
  padding: 48px 0;
  text-align: center;
}
.cta-band-inner { max-width: 720px; margin: 0 auto; padding: 0 24px; }
.cta-band-title { font-size: 2.2rem; margin: 0 0 10px; color: var(--text); }
.cta-band-text { color: var(--muted); font-size: 1.02rem; line-height: 1.7; margin: 0 0 26px; }
.cta {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent); color: var(--white);
  padding: 13px 28px; border-radius: 6px; border: 1px solid var(--accent);
  font-family: var(--display); font-size: .82rem; font-weight: 600;
  transition: background .2s, color .2s, transform .15s;
  text-decoration: none;
}
.cta:hover { background: transparent; color: var(--accent); border-color: var(--accent); transform: translateY(-1px); text-decoration: none; }
/* An alert carries its own close control: the result of a submission is
   information to read and put away, not a state of the page. */
.flash {
  padding: 10px 14px; border-radius: 4px; margin-bottom: 14px; font-size: .9rem;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
}
.flash-close {
  border: 0; background: none; color: inherit; cursor: pointer; padding: 0 2px;
  font-size: 1.15rem; line-height: 1; opacity: .7;
}
.flash-close:hover { opacity: 1; }
.flash-success { background: rgba(46,160,67,.15); color: #7ad38b; border: 1px solid rgba(46,160,67,.4); }
.flash-error { background: rgba(198,40,40,.15); color: #ff9d9d; border: 1px solid rgba(198,40,40,.4); }
.footer-bottom {
  border-top: 1px solid #222; padding: 20px 24px; color: var(--muted);
  display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;
  font-size: .82rem;
}
.footer-bottom a { color: var(--muted); text-decoration: none; }
.footer-bottom a:hover { color: var(--white); }
.footer-bottom-sep { margin: 0 8px; opacity: .5; }

/* Tablet & below: hamburger nav replaces the inline desktop links */
@media (max-width: 900px) {
  .nav-toggle { display: flex; }
  .nav-desktop {
    display: none;
    position: absolute; top: 72px; left: 0; right: 0;
    flex-direction: column; gap: 0;
    background: var(--black);
    border-top: 1px solid #222;
    box-shadow: 0 18px 36px rgba(0,0,0,.45);
  }
  .nav-desktop.open { display: flex; }
  .nav-desktop a {
    padding: 15px 24px; border-bottom: 1px solid #222;
    font-size: .9rem;
  }
  .nav-desktop a:hover { background: var(--panel); color: var(--white); }
  .brand-name { font-size: .9rem; }
  /* Language switcher moves into the hamburger menu on mobile. */
  .lang-switcher { display: none; }
  .nav-desktop .nav-langs {
    display: flex; flex-wrap: wrap; gap: 8px;
    padding: 12px 24px; border-bottom: 1px solid #222;
  }
  .nav-desktop .nav-langs a {
    padding: 7px 14px; border: 1px solid #333; border-radius: 4px;
    font-size: .78rem; text-transform: none; font-family: var(--body);
  }
  .nav-desktop .nav-langs a:hover { background: var(--accent); border-color: var(--accent); color: var(--white); }
  .nav-desktop .nav-langs a[aria-current="true"] { border-color: var(--accent); color: var(--accent); }
  .nav-desktop .nav-cta {
    display: inline-flex; align-items: center; gap: 8px;
    align-self: center; width: auto;
    margin: 14px 24px 18px; padding: 13px 18px;
    background: var(--accent); color: var(--white);
    border: 1px solid var(--accent); border-radius: 4px;
    font-family: var(--display); font-size: .82rem; font-weight: 600;
    transition: background .2s, color .2s;
  }
  .nav-desktop .nav-cta:hover { background: transparent; border-color: var(--accent); color: var(--accent); }
  .nav-desktop .nav-socials {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    padding: 16px 24px; border-bottom: 1px solid #222;
  }
  .nav-desktop .nav-social {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; padding: 0; border-bottom: none;
    color: var(--white); border: 1px solid rgba(255,255,255,.18); border-radius: 4px;
    background: rgba(255,255,255,.08); transition: color .2s, border-color .2s, background .2s;
  }
  .nav-desktop .nav-social:hover { border-color: var(--accent); background: var(--accent); color: var(--white); }
  .nav-desktop .nav-social .social-icon { width: 20px; height: 20px; }
  .header-cta { display: none; }
}

@media (max-width: 768px) {
  .project-detail { grid-template-columns: 1fr; }
  .footer-inner { grid-template-columns: 1fr; }
  /* On mobile the footer stacks: contact info & map, then the form, then the
     Explore nav last - so the menu isn't wedged between two contact parts. */
  .footer-col:nth-child(1) { order: 1; }
  .footer-col:nth-child(3) { order: 2; }
  .footer-col:nth-child(2) { order: 3; }
  .footer-bottom { flex-direction: column; text-align: center; gap: 6px; }
  .hero { height: 70vh; }
  .hero-overlay h1 { font-size: 1.9rem; }
  .page-heading h1 { font-size: 1.7rem; }
  .section-title { font-size: 1.7rem; margin: 0 0 28px; }
  .cta-band-title { font-size: 1.7rem; }
  .static-page { padding: 40px 20px 72px; }
  .static-page h1 { font-size: 1.7rem; }
  .projects-section { padding: 36px 16px; }
  .collections-section { padding: 36px 16px; }
  .services-section { padding: 36px 16px; }
  .gallery-section { padding: 36px 16px; }
  .service-hero { padding: 24px 16px 0; }
  .service-detail-wrap { padding: 0 16px 72px; }
  .service-detail h1 { font-size: 1.7rem; }
  .footer-tags { padding: 0 16px 36px; }
  .project-nav { padding: 20px 16px 56px; margin-top: 28px; }
  .breadcrumb { padding: 24px 16px 0; }
  .project-detail { padding: 16px 16px 0; gap: 28px; }
  .project-info h1 { font-size: 1.7rem; }
  .hero-arrow { width: 38px; height: 38px; font-size: 1.4rem; }
  .hero-arrow-prev { left: 10px; }
  .hero-arrow-next { right: 10px; }
  .map-canvas { height: 180px; }
  .contact-form button { width: 100%; }
  .page-heading { padding: 40px 16px 0; }
  .filter-bar { padding: 0 16px; flex-direction: column; align-items: stretch; }
  .filter-dropdown { width: 100%; }
  .filter-btn { width: 100%; justify-content: space-between; min-height: 44px; }
  .filter-menu { min-width: 100%; left: 0; right: 0; }
  /* The bumped Italiana root size eases back on smaller screens. */
  html[data-font="Italiana"] { font-size: 16px; }
  .section-more { margin-top: 22px; }
}

@media (max-width: 480px) {
  /* The mark is smaller on a phone, so the copy it displaces is too. */
  :root { --hero-mark-h: 120px; }
  .header-inner { padding: 0 16px; }
  .brand-mark { height: 40px; }
  /* A phone's bar carries the mark alone: at this width the wordmark next to it
     leaves the bar cramped, and the mark already names the site. */
  .brand-name { display: none; }
  .brand { gap: 10px; }
  .lang-btn { min-height: 44px; padding: 7px 12px; }
  .hero-overlay h1 { font-size: 1.55rem; }
  .hero-slide-desc { font-size: .95rem; }
  .hero { min-height: 480px; }
  .hero-slide-media { max-height: 120px; }
  /* Arrows drop below the title block so they never cover the copy; a 44px
     box keeps the tap target comfortable on phones. */
  .hero-arrow { top: 50%; bottom: auto; transform: translateY(-50%); width: 44px; height: 44px; }
  .hero-arrow svg { width: 18px; height: 18px; }
  .hero-arrow-prev { left: 12px; }
  .hero-arrow-next { right: 12px; }
  .project-grid { grid-template-columns: 1fr; }
  .collection-grid { grid-template-columns: 1fr; }
  .services-grid { grid-template-columns: 1fr; }
  .plans-grid { grid-template-columns: repeat(2, 1fr); }
  .gallery-grid { grid-template-columns: 1fr; }
  /* Full-width CTA on phones: consistent with the contact submit button and a
     comfortable touch target. */
  .cta { width: 100%; justify-content: center; }
}

/* Animations run for everyone (the site owner explicitly wanted them on, so
   the reduced-motion disables were removed). */

/* WhatsApp brand: green fill in the top bar only, with an outline hover. The
   footer and mobile-menu socials keep the shared accent hover. */
.header-social-wa { background: #25D366; border-color: #25D366; color: var(--white); }
.header-social-wa:hover { background: transparent; color: #25D366; border-color: #25D366; }
