/* Styles for alexsheleheda.co.uk (index.html).
   Sections follow the page from top to bottom: tokens, header, hero, skills,
   about, projects, get a quote, contact, footer; then hover and reduced-motion rules. */

/* ── TOKENS ── */
:root {
  /* Colours */
  --cream:  #FFF5E0;
  --white:  #FFFFFD;
  --orange: #F69540;
  /* Orange TEXT. The orange above is for fills (buttons, shapes, arrows, lines); as text
     on cream or white it's only 2.1:1, too faint to read well. These darker ones are
     the same orange, deepened just enough:
     --orange-text: big or bold text (Contact heading, "work:", the phone menu), 3:1
     --orange-text-small: small text (the active item of the desktop menu), 4.5:1
     To go back to how it was, set both to var(--orange). */
  --orange-text: #E06E0B;
  --orange-text-small: #B25808;
  --text:   #56524E;
  --status: #49F91D;
  --peach:  #FBCFA8;
  --yellow: #F5CE52; /* "Concept" tag */
  --line:   #BAB1B1; /* the line under section titles */
  --muted:  #75706B; /* small grey text; still readable on white and cream */
  --on-orange: #3E3A37;   /* text on orange: buttons and the footer (5:1); the About text colour would be only 3.4:1 */
  --soft-line: #E8E2DA; /* thin borders of cards and answers */
  --field-line: #D6C6AF; /* underline of form fields on the cream Contact background */
  --chip-line:  #CFC2B1; /* thin border of the answer pills */
  --footer-text: var(--on-orange); /* the footer is orange too */
  /* Peach header: your white header over the orange section.
     Almost opaque, so it looks the same over white, cream and orange */
  --header-bg: rgba(251, 207, 168, 0.9); /* #FBCFA8 */
  --focus:     #B5580A; /* darker orange: 3.3:1 on the header, 4.8:1 on white */

  /* Fluid sizes (designed at 1920px wide) */
  --radius:            clamp(30px, 7.8vw, 150px);
  --radius-scrolled:   clamp(20px, 5.2vw, 100px);
  --bar-h:             clamp(60px, 7.8vw, 150px);   /* header and footer */
  --footer-h:          var(--bar-h);   /* the script sets the footer's real height */
  --header-h-scrolled: clamp(50px, 5.2vw, 100px);
  --backdrop-h:        clamp(150px, 15.6vw, 300px);
  --gutter:            clamp(20px, 5vw, 100px);     /* side padding, same as the header */
  --reveal:            318px; /* how far the Skills strip slides out from under Hero */

  /* Screen height. svh = the visible area on phones, with the browser toolbars showing */
  --screen-h: 100vh;
}
@supports (height: 100svh) {
  :root { --screen-h: 100svh; }
}

/* ── RESET ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
button { font: inherit; color: inherit; }

/* Hidden on screen, still read by screen readers */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h-scrolled); /* anchors don't end up under the fixed header */
}
body {
  background: var(--white);
  color: var(--text);
  font-family: 'Syne', sans-serif;
}

/* ── SELECTION ──
   Selecting text looks like the yellow marker used across the site.
   Only real text can be selected: photos, shapes, arrows and the controls
   (menu, buttons, cards, answers, labels) stay out of it, so a drag,
   a double-click or Ctrl+A only highlights what's worth copying. */
::selection { background: var(--yellow); color: var(--on-orange); }
mark::selection, mark ::selection { background: rgb(246 149 64 / 0.55); } /* text already on the yellow marker */
img, svg, picture, video {
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none; /* photos and drawings can't be dragged off the page by accident */
}
.header, .menu-drawer, .hero-title, .skills-section, .about-tag, .contact-heading,
.btn, button, .header-cta, .calc-next, .calc-back, .contact-send, .cr-btn, .result-restart,
.quote-attached-icon, .quote-attached-actions,
.project-card, .project-tag, .project-dialog-visit, .project-dialog-close,
.chip, .calc-option, .calc-step, .calc-progress, .result-label,
.field label, .field legend, .footer-top {
  -webkit-user-select: none;
  user-select: none;
}
/* phones: no grey/blue flash when you tap a link or button (they have their own pressed look) */
html { -webkit-tap-highlight-color: transparent; }
/* the blinking cursor in the form fields is orange too */
input, textarea { caret-color: var(--orange-text); }

/* ── HEADER ── */
.header {
  position: fixed;
  top: 0; left: 0;
  z-index: 100;
  width: 100%;
  height: var(--bar-h);
  background: var(--header-bg);
  backdrop-filter: blur(30px);
  -webkit-backdrop-filter: blur(30px);
  --header-r: var(--radius); /* the bottom corners (the opening animation ends on them) */
  border-radius: 0 0 var(--header-r) var(--header-r);
  transition: height 0.4s ease, border-radius 0.4s ease;
  animation: header-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.15s backwards;
}
.header.scrolled {
  height: var(--header-h-scrolled);
  --header-r: var(--radius-scrolled);
}

/* Opening the page: the header comes out from behind the top edge of the screen,
   growing to the sides and down at the same time until it fills its place.
   It's a clip-path (a "window" onto the header), so nothing inside gets squashed.
   After the animation the clip is gone; the last frame matches the real corners,
   so there's no jump. */
@keyframes header-in {
  from { clip-path: inset(0 calc(50% - 40px) 100% calc(50% - 40px) round 0 0 999px 999px); }
  to   { clip-path: inset(0 0 0 0 round 0 0 var(--header-r) var(--header-r)); }
}
/* then what's inside fades in, left to right */
.header-content,
.nav,
.header-right { animation: header-content-in 0.5s ease-out backwards; }
.header-content { animation-delay: 0.7s; }
.nav            { animation-delay: 0.8s; }
.header-right   { animation-delay: 0.9s; }
@keyframes header-content-in {
  from { opacity: 0; transform: translateY(-8px); }
}

/* Three columns: left, centre, right */
.header-inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  height: 100%;
  padding: 0 var(--gutter);
}

.header-content {
  display: flex;
  align-items: center;
  gap: 10px;
}

.header-right {
  display: flex;
  justify-content: flex-end;
  padding-right: clamp(10px, 2vw, 40px);
}

/* The "Open to work" dot glows: two soft green glows grow and fade one after the
   other, all the time (the same waves as Get in touch on hover, sized to the dot) */
.header-dot {
  --dot: clamp(8px, 0.7vw, 14px);
  position: relative;
  flex-shrink: 0;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--status);
  animation: status-glow 2s ease-out infinite;
}
@keyframes status-glow {
  0%   { box-shadow: 0 0 calc(var(--dot) * 0.3) 0 rgb(73 249 29 / 0.9),
                     0 0 calc(var(--dot) * 0.3) 0 rgb(73 249 29 / 0.9); }
  50%  { box-shadow: 0 0 calc(var(--dot) * 1.3) calc(var(--dot) * 0.9) rgb(73 249 29 / 0),
                     0 0 calc(var(--dot) * 0.3) 0 rgb(73 249 29 / 0.9); }
  100% { box-shadow: 0 0 calc(var(--dot) * 1.3) calc(var(--dot) * 0.9) rgb(73 249 29 / 0),
                     0 0 calc(var(--dot) * 1.3) calc(var(--dot) * 0.9) rgb(73 249 29 / 0); }
}

.header-label {
  font-weight: 700;
  font-size: clamp(14px, 1.25vw, 24px);
  white-space: nowrap; /* "Open to work" stays on one line */
}

/* ── NAV ── */
.nav {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(2px, 0.5vw, 8px);
}

.nav a {
  position: relative;
  z-index: 1;
  padding: clamp(6px, 0.6vw, 10px) clamp(16px, 1.5vw, 28px);
  font-weight: 500;
  font-size: clamp(13px, 1.25vw, 24px);
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.35s ease;
}
.nav a.active { color: var(--orange-text-small); }
/* Hover line: white, like the capsule, grows from the middle of the word
   out to both sides. As wide as the text (inset by the link's side padding). */
.nav a::after {
  content: '';
  position: absolute;
  left: clamp(16px, 1.5vw, 28px);
  right: clamp(16px, 1.5vw, 28px);
  bottom: clamp(2px, 0.25vw, 5px);
  height: clamp(2px, 0.14vw, 3px);
  border-radius: 2px;
  background: var(--white);
  transform: scaleX(0); /* folded into its centre */
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Pill behind the active link, moved by JS */
.nav-pill {
  position: absolute;
  top: 50%;
  left: 0;
  z-index: 0;
  height: 100%;
  background: var(--white);
  border-radius: 40px;
  transform: translateY(-50%);
  transition: left 0.5s cubic-bezier(0.16, 1, 0.3, 1),
              width 0.5s cubic-bezier(0.16, 1, 0.3, 1);
  pointer-events: none;
}

/* "Get in touch" on the right of the header (takes you to the form) */
.header-cta {
  display: inline-flex;
  align-items: center;
  height: clamp(36px, 2.64vw, 50px);
  padding: 0 clamp(16px, 1.32vw, 26px);
  border-radius: 999px;
  background: var(--orange);
  font-weight: 700;
  font-size: clamp(14px, 1.04vw, 20px);
  color: var(--on-orange); /* dark text: 5:1 on orange (white was 2.3:1) */
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.header-cta:focus-visible { border-radius: 999px; }
/* "Look here": Contact me (Hero), Discuss your project (About) and Send message
   (Contact) send out a few of the same orange waves once, by themselves, where
   their arrows point.
   2 rounds = 4 waves (about 4 seconds), then they stop, so it doesn't nag. */
.btn.is-cue,
.contact-send.is-cue { animation: cta-waves 2s ease-out 2; }
/* Hero: the opening animation (long finished) stays first in the list. Without it,
   when the waves end the browser treats the opening as new and plays it again:
   the button would vanish for a second and slide in a second time. */
.hero-actions .btn.is-cue {
  animation: hero-btn-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) var(--in-delay, 0s) backwards,
             cta-waves 2s ease-out 2;
}
/* Two soft glows (a shadow with blur, not hard rings) grow and fade one after
   the other, so a new wave starts every second */
/* The glow is the buttons' own orange (246 149 64) */
@keyframes cta-waves {
  0%   { box-shadow: 0 0 4px 0 rgb(246 149 64 / 0.9),   0 0 4px 0 rgb(246 149 64 / 0.9); }
  50%  { box-shadow: 0 0 18px 14px rgb(246 149 64 / 0), 0 0 4px 0 rgb(246 149 64 / 0.9); }
  100% { box-shadow: 0 0 18px 14px rgb(246 149 64 / 0), 0 0 18px 14px rgb(246 149 64 / 0); }
}

/* ── PAGE ── */
/* Wrapper for everything under the header. It clips the slide-in animations
   at the bottom of the page. clip (unlike hidden) doesn't create a scroll
   container, so position: sticky will still work inside it. */
.page {
  position: relative;
  overflow: hidden; /* fallback for older browsers */
  overflow: clip;
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1),
              filter 0.6s ease;
}

.hero {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: var(--screen-h); /* min-height: grows with content instead of overflowing */
  /* top: clear the fixed header; bottom: extra space so the content sits
     a little above the centre, like in the mockup */
  padding-top: calc(var(--bar-h) + 24px);
  padding-bottom: calc(var(--screen-h) * 0.27);
  background: var(--cream);
  border-radius: 0 0 var(--radius) var(--radius);
}

/* ── HERO CONTENT (phone layout; wider screens come next) ── */
/* Sizes inside are in cqw: 1cqw = 1% of this block's width.
   So on narrower phones the whole composition shrinks together. */
.hero-inner {
  container-type: inline-size;
  width: min(100% - 2 * var(--gutter), 322px);
}

/* Photo and name share one grid cell, so they overlap.
   Layers from bottom to top: "Alex" → photo → "Sheleheda" */
.hero-visual { display: grid; }
.hero-title,
.hero-photo { grid-area: 1 / 1; }

/* A box for the photo and the two orange shapes behind it.
   Everything inside is placed in % of this box, so it all scales together. */
.hero-photo {
  position: relative;
  z-index: 1;
  justify-self: end;
  align-self: end;
  width: 49.2cqw;
  aspect-ratio: 158.4 / 244.9;
  overflow: hidden; /* crops the photo at the bottom of the box */
  /* fades the bottom of the box (photo and shapes) into the background */
  -webkit-mask-image: linear-gradient(to bottom, #000 76%, transparent);
          mask-image: linear-gradient(to bottom, #000 76%, transparent);
}
.hero-photo img {
  position: absolute;
  display: block;
  height: auto;
}
/* Layers: shapes first in the HTML, the person last, so the person is on top */
.hero-shape-top    { left: 3.2%;  top: 0;     width: 55.7%; }
.hero-shape-bottom { left: 24.9%; top: 29.4%; width: 75.1%; }
/* Your photo has transparent space around the person, so the image itself
   is wider than the box and sticks out on both sides (the box crops it) */
.hero-person       { left: -19.4%; top: 1.1%; width: 133.1%; }

.hero-title {
  align-self: end;
  font-weight: 800;
  line-height: 1;
}
.hero-first,
.hero-last {
  position: relative;
  display: block;
}
.hero-first {
  margin-left: 8cqw;
  font-size: 14.5cqw;
  color: var(--text);
}
/* "Sheleheda" is an SVG (to keep the cuts in S and a); its alt text keeps
   the heading readable for screen readers and search engines */
.hero-last {
  z-index: 2; /* above the photo */
  width: 93.32cqw;
  height: auto;
  margin: 4.22cqw 0 -0.34cqw 3.2cqw; /* bottom edge sits at the bottom of the photo */
}

.hero-actions {
  display: flex;
  gap: 16px;
  margin-top: 50px;
}
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  border-radius: 999px;
  font-weight: 700; /* all buttons on the site: 700 */
  font-size: 18px;
  text-decoration: none;
  transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, opacity 0.3s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.btn-primary {
  flex: 1;
  background: var(--orange);
  color: var(--on-orange); /* dark text: 5:1 on orange (white was 2.3:1) */
}
.btn-contact {
  flex-shrink: 0;
  width: 80px;
  border: 1px solid var(--orange);
  color: var(--text); /* dark text/icon; orange text on cream was only 2.1:1. The outline stays orange. */
}
.btn-contact-icon { width: 32px; height: 28px; }
/* On phones the button shows only the icon; the text stays for screen readers */
.btn-contact-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.hero-arrow { display: none; } /* desktop only */

/* ── HERO — OPENING ANIMATION ── */
/* Plays once when the page opens, at the same time as the header.
   Each piece starts before the previous one has finished, so it all flows
   and everything is readable and clickable after about 1.6 seconds.
   "backwards" = each piece waits hidden until its turn; when its animation
   ends, the normal styles take over (so hover effects work as usual). */
.hero-first  { animation: hero-alex-in  0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.3s backwards; }
.hero-last   { animation: hero-last-in  0.8s cubic-bezier(0.65, 0, 0.35, 1) 0.45s backwards; }
.hero-person { animation: hero-photo-in 0.8s cubic-bezier(0.22, 1, 0.36, 1) 0.6s backwards; }
/* the orange shapes come out from behind the person: each grows from its corner
   nearest to the photo's centre. No overshoot and no turning: the shapes touch
   the edges of the photo box, and anything bigger than their final size would be cut off */
/* Then they float: each drifts slowly along x and y and turns a tiny bit, and each
   of those is its own slow wave with its own length. The lengths don't divide into
   each other, so the waves keep meeting differently: sometimes a shape goes up and
   down, sometimes round in a circle one way or the other (a Lissajous figure), and
   the pattern doesn't repeat. The two shapes have different lengths too, so they
   drift apart and back together. The ease is a sine curve, so there are no stops.
   The shapes touch the edges of the photo box (the top one the top edge, the bottom
   one the right edge), so those two only drift inwards, never past the edge.
   translate/rotate are separate from transform, so they add to the entrance. */
.hero-shape-top {
  transform-origin: 100% 100%;
  translate: var(--float-x) var(--float-y);
  rotate: var(--float-r);
  animation: hero-shape-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.85s backwards,
             shape-top-x 4.3s cubic-bezier(0.37, 0, 0.63, 1) -1.7s infinite alternate,
             shape-top-y 3.1s cubic-bezier(0.37, 0, 0.63, 1) -0.4s infinite alternate,
             shape-top-r 5.9s cubic-bezier(0.37, 0, 0.63, 1) -2.9s infinite alternate;
}
.hero-shape-bottom {
  transform-origin: 0 0;
  translate: var(--float-x) var(--float-y);
  rotate: var(--float-r);
  animation: hero-shape-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.95s backwards,
             shape-bottom-x 3.7s cubic-bezier(0.37, 0, 0.63, 1) -2.2s infinite alternate,
             shape-bottom-y 4.9s cubic-bezier(0.37, 0, 0.63, 1) -3.3s infinite alternate,
             shape-bottom-r 6.7s cubic-bezier(0.37, 0, 0.63, 1) -1.1s infinite alternate;
}
.hero-shape-top, .hero-shape-bottom { will-change: translate, rotate; }
/* resting while Hero is scrolled away (the script sets .is-away) */
.hero.is-away .hero-shape-top,
.hero.is-away .hero-shape-bottom { animation-play-state: paused; }
/* The delay is a variable rather than animation-delay: animation-delay would also
   delay the "look here" waves (see .is-cue), which share this animation list. */
.hero-actions .btn { animation: hero-btn-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) var(--in-delay, 0s) backwards; }
.hero-actions .btn:nth-child(1) { --in-delay: 1s; }
.hero-actions .btn:nth-child(2) { --in-delay: 1.1s; }
/* Which arrow each screen gets (the same choice the <picture> made before) */
@media (744px <= width < 1024px) and (height >= 740px)  { .hero-arrow--mini     { display: block; } }
@media (width >= 1024px) and (orientation: portrait)    { .hero-arrow--vertical { display: block; } }
@media (1024px <= width < 1920px) and (orientation: landscape) { .hero-arrow--desk { display: block; } }
@media (width >= 1920px) and (orientation: landscape)   { .hero-arrow--wide     { display: block; } }

/* The arrow draws itself like a pen: the line is one long dash that slides into
   place (dashoffset 1 = nothing drawn, 0 = all drawn), tail first.
   The pen moves like a little roller coaster: it starts smoothly, speeds up going
   down, slows climbing (most at the top of the loop, where it turns tightly) and
   speeds up again on the way down. The speed is baked into the linear() curve.
   The line starts thin, like a pen just touching the paper: a still mask on it
   (narrow at the start, full width after), set in the markup of each arrow.
   "forwards" keeps it drawn when the animation ends.
   When the pen reaches the tip, the head springs out of it (a bit too big, then
   settles) and pokes Contact me: the button jolts the way the arrow points and
   sends out its orange waves (that part is in the script at the bottom). */
.hero-arrow .arrow-line { stroke-dasharray: 1 2; stroke-dashoffset: 1.01; }
.hero-arrow--desk .arrow-line {
  animation: draw-line 1s cubic-bezier(0.45, 0, 0.3, 1) 1.3s forwards;
  animation-timing-function: linear(0.0099 0.00%, 0.0139 1.25%, 0.0181 2.50%, 0.0226 3.75%, 0.0274 5.00%, 0.0327 6.25%, 0.0384 7.50%, 0.0447 8.75%, 0.0515 10.00%, 0.0589 11.25%, 0.0669 12.50%, 0.0753 13.75%, 0.0841 15.00%, 0.0932 16.25%, 0.1027 17.50%, 0.1125 18.75%, 0.1226 20.00%, 0.1330 21.25%, 0.1437 22.50%, 0.1547 23.75%, 0.1660 25.00%, 0.1776 26.25%, 0.1895 27.50%, 0.2017 28.75%, 0.2143 30.00%, 0.2271 31.25%, 0.2402 32.50%, 0.2536 33.75%, 0.2673 35.00%, 0.2812 36.25%, 0.2955 37.50%, 0.3099 38.75%, 0.3247 40.00%, 0.3397 41.25%, 0.3548 42.50%, 0.3702 43.75%, 0.3858 45.00%, 0.4016 46.25%, 0.4175 47.50%, 0.4335 48.75%, 0.4497 50.00%, 0.4660 51.25%, 0.4824 52.50%, 0.4988 53.75%, 0.5153 55.00%, 0.5318 56.25%, 0.5483 57.50%, 0.5648 58.75%, 0.5812 60.00%, 0.5976 61.25%, 0.6139 62.50%, 0.6301 63.75%, 0.6462 65.00%, 0.6621 66.25%, 0.6779 67.50%, 0.6935 68.75%, 0.7089 70.00%, 0.7241 71.25%, 0.7391 72.50%, 0.7538 73.75%, 0.7684 75.00%, 0.7826 76.25%, 0.7966 77.50%, 0.8104 78.75%, 0.8239 80.00%, 0.8371 81.25%, 0.8500 82.50%, 0.8626 83.75%, 0.8749 85.00%, 0.8869 86.25%, 0.8987 87.50%, 0.9101 88.75%, 0.9212 90.00%, 0.9321 91.25%, 0.9426 92.50%, 0.9529 93.75%, 0.9628 95.00%, 0.9725 96.25%, 0.9819 97.50%, 0.9910 98.75%, 1.0000 100.00%);
}
.hero-arrow--mini .arrow-line {
  animation: draw-line 0.65s cubic-bezier(0.45, 0, 0.3, 1) 1.3s forwards;
  animation-timing-function: linear(0.0099 0.00%, 0.0146 1.25%, 0.0196 2.50%, 0.0249 3.75%, 0.0305 5.00%, 0.0365 6.25%, 0.0429 7.50%, 0.0498 8.75%, 0.0570 10.00%, 0.0647 11.25%, 0.0726 12.50%, 0.0809 13.75%, 0.0894 15.00%, 0.0980 16.25%, 0.1067 17.50%, 0.1156 18.75%, 0.1246 20.00%, 0.1336 21.25%, 0.1428 22.50%, 0.1521 23.75%, 0.1615 25.00%, 0.1710 26.25%, 0.1806 27.50%, 0.1903 28.75%, 0.2001 30.00%, 0.2101 31.25%, 0.2201 32.50%, 0.2303 33.75%, 0.2406 35.00%, 0.2510 36.25%, 0.2616 37.50%, 0.2723 38.75%, 0.2831 40.00%, 0.2940 41.25%, 0.3051 42.50%, 0.3163 43.75%, 0.3276 45.00%, 0.3391 46.25%, 0.3507 47.50%, 0.3625 48.75%, 0.3744 50.00%, 0.3865 51.25%, 0.3987 52.50%, 0.4111 53.75%, 0.4236 55.00%, 0.4363 56.25%, 0.4492 57.50%, 0.4622 58.75%, 0.4754 60.00%, 0.4888 61.25%, 0.5024 62.50%, 0.5161 63.75%, 0.5300 65.00%, 0.5441 66.25%, 0.5584 67.50%, 0.5729 68.75%, 0.5875 70.00%, 0.6024 71.25%, 0.6174 72.50%, 0.6327 73.75%, 0.6481 75.00%, 0.6638 76.25%, 0.6796 77.50%, 0.6957 78.75%, 0.7119 80.00%, 0.7284 81.25%, 0.7450 82.50%, 0.7619 83.75%, 0.7790 85.00%, 0.7963 86.25%, 0.8138 87.50%, 0.8314 88.75%, 0.8494 90.00%, 0.8675 91.25%, 0.8858 92.50%, 0.9043 93.75%, 0.9230 95.00%, 0.9420 96.25%, 0.9611 97.50%, 0.9805 98.75%, 1.0000 100.00%);
}
.hero-arrow--vertical .arrow-line {
  animation: draw-line 0.9s cubic-bezier(0.45, 0, 0.3, 1) 1.3s forwards;
  animation-timing-function: linear(0.0099 0.00%, 0.0144 1.25%, 0.0191 2.50%, 0.0242 3.75%, 0.0295 5.00%, 0.0353 6.25%, 0.0414 7.50%, 0.0481 8.75%, 0.0552 10.00%, 0.0626 11.25%, 0.0705 12.50%, 0.0786 13.75%, 0.0869 15.00%, 0.0953 16.25%, 0.1039 17.50%, 0.1126 18.75%, 0.1214 20.00%, 0.1303 21.25%, 0.1393 22.50%, 0.1484 23.75%, 0.1577 25.00%, 0.1671 26.25%, 0.1766 27.50%, 0.1862 28.75%, 0.1960 30.00%, 0.2059 31.25%, 0.2159 32.50%, 0.2261 33.75%, 0.2364 35.00%, 0.2469 36.25%, 0.2575 37.50%, 0.2682 38.75%, 0.2791 40.00%, 0.2902 41.25%, 0.3014 42.50%, 0.3128 43.75%, 0.3243 45.00%, 0.3360 46.25%, 0.3478 47.50%, 0.3598 48.75%, 0.3720 50.00%, 0.3843 51.25%, 0.3968 52.50%, 0.4095 53.75%, 0.4223 55.00%, 0.4353 56.25%, 0.4485 57.50%, 0.4619 58.75%, 0.4754 60.00%, 0.4891 61.25%, 0.5030 62.50%, 0.5170 63.75%, 0.5312 65.00%, 0.5456 66.25%, 0.5602 67.50%, 0.5749 68.75%, 0.5898 70.00%, 0.6049 71.25%, 0.6201 72.50%, 0.6356 73.75%, 0.6512 75.00%, 0.6670 76.25%, 0.6829 77.50%, 0.6991 78.75%, 0.7154 80.00%, 0.7318 81.25%, 0.7485 82.50%, 0.7653 83.75%, 0.7824 85.00%, 0.7995 86.25%, 0.8169 87.50%, 0.8344 88.75%, 0.8521 90.00%, 0.8700 91.25%, 0.8881 92.50%, 0.9063 93.75%, 0.9247 95.00%, 0.9433 96.25%, 0.9621 97.50%, 0.9810 98.75%, 1.0000 100.00%);
}
.hero-arrow--wide .arrow-line {
  animation: draw-line 1.7s cubic-bezier(0.45, 0, 0.3, 1) 1.3s forwards;
  animation-timing-function: linear(0.0099 0.00%, 0.0141 1.25%, 0.0187 2.50%, 0.0236 3.75%, 0.0289 5.00%, 0.0348 6.25%, 0.0414 7.50%, 0.0487 8.75%, 0.0568 10.00%, 0.0656 11.25%, 0.0751 12.50%, 0.0852 13.75%, 0.0957 15.00%, 0.1068 16.25%, 0.1182 17.50%, 0.1301 18.75%, 0.1423 20.00%, 0.1549 21.25%, 0.1679 22.50%, 0.1812 23.75%, 0.1948 25.00%, 0.2086 26.25%, 0.2226 27.50%, 0.2368 28.75%, 0.2511 30.00%, 0.2654 31.25%, 0.2797 32.50%, 0.2939 33.75%, 0.3080 35.00%, 0.3219 36.25%, 0.3355 37.50%, 0.3488 38.75%, 0.3615 40.00%, 0.3735 41.25%, 0.3845 42.50%, 0.3946 43.75%, 0.4039 45.00%, 0.4125 46.25%, 0.4208 47.50%, 0.4287 48.75%, 0.4365 50.00%, 0.4442 51.25%, 0.4520 52.50%, 0.4597 53.75%, 0.4676 55.00%, 0.4755 56.25%, 0.4836 57.50%, 0.4920 58.75%, 0.5009 60.00%, 0.5103 61.25%, 0.5205 62.50%, 0.5319 63.75%, 0.5446 65.00%, 0.5586 66.25%, 0.5739 67.50%, 0.5904 68.75%, 0.6079 70.00%, 0.6263 71.25%, 0.6455 72.50%, 0.6652 73.75%, 0.6851 75.00%, 0.7051 76.25%, 0.7250 77.50%, 0.7446 78.75%, 0.7640 80.00%, 0.7829 81.25%, 0.8014 82.50%, 0.8194 83.75%, 0.8368 85.00%, 0.8537 86.25%, 0.8700 87.50%, 0.8858 88.75%, 0.9009 90.00%, 0.9154 91.25%, 0.9293 92.50%, 0.9425 93.75%, 0.9552 95.00%, 0.9672 96.25%, 0.9786 97.50%, 0.9895 98.75%, 1.0000 100.00%);
}
.hero-arrow .arrow-head {
  animation: arrow-head-pop 0.52s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  animation-timing-function: linear(0.0000 0.0%, 0.1349 2.5%, 0.2600 5.0%, 0.3754 7.5%, 0.4816 10.0%, 0.5789 12.5%, 0.6677 15.0%, 0.7482 17.5%, 0.8208 20.0%, 0.8859 22.5%, 0.9438 25.0%, 0.9947 27.5%, 1.0392 30.0%, 1.0775 32.5%, 1.1099 35.0%, 1.1367 37.5%, 1.1584 40.0%, 1.1752 42.5%, 1.1875 45.0%, 1.1957 47.5%, 1.2000 50.0%, 1.2008 52.5%, 1.1984 55.0%, 1.1933 57.5%, 1.1856 60.0%, 1.1758 62.5%, 1.1642 65.0%, 1.1510 67.5%, 1.1368 70.0%, 1.1218 72.5%, 1.1062 75.0%, 1.0906 77.5%, 1.0752 80.0%, 1.0603 82.5%, 1.0464 85.0%, 1.0336 87.5%, 1.0224 90.0%, 1.0131 92.5%, 1.0061 95.0%, 1.0016 97.5%, 1.0000 100.0%);
}
.hero-arrow--desk .arrow-head { animation-delay: 2.3s; }
.hero-arrow--mini .arrow-head { animation-delay: 1.95s; }
.hero-arrow--vertical .arrow-head { animation-delay: 2.2s; }
.hero-arrow--wide .arrow-head { animation-delay: 3s; }

/* "Alex" rises from under an invisible line at its bottom:
   it starts one full height lower and fully hidden, and as it moves up
   the hidden part shrinks by the same amount, so the cut stays in place */
@keyframes hero-alex-in {
  from { transform: translateY(100%); clip-path: inset(-20% -5% 100% -5%); }
  to   { transform: none;             clip-path: inset(-20% -5% 0 -5%); }
}
/* "Sheleheda" appears left to right, as if being written */
@keyframes hero-last-in {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 -2% 0 0); }
}
@keyframes hero-photo-in {
  from { opacity: 0; transform: translateY(6%); }
}
@keyframes hero-shape-in {
  from { opacity: 0; transform: scale(0.55); }
}
/* the floating (see .hero-shape-top): % of the shape's own size, so it scales */
@property --float-x { syntax: '<length-percentage>'; inherits: false; initial-value: 0%; }
@property --float-y { syntax: '<length-percentage>'; inherits: false; initial-value: 0%; }
@property --float-r { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
@keyframes shape-top-x    { from { --float-x: -3%; }   to { --float-x: 3%; } }
@keyframes shape-top-y    { from { --float-y: 0.6%; }  to { --float-y: 4.6%; } }   /* down only */
@keyframes shape-top-r    { from { --float-r: -1.2deg; } to { --float-r: 1.2deg; } }
@keyframes shape-bottom-x { from { --float-x: -0.6%; } to { --float-x: -5.4%; } }  /* left only */
@keyframes shape-bottom-y { from { --float-y: -2.6%; } to { --float-y: 2.6%; } }
@keyframes shape-bottom-r { from { --float-r: 1deg; }  to { --float-r: -1deg; } }
@keyframes hero-btn-in {
  from { opacity: 0; transform: translateY(16px); }
}

/* ── HERO — TABLET & DESKTOP ── */
/* On bigger screens .hero-inner is the Figma frame, scaled to fit the screen
   by width AND height. Everything inside is placed in cqw: 1cqw = 1% of the
   frame width. To take a value from Figma: px ÷ (frame width ÷ 100) = cqw.
   The rules below are shared; each frame further down only sets its numbers. */
/* Which frame a screen gets:
     phone   — narrower than 744px, or a short screen (e.g. a phone turned sideways)
     tablet  — 744–1023px wide and at least 740px tall; or 1024px+ in portrait
     desktop — 1024px+ in landscape (1920px+ gets the wide desktop frame)
   (width >= 744px) is the newer "range" way of writing (min-width: 744px) */
@media (width >= 744px) and (height >= 740px), (width >= 1024px) {
  .hero {
    container-type: inline-size;
    justify-content: var(--frame-align, center);
    padding: 0;
  }
  .hero-inner {
    position: relative;
    width: min(100cqw, var(--screen-h) * var(--frame-w) / var(--frame-h));
    aspect-ratio: var(--frame-w) / var(--frame-h);
  }

  .hero-title {
    position: absolute;
    left: var(--title-x);
    top: var(--title-y);
  }
  .hero-first {
    margin-left: 0;
    font-size: var(--alex-size);
  }
  .hero-last {
    margin: var(--shel-gap) 0 0 var(--shel-x);
    width: var(--shel-w);
  }

  .hero-photo {
    position: absolute;
    left: var(--photo-x);
    top: var(--photo-y);
    width: var(--photo-w);
  }

  .hero-actions {
    position: absolute;
    left: var(--btn-x);
    top: var(--btn-y);
    gap: var(--btn-gap);
    margin-top: 0;
  }
  .hero .btn {
    height: max(44px, var(--btn-h));
    font-size: var(--btn-font);
  }
  .hero .btn-primary {
    flex: none;
    width: var(--btn1-w);
  }
  .hero .btn-contact {
    width: var(--btn2-w);
    border-width: max(1px, 0.1cqw);
  }
  .btn-contact-icon { display: none; }
  .btn-contact-text {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }

  .hero-arrow {
    position: absolute;
    left: var(--arrow-x);
    top: var(--arrow-y);
    width: var(--arrow-w);
    height: auto;
    overflow: visible; /* the round line ends may poke out of the box a little */
  }
}

/* iPad mini frame, 744 × 1133 — tablets 744–1023px wide (1cqw = 7.44px) */
@media (744px <= width < 1024px) and (height >= 740px) {
  .hero {
    --frame-w: 744;
    --frame-h: 1133;
    --title-x: 17.28cqw;  --title-y: 59.27cqw;
    --alex-size: 13.51cqw;
    --shel-w: 65.16cqw;  --shel-x: 0.13cqw;  --shel-gap: 2.57cqw;
    --photo-x: 57.08cqw;  --photo-y: 37.76cqw;  --photo-w: 26.13cqw;
    --btn-x: 12.76cqw;  --btn-y: 90.17cqw;  --btn-gap: 4.66cqw;
    --btn-h: 6.55cqw;  --btn-font: 2.69cqw;
    --btn1-w: 33.79cqw;  --btn2-w: 35.86cqw;
    --arrow-x: 82.76cqw;  --arrow-y: 74.65cqw;  --arrow-w: 4.49cqw;  /* arrow-mini.svg */
  }
}

/* iPad Pro 12.9" frame, 1024 × 1366 — 1024px+ in portrait (1cqw = 10.24px) */
@media (width >= 1024px) and (orientation: portrait) {
  .hero {
    --frame-w: 1024;
    --frame-h: 1366;
    --title-x: 12.47cqw;  --title-y: 49.38cqw;
    --alex-size: 14.63cqw;
    --shel-w: 70.72cqw;  --shel-x: 2.21cqw;  --shel-gap: 2.41cqw;
    --photo-x: 58.05cqw;  --photo-y: 29.53cqw;  --photo-w: 25.56cqw;
    --btn-x: 20.87cqw;  --btn-y: 79.27cqw;  --btn-gap: 4.36cqw;
    --btn-h: 5.96cqw;  --btn-font: 2.34cqw;
    --btn1-w: 24.78cqw;  --btn2-w: 28.90cqw;
    --arrow-x: 81.42cqw;  --arrow-y: 64.86cqw;  --arrow-w: 8.33cqw;
  }
}

/* Desktop frame, 1440 × 1024 — 1024px+ in landscape (1cqw = 14.4px) */
@media (width >= 1024px) and (orientation: landscape) {
  .hero {
    --frame-w: 1440;
    --frame-h: 1024;
    --frame-align: flex-end; /* the frame sits at the bottom, so the photo touches the edge */
    --title-x: 7cqw;  --title-y: 26.02cqw;
    --alex-size: 12.5cqw;
    --shel-w: 49.73cqw;  --shel-x: 0.00cqw;  --shel-gap: 1.19cqw;
    --photo-w: 33.92cqw;
    --btn-x: 7cqw;  --btn-y: 47.4cqw;  --btn-gap: 2.15cqw;
    --btn-h: 4.13cqw;  --btn-font: 1.67cqw;
    --btn1-w: 17.33cqw;  --btn2-w: 20.47cqw;
    --arrow-x: 36cqw;  --arrow-y: 55.03cqw;  --arrow-w: 20.65cqw;
  }

  /* On desktop the photo box is anchored to the bottom right and has its own
     proportions; the shapes sit differently relative to the person */
  .hero-photo {
    left: auto;
    top: auto;
    right: 4.58cqw;
    bottom: 0;
    aspect-ratio: 488.5 / 763.5;
    -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent);
            mask-image: linear-gradient(to bottom, #000 82%, transparent);
  }
  .hero-shape-top    { left: 2.37%;  top: 0;      width: 57.26%; }
  .hero-shape-bottom { left: 22.74%; top: 28.36%; width: 77.22%; }
  .hero-person       { left: -24.8%; top: 7.5%;   width: 132%; }
}

/* Wide frame, 1920 × 1024 — landscape screens 1920px+ wide (1cqw = 19.2px).
   Builds on the desktop frame above: only the numbers change. */
@media (width >= 1920px) and (orientation: landscape) {
  .hero {
    --frame-w: 1920;
    --frame-h: 1024;
    --title-x: 10.43cqw;  --title-y: 16.50cqw;
    --alex-size: 10.45cqw;
    --shel-w: 43.59cqw;  --shel-x: -0.07cqw;  --shel-gap: 1.09cqw;
    --photo-w: 28.10cqw;
    --btn-x: 10.36cqw;  --btn-y: 35.18cqw;  --btn-gap: 1.61cqw;
    --btn-h: 3.21cqw;  --btn-font: 1.25cqw;
    --btn1-w: 13.03cqw;  --btn2-w: 15.36cqw;
    --arrow-x: 31.43cqw;  --arrow-y: 39.29cqw;  --arrow-w: 33.57cqw;  /* arrow-wide.svg */
  }
  .hero-photo { right: 7.43cqw; }
}

/* Skills sits behind Hero (negative margin) and slides out by --reveal
   as you scroll. JS only sets --p (0…1), CSS works out the clip-path. */
.skills-section {
  --p: 0;
  position: relative;
  z-index: 1;
  height: calc(var(--screen-h) + var(--reveal));
  margin-top: calc(-1 * var(--screen-h));
  background: var(--orange);
  border-radius: 0 0 var(--radius) var(--radius);
  clip-path: inset(0 0 calc(var(--reveal) * (1 - var(--p))) 0
                   round 0 0 var(--radius) var(--radius));
}
/* The part of the Skills block that shows below Hero */
.skills-strip {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: var(--reveal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--gutter);
}

/* ── SKILLS (the list inside the orange strip) ── */
/* Dot size and gaps are in em, so they grow together with the text */
/* Phone: one under another, starting with HTML */
.skills {
  display: flex;
  flex-direction: column;
  gap: 0.8em;
  list-style: none;
  font-weight: 800;
  font-size: clamp(22px, 6.9vw, 31px); /* 27px at 390 */
  line-height: 1;
  color: var(--white);
}
.skills li {
  display: flex;
  align-items: center;
  gap: 0.33em;
  /* hidden until the strip has slid out far enough to show it; then it fades in
     dropping a little from above (the script adds .is-in, one after another) */
  opacity: 0;
  translate: 0 -0.5em;
  transition: opacity 0.5s ease-out, translate 0.75s cubic-bezier(0.22, 1, 0.36, 1);
}
.skills li.is-in { opacity: 1; translate: 0 0; }
/* the dot before each skill */
.skills li::before {
  content: '';
  flex-shrink: 0;
  width: 0.53em;
  height: 0.53em;
  border-radius: 50%;
  background: currentColor;
}

/* Tablets: 2 × 2 — HTML and CSS on top, JavaScript and and More below.
   Same screens as the tablet frames of the Hero. */
@media (744px <= width < 1024px) and (height >= 740px), (width >= 1024px) and (orientation: portrait) {
  .skills {
    display: grid;
    grid-template-columns: auto auto;
    gap: 0.9em 3em; /* between rows, between columns */
    font-size: clamp(30px, 4vw, 34px);
  }
}

/* Desktop: one row, sizes from the 1440 mockup.
   The strip scales with the screen width: 16.56vw = 238px at 1440 and 318px at 1920 */
@media (width >= 1024px) and (orientation: landscape) {
  .skills-section { --reveal: 16.56vw; }
  .skills-strip { padding-top: 1.597vw; } /* the list sits a little below centre, as in the mockup */
  .skills {
    flex-direction: row;
    gap: 0 3.02em;
    font-size: 2.083vw; /* 30px at 1440 */
  }
}

/* ── ABOUT ── */
/* Phone and tablet: the photo sits on the left and the text wraps around it,
   like a picture in a book. Values from the phone mockup (390). */
.about {
  padding: 64px 0 48px;
}
.about-inner {
  padding-inline: var(--gutter);
}
/* Section title with the line under it — used by every section (About,
   Projects, Get a Quote, Contact). The line is a 1px gradient that fades
   out at both ends, same as section-line.svg, so it needs no image file. */
.section-title {
  margin: 0 34px 0 18px;
  padding-bottom: 18px;
  background: linear-gradient(to right, transparent, var(--line) 10%, var(--line) 90%, transparent)
              bottom / 100% 1px no-repeat;
  font-weight: 700;
  font-size: 26px;
  line-height: 1;
  color: var(--text);
}
.about-body {
  margin-top: 20px;
}
/* keeps the section tall enough even if the text were shorter than the photo */
.about-body::after {
  content: '';
  display: block;
  clear: both;
}

/* The photo box floats left and is as wide as the column; the text wraps
   around it like a picture in a book. shape-outside is the outline the text
   follows: it traces the right edge of the person (and the tag), measured from
   the photo itself (redo it if you change the photo), and
   shape-margin keeps a gap. Points are % of this box.
   --pl / --pw: where the person starts and how wide it is (% of the column). */
.about-photo {
  --pl: 2.5%;
  --pw: 50%;
  position: relative;
  float: left;
  width: 100%;
  shape-outside: polygon(0 0, 33.2% 0.0%, 33.2% 4.0%, 35.1% 8.0%, 35.5% 12.0%, 34.8% 16.0%, 35.6% 20.0%, 35.3% 24.0%, 33.0% 28.0%, 32.1% 32.0%, 38.7% 35.0%, 53.3% 35.0%, 53.3% 45.0%, 45.4% 45.0%, 46.6% 48.0%, 47.6% 52.0%, 48.3% 56.0%, 48.9% 60.0%, 49.4% 64.0%, 49.8% 68.0%, 50.1% 72.0%, 50.5% 76.0%, 50.5% 80.0%, 50.6% 84.0%, 50.5% 88.0%, 50.5% 100%, 0 100%);
  shape-margin: 12px;
}
/* Narrow phones: a slightly smaller photo, so the text beside it isn't too narrow */
@media (width < 380px) {
  .about-photo {
    --pw: 42%;
    shape-outside: polygon(0 0, 28.3% 0.0%, 28.3% 4.0%, 29.9% 8.0%, 30.2% 12.0%, 29.6% 16.0%, 30.3% 20.0%, 30.1% 24.0%, 28.1% 28.0%, 27.4% 32.0%, 32.9% 35.0%, 45.1% 35.0%, 45.1% 45.0%, 38.5% 45.0%, 39.6% 48.0%, 40.4% 52.0%, 41.0% 56.0%, 41.5% 60.0%, 41.9% 64.0%, 42.3% 68.0%, 42.5% 72.0%, 42.8% 76.0%, 42.9% 80.0%, 42.9% 84.0%, 42.8% 88.0%, 42.8% 100%, 0 100%);
    shape-margin: 8px;
  }
}
/* "Alex" tag (SVG) at the neck/shoulder, peeking out from behind the person */
.about-tag {
  position: absolute;
  left: calc(var(--pl) + var(--pw) * 0.66); /* 0.66 = share of the person's width: its left end tucks behind the neck */
  top: 35%;
  width: calc(var(--pw) * 0.355);
  height: auto;
}
/* The box is exactly the visible person (tight around them) */
.about-person {
  position: relative;
  z-index: 1; /* in front of the tag */
  width: var(--pw);
  margin-left: var(--pl);
  aspect-ratio: 697 / 1120;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 79%, transparent);
          mask-image: linear-gradient(to bottom, #000 79%, transparent);
}
/* Your photo file has empty space around the person, so the image is
   bigger than the box and shifted: the box shows just the person */
.about-person img {
  display: block;
  width: 143.5%;
  max-width: none;
  height: auto;
  margin: -10.04% 0 0 -17.65%;
}

.about-content {
  font-weight: 500;
  font-size: 17px;
  line-height: 1.3;
  color: var(--text);
}
.about-content p + p { margin-top: 1.3em; }
.accent {
  font-weight: 600;
  color: var(--orange-text);
}
strong.accent { font-weight: 800; } /* ExtraBold */

/* Highlighter for key phrases, used all over the site.
   --marker-from: where the colour starts (66% = thin, 52% = thicker)
   --marker-color: the marker's colour */
mark {
  padding: 0 0.15em;
  background: linear-gradient(transparent var(--marker-from, 66%), var(--marker-color, var(--yellow)) 0);
  color: inherit;
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone; /* if the text wraps, each line gets its own marker */
}
.about-content mark { font-weight: 600; }

/* ── About: entrance ──
   One wave, the first time each part comes into view (the script adds .is-in;
   --d is its place in the queue, so parts that come in together follow each other).
   Photo rises → the Alex tag slides out from behind the person → the paragraphs
   one by one → the marker is drawn under its phrase → "work:" turns orange and
   ExtraBold with a little pop → the button rises, and then its arrow draws. */
.about-person {
  opacity: 0;
  translate: 0 6%;
  transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s),
              translate 0.8s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s);
}
.about-tag {
  opacity: 0;
  translate: -45% 0;
  transition: opacity 0.35s ease-out calc(var(--d, 0s) + 0.45s),
              translate 0.7s cubic-bezier(0.34, 1.4, 0.64, 1) calc(var(--d, 0s) + 0.45s);
}
.about-photo.is-in .about-person,
.about-photo.is-in .about-tag { opacity: 1; translate: 0 0; }
.about-content p,
.about-btn {
  opacity: 0;
  translate: 0 14px;
  transition: opacity 0.6s ease-out var(--d, 0s),
              translate 0.8s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s);
}
/* the button keeps its usual hover transitions as well */
.about-btn {
  transition: opacity 0.6s ease-out var(--d, 0s),
              translate 0.8s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s),
              background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease,
              transform 0.25s ease, box-shadow 0.25s ease;
}
.about-content p.is-in,
.about-cta.is-in .about-btn { opacity: 1; translate: 0 0; }
/* the marker is drawn from left to right */
.about-content mark {
  background-size: 0% 100%;
  background-repeat: no-repeat;
  transition: background-size 0.8s cubic-bezier(0.65, 0, 0.35, 1) calc(var(--d, 0s) + 0.5s);
}
.about-content p.is-in mark { background-size: 100% 100%; }
/* "work:" starts as plain text, then turns orange and ExtraBold with a little pop.
   It sits in a box as wide as its bold version (the hidden copy after it), so the
   rest of the line doesn't shift while the word thickens. */
.about-content .accent { display: inline-grid; font-weight: 500; color: var(--text); }
.about-content .accent > span,
.about-content .accent::after { grid-area: 1 / 1; justify-self: center; }
.about-content .accent::after { content: attr(data-word); font-weight: 800; visibility: hidden; }
.about-content .accent > span {
  transition: color 0.4s ease-out calc(var(--d, 0s) + 0.6s),
              font-weight 0.4s ease-out calc(var(--d, 0s) + 0.6s);
}
.about-content p.is-in .accent > span {
  color: var(--orange-text);
  font-weight: 800;
  animation: work-pop 0.55s cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--d, 0s) + 0.6s) both;
}
@keyframes work-pop { 0%, 100% { scale: 1; } 45% { scale: 1.16; } }

.about-cta {
  clear: both; /* always below the photo */
  margin-top: 32px;
}
/* holds the button and the arrow */
.about-cta-inner {
  position: relative;
  display: block;
}
/* Phone: full-width button, text shrinks a little on narrow screens so it fits */
.about-btn {
  width: 100%;
  padding-inline: 16px;
  font-size: clamp(14px, 4.4vw, 18px);
}
.about-arrow { display: none; } /* hidden on phones */

/* iPad mini (744–799px): bigger photo, the text runs down its right side
   along the outline. Under the photo: the button with the long tablet
   arrow, centred together; the arrow leads from the end of the text. */
@media (744px <= width < 800px) and (height >= 740px) {
  .about-photo {
    --pw: 40%;
    shape-outside: polygon(0 0, 27.0% 0.0%, 27.0% 4.0%, 28.6% 8.0%, 28.9% 12.0%, 28.3% 16.0%, 29.0% 20.0%, 28.8% 24.0%, 26.9% 28.0%, 26.2% 32.0%, 31.5% 35.0%, 43.1% 35.0%, 43.1% 45.0%, 36.8% 45.0%, 37.8% 48.0%, 38.6% 52.0%, 39.1% 56.0%, 39.6% 60.0%, 40.0% 64.0%, 40.4% 68.0%, 40.6% 72.0%, 40.9% 76.0%, 40.9% 80.0%, 41.0% 84.0%, 40.9% 88.0%, 40.9% 100%, 0 100%);
    shape-margin: 20px;
  }
  .about-cta {
    margin-top: 24px;
    text-align: center;
  }
  /* the button and the arrow side by side, centred as one group */
  .about-cta-inner {
    display: inline-flex;
    align-items: flex-end;
    gap: 12px;
  }
  .about-btn {
    width: auto;
    padding-inline: 28px;
    font-size: 18px;
  }
  .about-arrow {
    display: block;
    width: 264px;
    height: auto;
    margin-bottom: 6px; /* the arrowhead points at the middle of the button */
  }
  .about-arrow--short { display: none; }
}

/* Bigger tablets (800px+): like desktop — photo on the left; on the right
   the text and, right under it, the button with the arrow */
@media (800px <= width < 1024px) and (height >= 740px), (width >= 1024px) and (orientation: portrait) {
  .about-body {
    display: grid;
    grid-template-columns: 36% 1fr;
    grid-template-rows: 1fr auto auto 1fr; /* text + button centred next to the photo */
    column-gap: 7%; /* room for the tag, which sticks out to the right of the photo */
    margin-top: 32px;
  }
  .about-body::after { display: none; } /* not needed in the grid */
  .about-photo {
    --pl: 0%;
    --pw: 100%;
    grid-row: 1 / -1;
    align-self: center;
    float: none;
  }
  .about-content {
    grid-column: 2;
    grid-row: 2;
  }
  .about-cta {
    grid-column: 2;
    grid-row: 3;
    /* space between the text and the button; the text + button pair stays
       centred next to the photo, so a bigger gap lifts the text and lowers
       the button by half each. Keeps the arrow clear of the last line. */
    margin-top: 60px;
  }
  .about-cta-inner { display: inline-block; }
  .about-btn {
    width: auto;
    padding-inline: 24px;
    font-size: 16px;
  }
  .about-arrow {
    display: block;
    position: absolute;
    left: calc(100% + 20px);
    bottom: 8px;
    width: 80px;
    height: auto;
  }
  .about-arrow--long { display: none; }
}

/* Desktop (mockup 1440): two columns, everything scales with the screen width
   (px from the mockup ÷ 14.4 = vw) */
@media (width >= 1024px) and (orientation: landscape) {
  .about {
    padding: 8.17vw 0 4.17vw;
  }
  .about-inner {
    padding-inline: 4.10vw;
  }
  .section-title {
    margin: 0;
    padding: 0 0 1.69vw 3.61vw;
    font-size: 2.08vw;
  }
  .about-body {
    display: grid;
    grid-template-columns: 47.65vw 1fr;
    grid-template-rows: 1fr auto auto 1fr; /* text + button centred next to the photo */
    gap: 0;
    margin-top: 3.19vw;
  }
  .about-body::after { display: none; } /* not needed in the grid */
  .about-photo {
    grid-row: 1 / -1;
    align-self: center;
    float: none;
    width: 31.97vw;
    margin: 0 0 0 4.59vw;
  }
  .about-photo {
    --pl: 0%;
    --pw: 100%;
  }
  .about-content {
    grid-column: 2;
    grid-row: 2;
    max-width: 36.11vw;
    font-size: max(16px, 1.35vw);
    line-height: 1.11;
  }
  .about-content p + p { margin-top: 1.11em; }
  .about-cta {
    grid-column: 2;
    grid-row: 3;
    margin-top: 3.61vw;
    margin-bottom: 0.56vw; /* text + button sit slightly above centre, as in the mockup */
  }
  .about-cta-inner {
    display: inline-block;
    margin-left: 0.35vw;
  }
  .about-btn {
    width: auto;
    height: max(44px, 3.01vw);
    padding-inline: 1.97vw;
    font-size: max(16px, 1.25vw);
  }
  .about-arrow {
    display: block;
    position: absolute;
    left: calc(100% + 2.78vw);
    bottom: 0.60vw;
    width: 6.88vw;
    height: auto;
  }
  .about-arrow--long { display: none; }
}

/* ── PROJECTS ── */
/* Phone: cards one under another (to be tuned with the phone mockup) */
.projects {
  padding: 48px 0;
}
.projects-inner {
  padding-inline: var(--gutter);
}
.projects-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
  margin-top: 24px;
  list-style: none;
}
/* The card is a button (it opens a window, not another page).
   Sizes inside are in cqw — % of the card width — so they scale with it. */
/* the cards' corner radius lives on the <li>, so its focus ring (below) can use it too */
.projects-list > li { --card-r: 32px; border-radius: var(--card-r); }
.project-card {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 365 / 283;
  padding: 0;
  border: 0;
  border-radius: var(--card-r);
  /* Rounded corners cut the whole card as ONE picture. With overflow: hidden the
     browser cut each layer on its own, and at the soft edge of the corner a little
     of the screenshot showed through the band and the Concept tag: a thin dark line.
     The mask makes the browser draw the card first and cut it after. */
  clip-path: inset(0 round var(--card-r));
  -webkit-mask-image: linear-gradient(#000, #000);
  mask-image: linear-gradient(#000, #000);
  background: var(--orange); /* empty cards stay plain orange for now */
  container-type: inline-size;
  font: inherit;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  isolation: isolate; /* helps the rounded corners clip the zoomed screenshot in every browser */
}
/* The cut above would hide the card's own focus ring (it's drawn outside the card),
   so the ring is drawn on the <li> around it instead. Same look as everywhere else. */
.project-card:focus-visible { outline: none; }
.projects-list > li:has(> .project-card:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 4px;
}
.project-card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top left;
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Yellow "Concept" tag in the corner. The card's cut (see .project-card) rounds its
   corner, so the tag has no rounded corner of its own: two soft edges on top of each
   other let the dark screenshot show through as a hairline. */
.project-tag {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  padding: 2.4cqw 6cqw 2.4cqw 15cqw;
  background: var(--yellow);
  clip-path: polygon(0 0, 100% 0, 98% 100%, 0 100%); /* slightly slanted right edge */
  font-weight: 600;
  font-size: clamp(12px, 5.4cqw, 22px);
  line-height: 1;
  color: var(--text);
}

/* Orange 40% tint over the whole screenshot */
.project-overlay {
  position: absolute;
  inset: 0;
  background: rgb(246 149 64 / 0.4);
  opacity: 0;
  transition: opacity 0.4s ease;
}
.project-caption {
  position: absolute;
  left: 7cqw;
  right: 7cqw;
  bottom: 6cqw;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 4cqw;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
/* Solid orange behind the text, fading out above it. It follows the
   caption's real height, so the text never sits on the busy screenshot. */
.project-caption::before {
  content: '';
  position: absolute;
  inset: -24cqw -7cqw -6cqw;
  z-index: -1;
  background: linear-gradient(to top, rgb(246 149 64 / 0.97) calc(100% - 24cqw), rgb(246 149 64 / 0));
}
.project-name {
  display: block;
  font-weight: 700;
  font-size: clamp(15px, 6.4cqw, 28px);
  line-height: 1.1;
}
.project-desc {
  display: block;
  margin-top: 0.4em;
  font-weight: 600;
  font-size: clamp(12px, 3.9cqw, 17px);
  line-height: 1.25;
}
/* Small cards (narrow tablets): just the name. Placed after .project-desc,
   otherwise that rule's display: block would win. */
@container (width < 240px) {
  .project-desc { display: none; }
}
/* round arrow: "this opens" */
.project-open {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: clamp(32px, 11cqw, 48px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--white);
  color: var(--text);
}
.project-open svg { width: 45%; height: 45%; }

/* Mouse: the effect appears on hover. Keyboard: on focus. */
@media (hover: hover) {
  .project-card:hover img { transform: scale(1.05); }
  .project-card:hover .project-overlay { opacity: 1; }
  .project-card:hover .project-caption { opacity: 1; transform: none; }
}
.project-card:focus-visible .project-overlay { opacity: 1; }
.project-card:focus-visible .project-caption { opacity: 1; transform: none; }
/* Touch screens can't hover, so the name and the arrow are always shown */
@media (hover: none) {
  .project-overlay,
  .project-caption { opacity: 1; transform: none; }
}

/* Tablets: three in a row, like desktop */
@media (744px <= width < 1024px) and (height >= 740px), (width >= 1024px) and (orientation: portrait) {
  .projects-list {
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    margin-top: 28px;
    padding-inline: 18px;
  }
  .projects-list > li { --card-r: 28px; }
}

/* Desktop (mockup 1440): px ÷ 14.4 = vw */
@media (width >= 1024px) and (orientation: landscape) {
  .projects {
    padding: 4.17vw 0;
  }
  .projects-inner {
    padding-inline: 4.10vw;
  }
  .projects-list {
    grid-template-columns: repeat(3, 1fr);
    gap: 3.96vw;
    margin-top: 2.64vw;
    padding-inline: 3.89vw;
  }
  .projects-list > li { --card-r: 4.86vw; }
}

/* ── SCROLLBAR (computers only) ── */
/* Phones and tablets show a thin scrollbar only while you swipe,
   so this is only for mouse/trackpad screens */
@media (hover: hover) and (pointer: fine) {
  /* Chrome, Edge, Safari */
  ::-webkit-scrollbar { width: 12px; height: 12px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    border: 3px solid transparent; /* makes the pill thinner than the track */
    border-radius: 999px;
    background: var(--line) padding-box;
  }
  ::-webkit-scrollbar-thumb:hover { background-color: var(--orange); }
  /* Firefox doesn't know ::-webkit-scrollbar, so it gets the standard properties */
  @supports not selector(::-webkit-scrollbar) {
    html {
      scrollbar-width: thin;
      scrollbar-color: var(--line) transparent;
    }
  }
}

/* ── Projects: entrance ──
   The first time the cards come into view they rise one after another (the script
   adds .is-in and --d, the same as About); then the Concept tag slides into its corner. */
.projects-list > li {
  opacity: 0;
  translate: 0 32px;
  scale: 0.97;
  transition: opacity 0.6s ease-out var(--d, 0s),
              translate 0.9s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s),
              scale 0.9s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s);
}
.projects-list > li.is-in { opacity: 1; translate: 0 0; scale: 1; }
.projects-list .project-tag {
  translate: -101% 0;
  transition: translate 0.55s cubic-bezier(0.22, 1, 0.36, 1) calc(var(--d, 0s) + 0.45s);
}
.projects-list > li.is-in .project-tag { translate: 0 0; }

/* ── PROJECT WINDOW (dialog) ── */
/* <dialog> gives the dark background, Esc to close and keeps keyboard
   focus inside the window. Desktop and tablet: a big rounded card. */
.project-dialog {
  margin: auto; /* centres the window (the reset at the top sets margin: 0 everywhere) */
  width: min(92vw, 960px);
  max-width: none;
  max-height: min(88vh, 840px);
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 40px;
  background: var(--orange);
  color: var(--text);
}
.project-dialog::backdrop {
  background: rgb(40 38 36 / 0.55);
  backdrop-filter: blur(4px);
}
html:has(.project-dialog[open]) { overflow: hidden; } /* the page behind doesn't scroll */
html { scrollbar-gutter: stable; } /* the page doesn't jump sideways when the scrollbar hides */
/* ...but the space kept for the scrollbar isn't covered by the dark background
   of the window, so it showed as a light strip on the right. Paint it the same
   colour as the dimmed page (the backdrop over #FFFFFD). */
html:has(.project-dialog[open]) { background-color: rgb(137 136 134); }

.project-dialog-inner {
  display: flex;
  flex-direction: column;
  max-height: inherit;
}
.project-dialog-media {
  position: relative;
  z-index: 1; /* so its shadow falls onto the orange part below */
  flex: none;
  height: 200px;
  box-shadow: 0 6px 16px rgb(60 30 0 / 0.22); /* soft shadow = smoother transition */
}
.project-dialog-media picture { display: contents; }
.project-dialog-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--pos-wide, 50% 40%);
}
@media (width < 744px) {
  .project-dialog-media img { object-position: var(--pos-phone, top); }
}
/* In the window the tag sits on the bottom edge of the screenshot,
   with a big rounded top-right corner (the huge radius is capped at the tag's height) */
.project-dialog-media .project-tag {
  top: auto;
  bottom: 0;
  padding: 10px 32px 8px 24px;
  clip-path: none;
  border-radius: 0 999px 0 0;
  font-size: 18px;
}
.project-dialog-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: var(--white);
  color: var(--text);
  cursor: pointer;
}
.project-dialog-close svg { width: 18px; height: 18px; }
.project-dialog-close:focus-visible { border-radius: 50%; }

.project-dialog-body {
  flex: 1 1 auto;
  min-height: 0;    /* lets the body shrink so it can scroll */
  overflow-y: auto; /* long text scrolls inside the window */
  /* The scrollbar sits between the padding and the border, so a transparent
     border moves it 18px in from the window's edges. Text stays where it was:
     18 + 14 = 32px from the top, 18 + 22 = 40px from the right and bottom. */
  border: 18px solid transparent;
  border-left: 0;
  padding: 14px 22px 22px 40px;
}
.project-dialog-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px 24px;
}
.project-dialog-title {
  font-weight: 700;
  font-size: clamp(24px, 3vw, 34px);
  line-height: 1.1;
}
.project-dialog-sub {
  margin-top: 8px;
  font-weight: 600;
  font-size: 17px;
}
.project-dialog-sub mark { --marker-from: 52%; } /* thicker marker on the orange */
.project-dialog-visit {
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  gap: 8px;
  padding-inline: 28px 24px;
  background: var(--white);
  color: var(--text);
}
.project-dialog-visit svg {
  width: 14px;
  height: 14px;
  transition: transform 0.3s ease;
}
.project-dialog-close { transition: background-color 0.3s ease; }
.project-dialog-close svg { transition: transform 0.3s ease; }
/* Hover (mouse only): "Visit website" rises like every button (see HOVER below)
   and its arrow nudges towards the corner; the round cross turns a quarter */
@media (hover: hover) {
  .project-dialog-visit:hover svg { transform: translate(3px, -3px); }
  .project-dialog-close:hover svg { transform: rotate(90deg); }
}
/* Scrollbar inside the window (computers only; it appears when the text
   doesn't fit): a cream pill on a darker track, small arrows at both ends */
@media (hover: hover) and (pointer: fine) {
  /* Chrome, Edge, Safari */
  .project-dialog-body::-webkit-scrollbar { width: 8px; }
  .project-dialog-body::-webkit-scrollbar-track {
    margin-block: 6px; /* gap between the track and the arrows */
    border: 0;
    border-radius: 999px;
    background: rgb(0 0 0 / 0.08);
  }
  .project-dialog-body::-webkit-scrollbar-thumb {
    border: 0;
    border-radius: 999px;
    background: var(--cream);
  }
  .project-dialog-body::-webkit-scrollbar-thumb:hover { background: var(--white); }
  /* the arrows: one at each end */
  .project-dialog-body::-webkit-scrollbar-button:single-button {
    display: block;
    height: 9px;
    background: center / 10px 9px no-repeat;
  }
  .project-dialog-body::-webkit-scrollbar-button:single-button:vertical:decrement { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 12'%3E%3Cpath d='M7 2L12 10H2Z' fill='%23FFF5E0' stroke='%23FFF5E0' stroke-width='2.5' stroke-linejoin='round'/%3E%3C/svg%3E"); }
  .project-dialog-body::-webkit-scrollbar-button:single-button:vertical:increment { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 12'%3E%3Cpath d='M7 10L12 2H2Z' fill='%23FFF5E0' stroke='%23FFF5E0' stroke-width='2.5' stroke-linejoin='round'/%3E%3C/svg%3E"); }
  /* Firefox: no custom shapes or arrows, just the colours */
  @supports not selector(::-webkit-scrollbar) {
    .project-dialog-body {
      scrollbar-width: thin;
      scrollbar-color: var(--cream) rgb(0 0 0 / 0.08);
    }
  }
}

/* keyboard focus ring: dark, so it shows on the orange */
.project-dialog :focus-visible { outline-color: var(--text); }
.project-dialog-text {
  max-width: 62ch;
  margin-top: 28px;
  font-weight: 500;
  font-size: 17px;
  line-height: 1.4;
}
.project-dialog-text h4 {
  margin-top: 22px;
  font-weight: 700;
  font-size: 18px;
}
.project-dialog-text h4:first-child { margin-top: 0; }
.project-dialog-text p { margin-top: 6px; }
/* a short list: each point starts with its idea in bold */
.project-dialog-text ul {
  display: grid;
  gap: 8px;
  margin-top: 8px;
  list-style: none;
}
.project-dialog-text li {
  position: relative;
  padding-left: 1.1em;
}
.project-dialog-text li::before {
  content: '';
  position: absolute;
  left: 0.15em;
  top: 0.55em;
  width: 0.4em;
  height: 0.4em;
  border-radius: 50%;
  background: currentColor;
}
.project-dialog-text strong { font-weight: 700; }

/* LOOK of the project cards and windows: change one word,
   data-look="..." on <section class="projects">.
     calm   = clean screenshot, cream band on the card; cream window with orange accents
     orange = clean screenshot, solid orange band; orange window with dark text
     old    = the previous look (orange haze over the screenshot, grey text on orange) */
.projects:is([data-look="calm"], [data-look="orange"]) .project-overlay { background: none; }
.projects:is([data-look="calm"], [data-look="orange"]) .project-caption::before {
  inset: -5cqw -7cqw -6cqw; /* a solid band with a straight edge, no fade over the screenshot */
  background: var(--orange);
  /* the screenshot casts a soft shadow down onto the band, like the picture in the window */
  box-shadow: inset 0 9px 14px -9px rgb(60 30 0 / 0.30);
}
.projects[data-look="orange"] .project-caption,
.projects[data-look="orange"] .project-dialog { color: var(--on-orange); } /* 5:1 on the orange */

.projects[data-look="calm"] .project-caption::before { background: var(--cream); }
.projects[data-look="calm"] .project-open { background: var(--orange); color: var(--on-orange); }
.projects[data-look="calm"] .project-dialog { background: var(--cream); }
.projects[data-look="calm"] .project-dialog-visit { background: var(--orange); color: var(--on-orange); }
.projects[data-look="calm"] .project-dialog-text li::before { background: var(--orange); }

/* Text in the window: section headings become small capital labels (THE IDEA,
   WHAT I FOCUSED ON, BUILT WITH), so they stand apart from the paragraphs; a bit
   more space between lines makes the longer text easier to read. */
.projects:is([data-look="calm"], [data-look="orange"]) .project-dialog-text { line-height: 1.55; }
.projects:is([data-look="calm"], [data-look="orange"]) .project-dialog-text h4 {
  margin-top: 30px;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.projects:is([data-look="calm"], [data-look="orange"]) .project-dialog-text h4:first-child { margin-top: 0; }
.projects:is([data-look="calm"], [data-look="orange"]) .project-dialog-text :is(p, ul) { margin-top: 8px; }
.projects:is([data-look="calm"], [data-look="orange"]) .project-dialog-text ul { gap: 10px; }
/* dark orange on the cream (4.5:1); on the orange window the labels stay dark */
.projects[data-look="calm"] .project-dialog-text h4 { color: var(--orange-text-small); }
@media (hover: hover) {
  /* the orange button glows orange, like the other orange buttons */
  .projects[data-look="calm"] .project-dialog-visit:hover { box-shadow: 0 8px 18px rgb(246 149 64 / 0.45); }
}
@media (hover: hover) and (pointer: fine) {
  .projects[data-look="calm"] .project-dialog-body::-webkit-scrollbar-thumb { background: var(--orange); }
  .projects[data-look="calm"] .project-dialog-body::-webkit-scrollbar-thumb:hover { background: var(--orange-text); }
  .projects[data-look="calm"] .project-dialog-body::-webkit-scrollbar-button:single-button:vertical:decrement { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 12'%3E%3Cpath d='M7 2L12 10H2Z' fill='%23F69540' stroke='%23F69540' stroke-width='2.5' stroke-linejoin='round'/%3E%3C/svg%3E"); }
  .projects[data-look="calm"] .project-dialog-body::-webkit-scrollbar-button:single-button:vertical:increment { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 12'%3E%3Cpath d='M7 10L12 2H2Z' fill='%23F69540' stroke='%23F69540' stroke-width='2.5' stroke-linejoin='round'/%3E%3C/svg%3E"); }
  @supports not selector(::-webkit-scrollbar) {
    .projects[data-look="calm"] .project-dialog-body { scrollbar-color: var(--orange) rgb(0 0 0 / 0.08); }
  }
}

/* Phones: the window fills the whole screen, like its own page */
@media (width < 744px) {
  .project-dialog {
    width: 100vw;
    height: 100dvh;
    max-height: none;
    border-radius: 0;
  }
  .project-dialog-inner { height: 100%; }
  .project-dialog-media { height: 180px; }
  .project-dialog-body {
    flex: 1;
    border: 0;
    padding: 24px var(--gutter) 40px;
  }
  .project-dialog-visit { width: 100%; }
}

/* ── SOFT url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E")S on buttons ── */
/* Rounded arrow drawn in the text's colour (mask + currentColor).
   .icon-arrow-after: arrow after the text; .icon-arrow-before: before it, pointing back */
.icon-arrow-after::after,
.icon-arrow-before::before {
  content: '';
  display: inline-block;
  width: 1.05em;
  height: 1.05em;
  vertical-align: -0.2em;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 6.5l5.5 5.5-5.5 5.5'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 0.25s ease;
}
.icon-arrow-after::after { margin-left: 0.45em; }
.icon-arrow-before::before { margin-right: 0.4em; transform: scaleX(-1); }
/* on hover the arrow nudges in its direction */
@media (hover: hover) {
  .icon-arrow-after:not(:disabled):hover::after { transform: translateX(3px); }
  .icon-arrow-before:hover::before { transform: scaleX(-1) translateX(3px); }
}

/* ── ARROWS: SMOOTH DRAWING ── */
/* Every arrow draws in ONE continuous movement, like a pen: the line is one long dash
   sliding into place (dashoffset 1.01 = nothing drawn, 0 = all drawn).
   The speed lives in the linear() easing on each arrow, worked out from the arrow itself:
   a gentle start, slower round the loop, easing into the tip, then a quick flick for the
   head (the bit drawn twice, back to the tip, goes instantly, so there's no pause).
   Older browsers that don't know linear() use the cubic-bezier before it. */
@keyframes draw-line {
  from { stroke-dashoffset: 1.01; }
  to   { stroke-dashoffset: 0; }
}
/* the arrow head springs out of the tip */
@keyframes arrow-head-pop {
  from { transform: scale(0); }
  to   { transform: scale(1); }
}
/* Contact: the glint behind the pen, and the shine at the end */
@keyframes contact-glint-pen {
  from { stroke-dashoffset: 0.0725; }
  to   { stroke-dashoffset: -0.9375; }
}
@keyframes glint-pen-fade { 0% { opacity: 0; } 2% { opacity: 0.9; } 92% { opacity: 0.9; } 100% { opacity: 0; } }
@keyframes contact-shine-a {
  from { stroke-dashoffset: 113.67; }
  to   { stroke-dashoffset: -921.36; }
}
@keyframes contact-shine-b {
  from { stroke-dashoffset: 712.12; }
  to   { stroke-dashoffset: -322.91; }
}
@keyframes glint-shine-fade { 0% { opacity: 0.00; } 10% { opacity: 0.29; } 20% { opacity: 0.56; } 30% { opacity: 0.77; } 40% { opacity: 0.90; } 50% { opacity: 0.95; } 60% { opacity: 0.90; } 70% { opacity: 0.77; } 80% { opacity: 0.56; } 90% { opacity: 0.29; } 100% { opacity: 0.00; } }
/* Where an arrow crosses itself, the strand underneath gets a soft shadow from the one
   on top, so the crossing reads as over/under. It fades in as the pen crosses. */
.arrow-shadow { opacity: 0; }
.hero-arrow--wide .arrow-shadow { animation: arrow-shadow-in 0.08s linear 2.441s forwards; }
.contact-art.is-drawn .arrow-shadow { animation: arrow-shadow-in 0.08s linear 1.865s forwards; }
@keyframes arrow-shadow-in { to { opacity: 1; } }
/* About: draws itself the first time the button comes into view (the script adds
   .is-drawn), then the head springs out and pokes Discuss your project */
svg.about-arrow { overflow: visible; } /* the round line ends may poke out a little */
.about-arrow .arrow-line { stroke-dasharray: 1 2; stroke-dashoffset: 1.01; }
.about-arrow .arrow-head { transform: scale(0); }
.about-cta.is-drawn .about-arrow--long .arrow-line {
  animation: draw-line 0.9s cubic-bezier(0.45, 0, 0.3, 1) 0.2s forwards;
  animation-timing-function: linear(0.0099 0.00%, 0.0138 1.25%, 0.0179 2.50%, 0.0222 3.75%, 0.0269 5.00%, 0.0319 6.25%, 0.0374 7.50%, 0.0433 8.75%, 0.0498 10.00%, 0.0568 11.25%, 0.0643 12.50%, 0.0722 13.75%, 0.0805 15.00%, 0.0892 16.25%, 0.0981 17.50%, 0.1073 18.75%, 0.1168 20.00%, 0.1265 21.25%, 0.1364 22.50%, 0.1466 23.75%, 0.1571 25.00%, 0.1678 26.25%, 0.1786 27.50%, 0.1897 28.75%, 0.2010 30.00%, 0.2125 31.25%, 0.2242 32.50%, 0.2360 33.75%, 0.2480 35.00%, 0.2602 36.25%, 0.2725 37.50%, 0.2850 38.75%, 0.2976 40.00%, 0.3103 41.25%, 0.3232 42.50%, 0.3362 43.75%, 0.3493 45.00%, 0.3625 46.25%, 0.3759 47.50%, 0.3893 48.75%, 0.4028 50.00%, 0.4165 51.25%, 0.4302 52.50%, 0.4440 53.75%, 0.4579 55.00%, 0.4719 56.25%, 0.4860 57.50%, 0.5002 58.75%, 0.5144 60.00%, 0.5287 61.25%, 0.5431 62.50%, 0.5576 63.75%, 0.5721 65.00%, 0.5867 66.25%, 0.6014 67.50%, 0.6161 68.75%, 0.6309 70.00%, 0.6457 71.25%, 0.6606 72.50%, 0.6756 73.75%, 0.6906 75.00%, 0.7056 76.25%, 0.7207 77.50%, 0.7359 78.75%, 0.7511 80.00%, 0.7664 81.25%, 0.7817 82.50%, 0.7970 83.75%, 0.8124 85.00%, 0.8278 86.25%, 0.8433 87.50%, 0.8588 88.75%, 0.8744 90.00%, 0.8899 91.25%, 0.9056 92.50%, 0.9212 93.75%, 0.9369 95.00%, 0.9526 96.25%, 0.9684 97.50%, 0.9842 98.75%, 1.0000 100.00%);
}
.about-cta.is-drawn .about-arrow .arrow-head {
  animation: arrow-head-pop 0.52s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  animation-timing-function: linear(0.0000 0.0%, 0.1349 2.5%, 0.2600 5.0%, 0.3754 7.5%, 0.4816 10.0%, 0.5789 12.5%, 0.6677 15.0%, 0.7482 17.5%, 0.8208 20.0%, 0.8859 22.5%, 0.9438 25.0%, 0.9947 27.5%, 1.0392 30.0%, 1.0775 32.5%, 1.1099 35.0%, 1.1367 37.5%, 1.1584 40.0%, 1.1752 42.5%, 1.1875 45.0%, 1.1957 47.5%, 1.2000 50.0%, 1.2008 52.5%, 1.1984 55.0%, 1.1933 57.5%, 1.1856 60.0%, 1.1758 62.5%, 1.1642 65.0%, 1.1510 67.5%, 1.1368 70.0%, 1.1218 72.5%, 1.1062 75.0%, 1.0906 77.5%, 1.0752 80.0%, 1.0603 82.5%, 1.0464 85.0%, 1.0336 87.5%, 1.0224 90.0%, 1.0131 92.5%, 1.0061 95.0%, 1.0016 97.5%, 1.0000 100.0%);
}
.about-cta.is-drawn .about-arrow--long .arrow-head { animation-delay: 1.1s; }
.about-cta.is-drawn .about-arrow--short .arrow-line {
  animation: draw-line 0.8s cubic-bezier(0.45, 0, 0.3, 1) 0.2s forwards;
  animation-timing-function: linear(0.0099 0.00%, 0.0140 1.25%, 0.0183 2.50%, 0.0228 3.75%, 0.0277 5.00%, 0.0329 6.25%, 0.0385 7.50%, 0.0445 8.75%, 0.0510 10.00%, 0.0580 11.25%, 0.0653 12.50%, 0.0730 13.75%, 0.0809 15.00%, 0.0890 16.25%, 0.0974 17.50%, 0.1059 18.75%, 0.1146 20.00%, 0.1234 21.25%, 0.1324 22.50%, 0.1415 23.75%, 0.1509 25.00%, 0.1603 26.25%, 0.1700 27.50%, 0.1798 28.75%, 0.1898 30.00%, 0.2000 31.25%, 0.2104 32.50%, 0.2209 33.75%, 0.2316 35.00%, 0.2425 36.25%, 0.2536 37.50%, 0.2649 38.75%, 0.2763 40.00%, 0.2880 41.25%, 0.2998 42.50%, 0.3118 43.75%, 0.3240 45.00%, 0.3364 46.25%, 0.3489 47.50%, 0.3617 48.75%, 0.3746 50.00%, 0.3877 51.25%, 0.4010 52.50%, 0.4145 53.75%, 0.4281 55.00%, 0.4419 56.25%, 0.4559 57.50%, 0.4700 58.75%, 0.4843 60.00%, 0.4988 61.25%, 0.5134 62.50%, 0.5281 63.75%, 0.5430 65.00%, 0.5580 66.25%, 0.5732 67.50%, 0.5885 68.75%, 0.6039 70.00%, 0.6194 71.25%, 0.6351 72.50%, 0.6508 73.75%, 0.6667 75.00%, 0.6826 76.25%, 0.6987 77.50%, 0.7149 78.75%, 0.7311 80.00%, 0.7474 81.25%, 0.7638 82.50%, 0.7803 83.75%, 0.7969 85.00%, 0.8135 86.25%, 0.8302 87.50%, 0.8469 88.75%, 0.8637 90.00%, 0.8806 91.25%, 0.8975 92.50%, 0.9145 93.75%, 0.9315 95.00%, 0.9486 96.25%, 0.9657 97.50%, 0.9828 98.75%, 1.0000 100.00%);
}
.about-cta.is-drawn .about-arrow--short .arrow-head { animation-delay: 1s; }

/* ── HOW IT WORKS ── */
/* Phone and tablet: the steps one under another; the line runs down the left
   through the dots.
   Desktop: the steps climb like stairs, from bottom left to top right, and the
   line waves up through the dots, with a soft shadow under it.
   On every screen a big quiet number sits behind each step, and each dot sits
   on a small white tile with a soft shadow; the line runs in under the tile. */
.process {
  padding: 48px 0;
  --plate: 30px;        /* the white tile */
  --dot: 11px;          /* the dot on it */
  --quiet: #F3ECE4;     /* the numbers and the dots: barely there on the white */
  --title-size: 21px;
}
.process-inner {
  padding-inline: var(--gutter);
}
.process-track {
  position: relative;
  isolation: isolate;   /* the layers below stay inside the track */
  margin-top: 32px;
  padding-left: 11px;   /* the dots line up with the start of the title */
}
/* Layers, bottom to top: the big numbers, the line, then the dots and the text */
.process-num { z-index: 0; }
.process-line { z-index: 1; }
.process-dot, .process-title, .process-text { position: relative; z-index: 2; }

/* The line. The script gives the paths their shape at the real size and draws
   the orange one (see main.js, "How it works"). */
.process-line {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.process-line path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* the way ahead: faint dots */
.process-line-route { stroke: var(--chip-line); stroke-width: 2; stroke-dasharray: 0 9; }
/* the orange ink; the script moves stroke-dashoffset from 1 (none) to 0 (all) */
.process-line-ink { stroke: var(--orange); stroke-width: 3; stroke-dasharray: 1 2; stroke-dashoffset: 1.01; }
/* a short dashed end after the last dot (computers): it fades in once the line is drawn */
.process-line-tail {
  stroke: url(#processTailFade);
  stroke-width: 3;
  stroke-dasharray: 9 8;
  opacity: 0;
  transition: opacity 0.6s ease-out;
}
.process-track.is-done .process-line-tail { opacity: 1; }

.process-steps {
  display: grid;
  gap: 44px;
  list-style: none;
}
.process-step {
  position: relative;
  display: grid;
  grid-template-columns: var(--plate) 1fr;
  column-gap: 16px;
}
/* the dot sits beside the first line of the title */
.process-dot   { grid-area: 1 / 1; margin-top: calc((var(--title-size) * 1.2 - var(--plate)) / 2); }
.process-title { grid-area: 1 / 2; }
.process-text  { grid-area: 2 / 2; }
.process-dot {
  display: grid;
  place-items: center;
  width: var(--plate);
  height: var(--plate);
  border-radius: 32%;
  background: var(--white);
  box-shadow: 0 4px 12px rgb(86 82 78 / 0.13), 0 0 0 1px rgb(86 82 78 / 0.04);
}
.process-dot::after {
  content: '';
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--quiet);
}
/* the big quiet number behind the step */
.process-num {
  position: absolute;
  top: -22px;
  right: 0;
  font-weight: 700;
  font-size: 96px;
  line-height: 1;
  color: var(--quiet);
  pointer-events: none;
}
.process-title {
  font-weight: 700;
  font-size: var(--title-size);
  line-height: 1.2;
  color: var(--text);
}
.process-text {
  max-width: 34em;
  margin-top: 8px;
  font-weight: 500;
  font-size: 17px;
  line-height: 1.45;
}
.process-text strong { font-weight: 700; }
.process-text a {
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--orange);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
@media (hover: hover) {
  .process-text a { transition: color 0.2s ease; }
  .process-text a:hover { color: var(--orange-text-small); }
}

/* Entrance (only when the script runs: it adds .is-ready, then .is-in to each
   step when the pen reaches its dot). Until then the tile is small and flat and
   the rest waits; then the tile springs up with its dot and the number, title
   and text rise one after another. */
.process-track.is-ready .process-step > :not(.process-dot) {
  opacity: 0;
  translate: 0 14px;
  transition: opacity 0.5s ease-out var(--td, 0s),
              translate 0.7s cubic-bezier(0.22, 1, 0.36, 1) var(--td, 0s);
}
.process-track.is-ready .process-title { --td: 0.07s; }
.process-track.is-ready .process-text  { --td: 0.14s; }
.process-track.is-ready .process-step.is-in > :not(.process-dot) { opacity: 1; translate: 0 0; }
.process-track.is-ready .process-dot {
  transition: scale 0.55s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.4s ease-out;
}
.process-track.is-ready .process-dot::after { transition: opacity 0.3s ease-out 0.1s; }
.process-track.is-ready .process-step:not(.is-in) .process-dot {
  scale: 0.55;
  box-shadow: inset 0 0 0 2px var(--chip-line);
}
.process-track.is-ready .process-step:not(.is-in) .process-dot::after { opacity: 0; }

/* Tablets: the same column, a little bigger */
@media (744px <= width < 1024px) and (height >= 740px), (width >= 1024px) and (orientation: portrait) {
  .process { --plate: 34px; --dot: 13px; --title-size: 25px; }
  .process-track { margin-top: 40px; padding-left: 28px; }
  .process-steps { max-width: 660px; gap: 56px; }
  .process-step { column-gap: 22px; }
  .process-num { top: -28px; font-size: 128px; }
  .process-text { font-size: 18px; }
}

/* Desktop (mockup 1440): px ÷ 14.4 = vw.
   The steps climb: each one is set lower by its own share of --rise, so the
   line between the dots goes up in uneven waves, like a hand-drawn one.
   The line starts at the left edge (the steps leave room for it) and dips into
   the first dot. */
@media (width >= 1024px) and (orientation: landscape) {
  .process {
    padding: 4.17vw 0 5.56vw;
    --plate: max(34px, 2.78vw);
    --dot: max(12px, 1.04vw);
    --title-size: max(19px, 1.53vw);
    --rise: 6.94vw; /* 100px */
  }
  .process-inner { padding-inline: 4.10vw; }
  .process-track { margin-top: 4.17vw; padding: 0; }
  .process-steps {
    grid-template-columns: repeat(4, 1fr);
    align-items: start;
    column-gap: 3.33vw;
    padding: 0 1.39vw 0 7.64vw; /* left: room for the start of the line */
  }
  /* 1→2 a small climb, 2→3 the big steep one, 3→4 small again (as in the sketch) */
  .process-step:nth-child(1) { margin-top: calc(var(--rise) * 3); }
  .process-step:nth-child(2) { margin-top: calc(var(--rise) * 2.25); }
  .process-step:nth-child(3) { margin-top: calc(var(--rise) * 0.7); }
  .process-step {
    display: block;
  }
  .process-dot { margin: 0 0 1.39vw; box-shadow: 0 0.42vw 1.11vw rgb(86 82 78 / 0.14), 0 0 0 1px rgb(86 82 78 / 0.04); }
  .process-num { top: -2.78vw; left: 5.9vw; right: auto; font-size: 13.89vw; }
  .process-text { margin-top: 0.69vw; font-size: max(16px, 1.18vw); }
  .process-line-ink { filter: url(#processShadow); }
}

/* ── GET A QUOTE (price calculator) ── */
/* Phone and tablet: the questions and the estimate one under another */
.quote {
  padding: 48px 0 56px;
}
.quote-inner {
  padding-inline: var(--gutter);
}
.calc-card {
  display: grid;
  gap: 32px;
  margin-top: 24px;
  padding: 28px 20px 32px;
  border-radius: 28px;
  background: var(--cream); /* the same cream as Contact: the two read as one conversation */
}

.calc-progress {
  height: 4px;
  margin-bottom: 24px;
  border-radius: 2px;
  background: rgb(246 149 64 / 0.2);
  container-type: inline-size; /* lets the fill's gradient span the whole bar (100cqw) */
}
/* Yellow to orange. The gradient is as long as the whole bar, not just the filled
   part, so the bar "warms up" step by step: mostly yellow at the start, orange
   when the estimate is ready. */
.calc-progress-fill {
  width: 0;
  height: 100%;
  border-radius: 2px;
  background: linear-gradient(to right, var(--yellow), var(--orange)) left / 100cqw 100% no-repeat;
  transition: width 0.4s cubic-bezier(0.65, 0, 0.35, 1);
}
/* STEP 1 OF 4: small orange capitals, like the labels in the project windows */
.calc-step {
  margin-bottom: 8px;
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--orange-text-small);
}
.calc-fieldset {
  border: 0;
  min-width: 0;
}
.calc-question {
  margin-bottom: 20px;
  font-weight: 700;
  font-size: 22px;
  line-height: 1.2;
  color: var(--text);
}
.calc-question:focus { outline: none; } /* focused by script only, to read it out */

/* Answers: real radio buttons / checkboxes, styled as rounded cards.
   The input itself is invisible but covers the whole card, so a click anywhere
   picks it, and the keyboard still works (focus ring on the card). */
.calc-options {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.calc-option {
  position: relative;
  display: flex;
  align-items: flex-start;
  padding: 13px 18px;
  border: 1px solid var(--chip-line);
  border-radius: 22px;
  background: var(--white);
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.calc-option input {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  margin: 0;
  border-radius: inherit;
  opacity: 0;
  cursor: pointer;
}
/* the chosen answer: yellow with a dark outline, exactly like the Contact pills */
.calc-option:has(input:checked) {
  border-color: var(--text);
  background: rgb(245 206 82 / 0.45);
}
/* Questions with short answers (design, extras, when): pills in a row,
   the same as "New website" or "Under £300" in the Contact form */
.calc-options:not(:has(.calc-option-desc)) {
  flex-direction: row;
  flex-wrap: wrap;
}
.calc-options:not(:has(.calc-option-desc)) .calc-option {
  padding: 10px 18px;
  border-radius: 999px;
}
.calc-option:has(input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}
.calc-option-title {
  display: block;
  font-weight: 600;
  font-size: 16px;
  line-height: 1.25;
  color: var(--text);
}
.calc-option-desc {
  display: block;
  margin-top: 3px;
  font-weight: 500;
  font-size: 13px;
  line-height: 1.35;
  color: var(--muted);
}
@media (hover: hover) {
  .calc-option:hover { border-color: var(--text); }
}

.calc-other {
  margin-top: 14px;
  transition: opacity 0.35s ease, translate 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
/* when it appears (it was display: none), it starts from here: fades and slides in */
@starting-style {
  .calc-other { opacity: 0; translate: 0 -8px; }
}
.calc-other-label {
  display: block;
  margin-bottom: 8px;
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
}
/* the "Something else" box looks like a tile; it gets the chosen tile's
   orange edge while you type in it */
.calc-textarea {
  display: block;
  width: 100%;
  height: 96px;
  padding: 14px 18px;
  border: 1.5px solid transparent;
  border-radius: 20px;
  background: var(--white);
  box-shadow: 0 2px 10px rgb(86 82 78 / 0.06);
  transition: border-color 0.2s ease, box-shadow 0.25s ease;
  font: inherit;
  font-size: 16px;
  color: var(--text);
  resize: vertical;
}
.calc-textarea:focus { outline: none; border-color: var(--orange); box-shadow: 0 6px 18px rgb(246 149 64 / 0.18); }
.calc-textarea::placeholder { color: var(--muted); }

.calc-nav {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 24px;
}
.calc-next {
  flex-shrink: 0;
  height: 48px;
  margin-left: auto; /* stays on the right, even when Back is hidden */
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  background: var(--orange);
  font: inherit;
  font-weight: 700;
  font-size: 16px;
  color: var(--on-orange); /* dark text: 5:1 on orange (white was 2.3:1) */
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.calc-next:disabled { cursor: not-allowed; }
.calc-back {
  display: block;
  margin: 0 0 0 -12px; /* the text lines up with the answers' edge */
  padding: 6px 12px;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  color: var(--muted);
  cursor: pointer;
}
.calc-next:focus-visible, .calc-back:focus-visible { border-radius: 999px; }
@media (hover: hover) {
  .calc-back:hover { color: var(--text); }
}

/* Phones and tablets: a line between the questions and the estimate,
   the same fading line as under the section titles */
.calc-side {
  padding-top: 28px;
  background: linear-gradient(to right, transparent, var(--line) 10%, var(--line) 90%, transparent)
              top / 100% 1px no-repeat;
}
/* display: block/flex above would otherwise beat the hidden attribute */
.calc-result[hidden], .calc-back[hidden] { display: none; }

/* ── Estimate (right side) ── */
/* Sizes are in em: on desktop the whole block scales with one font-size,
   so it grows together with the questions on the left */
.calc-result { font-size: 16px; }
.result-label {
  margin-bottom: 0.3em;
  font-weight: 700;
  font-size: 0.8em;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--orange-text-small); /* the same orange labels as STEP 1 OF 4 */
}
.result-price mark { --marker-from: 58%; } /* the price gets the yellow highlighter */
.result-price {
  margin-bottom: 0.6em;
  font-weight: 700;
  font-size: clamp(1.5em, 7.5vw, 2em); /* a bit smaller on narrow phones, so the range stays on one line */
  white-space: nowrap;
  line-height: 1.15;
  color: var(--text);
}

/* Timeline: a light yellow card with a soft clock */
.result-time {
  display: flex;
  align-items: center;
  gap: 0.9em;
  margin-bottom: 1.4em;
  padding: 0.9em 1.1em;
  border-radius: 1.2em;
  background: var(--white); /* white boxes stand out on the cream card */
}
.result-time svg {
  flex-shrink: 0;
  width: 2.4em;
  height: 2.4em;
}
.result-time .result-label { margin-bottom: 0.15em; }
.result-time-value {
  font-weight: 700;
  font-size: 1.2em;
  color: var(--text);
}

/* What's included: soft round ticks (like the arrows on the site);
   two columns when there's room */
.result-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 16em), 1fr));
  gap: 0.6em 1.4em;
  margin: 0.5em 0 1.4em;
  list-style: none;
}
.result-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.65em;
  font-weight: 600;
  font-size: 0.95em;
  line-height: 1.4;
  color: var(--text);
}
.result-list li::before {
  content: '';
  flex-shrink: 0;
  width: 1.4em;
  height: 1.4em;
  border-radius: 50%;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F69540' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5l4 4 8-9'/%3E%3C/svg%3E") center / 72% no-repeat, rgb(245 206 82 / 0.3);
}

.result-tip {
  margin-bottom: 1.4em;
  padding: 0.8em 1em;
  border-left: 3px solid var(--orange);
  border-radius: 0 0.8em 0.8em 0;
  background: var(--white);
  font-weight: 500;
  font-size: 0.9em;
  line-height: 1.5;
  color: var(--text);
}
.result-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75em;
}
.result-talk,
.result-restart {
  height: 3.25em; /* same height as the "Show my estimate" button */
  font-size: 1em;
}
.result-talk { flex: 2 1 11em; }
.result-restart {
  flex: 1 1 7em;
  /* the light button, the same everywhere: white, thin beige outline, dark text
     (Start over, Change, ✕, Send another message) */
  border: 1px solid var(--chip-line);
  border-radius: 999px;
  background: var(--white);
  font-family: inherit;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.result-restart:focus-visible { border-radius: 999px; }
@media (hover: hover) {
  .result-restart:hover { border-color: var(--text); color: var(--text); }
}

.quote-note {
  margin-top: 16px;
  font-weight: 500;
  font-size: 15px;
  text-align: center;
  color: var(--muted);
}

/* ── Get a Quote: motion ──
   Entrance, the first time it's in view (revealOnView adds .is-in and --d): the
   card rises, its answers follow one by one, then the note under it fades in and
   its marker is drawn.
   Each new step: the question and the answers slide in from the side you're going
   (from the right on Continue, from the left on Back; the script sets --from-x).
   The estimate: its lines come in one after another and the price gets its marker. */
.calc-card {
  opacity: 0;
  translate: 0 32px;
  scale: 0.98;
  transition: opacity 0.6s ease-out var(--d, 0s),
              translate 0.9s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s),
              scale 0.9s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0s);
}
.calc-card.is-in { opacity: 1; translate: 0 0; scale: 1; }
.calc-card:not(.is-in) .calc-question,
.calc-card:not(.is-in) .calc-option { opacity: 0; }
.calc-card.is-in .calc-question.is-new,
.calc-card.is-in .calc-option {
  animation: calc-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--enter, 0s) + var(--i, 0) * 45ms);
}
@keyframes calc-in {
  from { opacity: 0; translate: var(--from-x, 0px) var(--from-y, 12px); }
}
.calc-result:not([hidden]) > * { animation: calc-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; }
.calc-result > :nth-child(2) { animation-delay: 0.06s; }
.calc-result > :nth-child(3) { animation-delay: 0.14s; }
.calc-result > :nth-child(4) { animation-delay: 0.2s; }
.calc-result > :nth-child(5) { animation: none; }
.calc-result:not([hidden]) .result-list li {
  animation: calc-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(0.24s + var(--i, 0) * 50ms);
}
.calc-result > :nth-child(6) { animation-delay: 0.45s; }
.calc-result > :nth-child(7) { animation-delay: 0.52s; }
/* the price's marker is drawn from left to right */
.calc-result:not([hidden]) .result-price mark {
  background-size: 0% 100%;
  background-repeat: no-repeat;
  animation: marker-draw 0.7s cubic-bezier(0.65, 0, 0.35, 1) 0.35s forwards;
}
@keyframes marker-draw { to { background-size: 100% 100%; } }
.quote-note {
  opacity: 0;
  translate: 0 10px;
  transition: opacity 0.6s ease-out calc(var(--d, 0s) + 0.4s),
              translate 0.8s cubic-bezier(0.22, 1, 0.36, 1) calc(var(--d, 0s) + 0.4s);
}
.quote-note.is-in { opacity: 1; translate: 0 0; }
.quote-note mark {
  background-size: 0% 100%;
  background-repeat: no-repeat;
  transition: background-size 0.8s cubic-bezier(0.65, 0, 0.35, 1) calc(var(--d, 0s) + 0.8s);
}
.quote-note.is-in mark { background-size: 100% 100%; }

/* ── Get a Quote: answers, Continue and the estimate so far ── */
.calc-summary[hidden], .summary-row[hidden] { display: none; }
/* Continue: a calm button that's always in the same place. Until there's an
   answer it's pale; once you pick one it lights up. */
.calc-next {
  height: 44px;
  padding: 0 22px;
  font-weight: 600;
  font-size: 15px;
  transition: opacity 0.25s ease, background-color 0.25s ease, color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.calc-card .calc-next:disabled {
  background: var(--orange);
  color: var(--on-orange);
  opacity: 0.35;
}
.calc-option-icon svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5; /* Heroicons' own line */
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The estimate so far: like a receipt. Same label and price as the full
   estimate, so one turns into the other in the same place. Sizes in em. */
.calc-summary { font-size: 16px; }
.summary-price {
  margin-bottom: 0.4em;
  font-weight: 700;
  font-size: clamp(1.5em, 7.5vw, 2em);
  line-height: 1.15;
  white-space: nowrap;
  color: var(--text);
}
.summary-price.is-empty { color: #CDBFAE; }
.summary-time {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-weight: 600;
  font-size: 0.95em;
  color: var(--muted);
}
.summary-time svg { flex-shrink: 0; width: 1.2em; height: 1.2em; color: var(--orange); }
.summary-list {
  margin-top: 1.5em;
  border-top: 1.5px dashed var(--chip-line);
}
.summary-row {
  display: grid;
  grid-template-columns: 5.2em 1fr;
  gap: 1em;
  padding: 0.85em 0;
  border-bottom: 1.5px dashed var(--chip-line);
}
.summary-row dt {
  padding-top: 0.08em;
  font-weight: 600;
  font-size: 0.85em;
  color: var(--muted);
}
.summary-row dd {
  font-weight: 600;
  font-size: 0.95em;
  line-height: 1.4;
  color: #CDBFAE; /* not answered yet: a quiet dash */
}
.summary-row.is-set dd { color: var(--text); }
.summary-row.is-new dd { animation: calc-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both; }

/* ── Tiles ── white tiles on the cream, two in a row; the first question
   has little icons. The chosen one gets an orange edge and a tick. */
.calc-card[data-look="tiles"] .calc-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.calc-card[data-look="tiles"] .calc-option {
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 18px 17px;
  border: 1.5px solid transparent;
  border-radius: 20px;
  background: var(--white);
  box-shadow: 0 2px 10px rgb(86 82 78 / 0.06);
  transition: border-color 0.2s ease, box-shadow 0.25s ease, translate 0.25s ease;
}
.calc-card[data-look="tiles"] .calc-option-icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 14px;
  background: var(--cream);
  color: var(--orange-text);
}
/* an odd one out at the end ("Not sure yet") takes the whole row */
.calc-card[data-look="tiles"] .calc-option:last-child:nth-child(odd) {
  grid-column: 1 / -1;
  flex-direction: row;
  align-items: center;
}
.calc-card[data-look="tiles"] .calc-option:has(input:checked) {
  border-color: var(--orange);
  background: var(--white);
  box-shadow: 0 6px 18px rgb(246 149 64 / 0.18);
}
/* the tick in the corner */
.calc-card[data-look="tiles"] .calc-option::after {
  content: '';
  position: absolute;
  top: 12px;
  right: 12px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--orange) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%233E3A37' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8.5l2.6 2.5L12 5.5'/%3E%3C/svg%3E") center / 14px no-repeat;
  scale: 0;
  transition: scale 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
  pointer-events: none;
}
.calc-card[data-look="tiles"] .calc-option:has(input:checked)::after { scale: 1; }
.calc-card[data-look="tiles"] .calc-option-title { padding-right: 18px; } /* room for the tick */
@media (hover: hover) {
  .calc-card[data-look="tiles"] .calc-option:hover {
    border-color: transparent;
    translate: 0 -2px;
    box-shadow: 0 8px 22px rgb(86 82 78 / 0.10);
  }
  .calc-card[data-look="tiles"] .calc-option:has(input:checked):hover { border-color: var(--orange); }
}
/* phones: answers with a description go one per row (two would be too narrow);
   in the first question the icon sits on the left */
@media (width < 744px) {
  .calc-card[data-look="tiles"] .calc-options:has(.calc-option-desc) { grid-template-columns: 1fr; }
  .calc-card[data-look="tiles"] .calc-options:has(.calc-option-desc) .calc-option { padding-block: 14px; }
  .calc-card[data-look="tiles"] .calc-options[data-step="type"] .calc-option { flex-direction: row; align-items: center; gap: 14px; }
}

/* Desktop (mockup 1920): questions on the left, estimate on the right.
   Text never gets smaller than on phones (max(...)). */
@media (width >= 1024px) and (orientation: landscape) {
  .quote { padding: 3.12vw 0 4.17vw; }
  .quote-inner { padding-inline: 4.10vw; }
  .calc-card {
    grid-template-columns: 8fr 7fr; /* 640 : 560 in the mockup */
    align-items: start;
    gap: 3.12vw;
    margin: 2.92vw 3.59vw 0;
    padding: 3.12vw 4.17vw 3.65vw;
    border-radius: 3.12vw;
  }
  .calc-question { font-size: max(22px, 1.46vw); }
  .calc-option-title { font-size: max(16px, 0.94vw); }
  .calc-option-desc { font-size: max(13px, 0.73vw); }
  /* same size as the Send button in Contact */
  .calc-next { height: max(48px, 3.33vw); padding: 0 max(26px, 1.81vw); font-size: max(16px, 1.11vw); }
  .calc-side { padding-top: 0; background: none; } /* side by side: no line needed */
  .calc-result { font-size: max(16px, 0.94vw); } /* everything on the right follows this */
  .quote-note { margin-top: 1.25vw; font-size: max(15px, 0.89vw); }
}


/* desktop sizes for the parts above */
@media (width >= 1024px) and (orientation: landscape) {
  .calc-next { height: max(44px, 3.06vw); padding: 0 max(22px, 1.53vw); font-size: max(15px, 1.04vw); }
  .calc-summary { font-size: max(16px, 0.94vw); }
  .calc-card[data-look="tiles"] .calc-options { gap: max(12px, 0.83vw); }
  .calc-card[data-look="tiles"] .calc-option { padding: max(16px, 1.11vw) max(18px, 1.25vw); gap: max(12px, 0.83vw); border-radius: max(20px, 1.39vw); }
  .calc-card[data-look="tiles"] .calc-option-icon { width: max(42px, 2.92vw); height: max(42px, 2.92vw); border-radius: max(14px, 0.97vw); }
  .calc-card[data-look="tiles"] .calc-option-icon svg { width: max(22px, 1.53vw); height: max(22px, 1.53vw); }
  .calc-card[data-look="tiles"] .calc-option::after {
    top: max(12px, 0.83vw); right: max(12px, 0.83vw);
    width: max(22px, 1.53vw); height: max(22px, 1.53vw); background-size: max(14px, 0.97vw);
  }
}

/* ── CONTACT ── */
.contact-group {
  position: relative;
  transform: translateY(80px);
  transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1);
}
.contact-group.risen { transform: translateY(0); }

.contact-backdrop {
  position: relative;
  z-index: 1;
  height: var(--backdrop-h);
  background: var(--orange);
  border-radius: var(--radius) var(--radius) 0 0;
  transform: translateY(100%);
  transition: transform 1s cubic-bezier(0.16, 1, 0.3, 1);
}
.contact-backdrop.visible { transform: translateY(0); }

.contact {
  position: relative;
  z-index: 2;
  min-height: clamp(600px, 53.9vw, 1036px);
  margin-top: calc(-1 * (var(--backdrop-h) - 15px));
  /* the footer bar overlaps the bottom of this block */
  padding: 40px 0 calc(var(--footer-h) + 48px);
  background: var(--cream);
  border-radius: var(--radius) var(--radius) 0 0;
}
.contact-inner { padding-inline: var(--gutter); }
.contact-body {
  display: grid;
  gap: 32px;
  margin-top: 28px;
}

/* Left: the big line, the text and (desktop only) the drawn arrow */
.contact-intro {
  position: relative;
  display: flex;
  flex-direction: column;
}
.contact-heading {
  font-weight: 800;
  font-size: clamp(34px, 9vw, 44px);
  line-height: 1.15;
  color: var(--orange-text);
}
/* the short intro: under the heading on phones, top of the left column on desktop */
.contact-text {
  max-width: 34em;
  margin-top: 16px;
  font-weight: 500;
  font-size: 16px;
  line-height: 1.45;
  color: var(--text);
}
.contact-art { display: none; } /* desktop only: the arrow points at the form beside it */

/* Right: the form — light and airy: underlined fields, thin pills */
.contact-form {
  display: grid;
  gap: 26px;
}
.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 26px 24px;
}
.field { min-width: 0; border: 0; }
.legend-hint { font-weight: 500; color: var(--muted); }
/* Under the budget pills: a calm note, not an error. It opens smoothly: the
   row grows from 0 to its full height (grid 0fr → 1fr) while the text fades
   in, so the rest of the form slides down instead of jumping. */
/* closing: the words fade first, then the space closes */
.budget-hint-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.12s;
}
.budget-hint-inner { min-height: 0; overflow: hidden; }
.budget-hint {
  margin-top: 10px;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
  opacity: 0;
  translate: 0 -6px;
  transition: opacity 0.2s ease, translate 0.3s ease;
}
/* opening: the space opens first, then the words fade in */
.budget-hint-wrap.is-shown {
  grid-template-rows: 1fr;
  transition-delay: 0s;
}
.budget-hint-wrap.is-shown .budget-hint {
  opacity: 1;
  translate: 0 0;
  transition: opacity 0.4s ease 0.2s, translate 0.55s cubic-bezier(0.4, 0, 0.2, 1) 0.15s;
}
.field label,
.field legend {
  display: block;
  margin-bottom: 4px;
  padding: 0;
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}
.req { color: var(--focus); } /* the * of required fields */
.optional { font-weight: 500; color: var(--muted); }
/* fields: just a line underneath, no box */
.field input,
.field textarea {
  display: block;
  width: 100%;
  padding: 10px 0 11px;
  border: 0;
  border-bottom: 1px solid var(--field-line);
  border-radius: 0;
  background: transparent;
  font: inherit;
  font-weight: 500;
  font-size: 16px; /* 16px+ stops iPhones zooming in on tap */
  color: var(--text);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.field textarea {
  height: 96px;
  line-height: 1.45;
  resize: none;
}
.field input::placeholder,
.field textarea::placeholder { color: #A89F95; }
/* focus: the line turns orange and a little thicker */
.field input:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--orange);
  box-shadow: 0 1px 0 var(--orange);
}
.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-bottom-color: #B42318;
  box-shadow: 0 1px 0 #B42318;
}
.field { position: relative; }
/* Errors float just under the line, in the gap before the next field,
   so nothing on the page moves when they appear */
.field-error {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  font-weight: 600;
  font-size: 13px;
  color: #B42318; /* red that's readable on cream */
}
.field-error:empty { display: none; }

/* Answer pills (real checkboxes / radio buttons inside). They look like the
   tiles in Get a Quote: white with a soft shadow; the chosen one gets the orange
   edge, a soft orange glow and the orange tick in the corner. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 8px;
  margin-top: 8px;
}
.chip { position: relative; }
.chip input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}
.chip span {
  position: relative;
  display: block;
  padding: 7px 15px;
  border: 1.5px solid transparent;
  border-radius: 999px;
  background: var(--white);
  box-shadow: 0 2px 8px rgb(86 82 78 / 0.07);
  font-weight: 500;
  font-size: 14px;
  color: var(--text);
  white-space: nowrap;
  transition: border-color 0.2s ease, box-shadow 0.25s ease;
}
/* the tick: sits on the corner, pops in when chosen (doesn't move the other pills).
   Sized in em, so on wide screens it grows together with the pill. */
.chip span::after {
  content: '';
  position: absolute;
  top: -0.36em;
  right: -0.24em;
  width: 1.1em;
  height: 1.1em;
  border-radius: 50%;
  background: var(--orange) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%233E3A37' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8.5l2.6 2.5L12 5.5'/%3E%3C/svg%3E") center / 0.74em no-repeat;
  scale: 0;
  transition: scale 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
  pointer-events: none;
}
.chip input:checked + span {
  border-color: var(--orange);
  box-shadow: 0 4px 14px rgb(246 149 64 / 0.18);
}
.chip input:checked + span::after { scale: 1; }
.chip input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 3px; }
@media (hover: hover) {
  .chip:hover span { box-shadow: 0 4px 12px rgb(86 82 78 / 0.12); }
  .chip:hover input:checked + span { box-shadow: 0 4px 14px rgb(246 149 64 / 0.24); }
}
/* Touch screens: at least 44px tall, so they're easy to tap with a finger */
@media (pointer: coarse) {
  .chip span { display: flex; align-items: center; min-height: 44px; }
}

/* The estimate from Get a Quote, attached to the message */
/* "Your estimate is attached": the same sizes as the fields around it (title like
   a label, summary like the text you type), so it reads as part of the form.
   On a narrow phone the buttons move under the text instead of squeezing it. */
/* looks like a chosen answer in Get a Quote: white, an orange edge,
   a soft orange glow and the same orange tick */
.quote-attached {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  padding: 14px 14px 14px 16px;
  border: 1.5px solid var(--orange);
  border-radius: 20px;
  background: var(--white);
  box-shadow: 0 6px 18px rgb(246 149 64 / 0.18);
}
.quote-attached[hidden] { display: none; }
.quote-attached-icon {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--orange) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%233E3A37' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8.5l2.6 2.5L12 5.5'/%3E%3C/svg%3E") center / 16px no-repeat;
}
.quote-attached-text { flex: 1 1 220px; min-width: 0; }
.quote-attached-title {
  font-weight: 600;
  font-size: 14px;
  color: var(--muted);
}
/* the summary wraps instead of being cut off, so the price is never hidden */
.quote-attached-sum {
  margin-top: 2px;
  font-weight: 500;
  font-size: 16px;
  line-height: 1.35;
  color: var(--text);
}
.quote-attached-actions {
  display: flex;
  gap: 8px;
  margin-left: auto;
}
.quote-attached-redo,
.quote-attached-remove {
  flex-shrink: 0;
  height: 40px;
  padding: 0 16px;
  border: 1px solid var(--chip-line);
  border-radius: 999px;
  background: var(--white);
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  line-height: 38px;
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}
.quote-attached-remove { width: 40px; padding: 0; line-height: 1; }
/* touch screens: 44px, easy to hit with a finger */
@media (pointer: coarse) {
  .quote-attached-redo, .quote-attached-remove { height: 44px; line-height: 42px; }
  .quote-attached-remove { width: 44px; line-height: 1; }
}
.quote-attached-redo:focus-visible,
.quote-attached-remove:focus-visible { border-radius: 999px; }
@media (hover: hover) {
  .quote-attached-redo:hover,
  .quote-attached-remove:hover { border-color: var(--text); }
}

/* Bottom row: a thin line, the privacy note on the left, the button on the right */
.form-submit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 4px; /* the message's underline above works as the divider */
}
.contact-privacy {
  font-size: 13px;
  color: var(--muted);
}
.contact-privacy a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.contact-send {
  flex-shrink: 0;
  height: 48px;
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  background: var(--orange);
  font: inherit;
  font-weight: 700;
  font-size: 16px;
  color: var(--on-orange); /* dark text: 5:1 on orange (white was 2.3:1) */
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.contact-send:focus-visible { border-radius: 999px; }
/* while sending: the arrow turns into a spinner */
.contact-send.is-sending { cursor: wait; }
.contact-send.is-sending::after {
  -webkit-mask: none;
          mask: none;
  width: 0.85em;
  height: 0.85em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  background: none;
  vertical-align: -0.12em;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(1turn); } }
/* phones: the button full width (easier to tap), the note under it */
@media (width < 560px) {
  .form-submit {
    flex-direction: column-reverse;
    align-items: stretch;
  }
  .contact-privacy { text-align: center; }
}
/* ── After sending: a card in place of the form ── */
/* The form's column keeps its height, and the card sits in the middle of it,
   so nothing else on the page moves */
.contact-form-wrap.is-result {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.contact-form[hidden], .contact-result[hidden] { display: none; }
.contact-result {
  overflow: hidden;
  border-radius: 28px;
  background: var(--white);
  box-shadow: 0 18px 50px rgb(86 82 78 / 0.12);
  text-align: center;
  animation: result-in 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.contact-result:focus { outline: none; }
@keyframes result-in {
  from { opacity: 0; transform: translateY(16px) scale(0.97); }
}
/* top: a coloured area with a soft rounded bottom and the drawing */
.cr-top {
  padding: 26px 24px 14px;
  border-radius: 0 0 50% 50% / 0 0 26px 26px;
  background: rgb(245 206 82 / 0.25);
}
.contact-result.is-error .cr-top { background: #FBE3DA; }
.cr-art {
  display: block;
  width: min(220px, 70%);
  height: auto;
  margin: 0 auto;
}
.cr-art-err { display: none; }
.contact-result.is-error .cr-art-ok { display: none; }
.contact-result.is-error .cr-art-err { display: block; }
/* success: the plane flies in, then keeps gently flying (bobs up and down),
   and the dashes of its trail keep drifting back, so it looks like it's moving */
.cr-plane {
  transform-box: fill-box;
  transform-origin: center;
  animation: plane-in 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.1s both,
             plane-float 2.6s ease-in-out 1s infinite alternate;
}
.cr-trail {
  stroke-dashoffset: 0;
  animation: trail-in 1s ease-out 0.15s both,
             trail-flow 1s linear 1.15s infinite;
}
@keyframes plane-in {
  from { opacity: 0; transform: translate(-60px, 40px) rotate(-10deg); }
}
@keyframes plane-float {
  to { transform: translate(3px, -6px) rotate(-3deg); }
}
@keyframes trail-flow {
  to { stroke-dashoffset: 16; } /* one dash + one gap (7 + 9) */
}
@keyframes trail-in {
  from { opacity: 0; clip-path: inset(0 100% 0 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}
/* error: the plane drops and sticks in the ground, with a little bounce */
.cr-plane-down {
  transform-origin: 108px 108px;
  animation: plane-drop 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both;
}
.cr-bump { animation: bump-in 0.3s ease-out 0.55s both; }
@keyframes plane-drop {
  from { opacity: 0; transform: translateY(-50px) rotate(-14deg); }
}
@keyframes bump-in { from { opacity: 0; } }

.cr-body { padding: 18px 28px 30px; }
.cr-title {
  margin-bottom: 8px;
  font-weight: 700;
  font-size: 26px;
  color: var(--text);
}
.cr-text {
  max-width: 26em;
  margin: 0 auto;
  font-weight: 500;
  font-size: 16px;
  line-height: 1.5;
  color: var(--text);
}
.cr-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px 18px;
  margin-top: 22px;
}
.cr-btn {
  height: 46px;
  padding: 0 24px;
  border: 0;
  border-radius: 999px;
  background: var(--orange);
  font: inherit;
  font-weight: 700;
  font-size: 15px;
  color: var(--on-orange); /* dark text: 5:1 on orange (white was 2.3:1) */
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.cr-btn-outline {
  border: 1px solid var(--chip-line);
  background: var(--white);
  color: var(--text);
}
.cr-btn:focus-visible { border-radius: 999px; }
.cr-link {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}
.cr-text strong { font-weight: 700; } /* their email: easy to check for a typo */
/* "Wrong email? Fix it": a button that looks like a quiet link */
button.cr-link {
  padding: 8px 4px;
  border: 0;
  background: none;
  font-family: inherit;
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: var(--chip-line);
  text-underline-offset: 3px;
  cursor: pointer;
}
@media (pointer: coarse) { button.cr-link { min-height: 44px; } }
@media (hover: hover) { button.cr-link:hover { color: var(--text); text-decoration-color: currentColor; } }
@media (hover: hover) {
  .cr-btn-outline:hover { border-color: var(--text); color: var(--text); }
}
@media (prefers-reduced-motion: reduce) {
  .contact-result, .cr-plane, .cr-trail, .cr-plane-down, .cr-bump,
  .contact-send.is-sending::after { animation: none; }
}


/* Desktop (mockup 1440): text and arrow on the left, form on the right.
   The arrow draws itself the first time the section comes into view. */
@media (width >= 1024px) and (orientation: landscape) {
  .contact {
    padding-top: 3.19vw;
    padding-bottom: calc(var(--footer-h) + 7vw); /* the arrow's loop must stay above the footer */
  }
  .contact-inner { padding-inline: 4.10vw; }
  .contact-body {
    grid-template-columns: 1fr 36.53vw;
    align-items: end; /* the drawing sits at the bottom, level with the Send button */
    gap: 0;
    margin-top: 2.08vw;
    padding-right: 2.99vw;
  }
  /* The arrow's tip is 19.5% of the drawing's height above its bottom (6.32vw).
     This negative margin lets the drawing hang below the form's bottom just
     enough for the tip to point at the middle of the Send button,
     whatever the height of the form. */
  .contact-intro {
    align-self: stretch; /* full height: text at the top, drawing at the bottom */
    padding-left: 3.89vw;
    margin-bottom: calc(max(24px, 1.665vw) + 6px - 6.32vw);
  }
  /* the text stays for screen readers and Google, but the drawing shows instead */
  .contact-heading {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .contact-art {
    display: block;
    width: 38.4vw;
    height: auto;
    margin-top: auto; /* pushed to the bottom of the column */
    overflow: visible;
  }
  .contact-text {
    max-width: 26vw;
    margin: 0 0 max(24px, 2.08vw);
    font-size: max(16px, 1.11vw);
  }
  /* Drawing: the line is ink drawn by the script at the bottom (contactInk), thicker
     where the pen is slow (the start, the loop) and thinner where it is fast. It is
     two pieces split between the two passes through the loop, so the second pass
     goes over the first, with a soft shadow underneath. The head is drawn as two
     quick strokes from the tip; they poke Send message, and hovering the button
     later makes the head poke it again. */
  /* A pale glint rides just behind the pen; after the head, one shine runs down the
     whole arrow into the button. The shine is two pieces split between the two passes
     through the loop: the first is under the second ink piece, the second over it,
     so the shine also goes under, then over. */
  .contact-arrow-glint { opacity: 0; }
  .contact-arrow-glint--pen { stroke-dasharray: 0.0625 2; stroke-dashoffset: 0.0725; }
  .contact-art.is-drawn .contact-arrow-glint--pen {
    animation: contact-glint-pen 2.1s cubic-bezier(0.45, 0, 0.3, 1) 0.3s both, glint-pen-fade 2.1s linear 0.3s both;
    animation-timing-function: linear(0.0099 0.00%, 0.0142 1.25%, 0.0188 2.50%, 0.0237 3.75%, 0.0289 5.00%, 0.0347 6.25%, 0.0409 7.50%, 0.0478 8.75%, 0.0553 10.00%, 0.0633 11.25%, 0.0719 12.50%, 0.0809 13.75%, 0.0902 15.00%, 0.0999 16.25%, 0.1099 17.50%, 0.1202 18.75%, 0.1309 20.00%, 0.1418 21.25%, 0.1531 22.50%, 0.1647 23.75%, 0.1767 25.00%, 0.1890 26.25%, 0.2016 27.50%, 0.2146 28.75%, 0.2280 30.00%, 0.2417 31.25%, 0.2558 32.50%, 0.2702 33.75%, 0.2850 35.00%, 0.3002 36.25%, 0.3157 37.50%, 0.3315 38.75%, 0.3476 40.00%, 0.3639 41.25%, 0.3804 42.50%, 0.3971 43.75%, 0.4137 45.00%, 0.4303 46.25%, 0.4469 47.50%, 0.4633 48.75%, 0.4796 50.00%, 0.4957 51.25%, 0.5111 52.50%, 0.5252 53.75%, 0.5376 55.00%, 0.5482 56.25%, 0.5574 57.50%, 0.5658 58.75%, 0.5736 60.00%, 0.5812 61.25%, 0.5886 62.50%, 0.5961 63.75%, 0.6038 65.00%, 0.6116 66.25%, 0.6197 67.50%, 0.6281 68.75%, 0.6371 70.00%, 0.6470 71.25%, 0.6580 72.50%, 0.6705 73.75%, 0.6846 75.00%, 0.6998 76.25%, 0.7155 77.50%, 0.7313 78.75%, 0.7470 80.00%, 0.7627 81.25%, 0.7784 82.50%, 0.7940 83.75%, 0.8096 85.00%, 0.8252 86.25%, 0.8408 87.50%, 0.8565 88.75%, 0.8721 90.00%, 0.8879 91.25%, 0.9037 92.50%, 0.9195 93.75%, 0.9355 95.00%, 0.9515 96.25%, 0.9676 97.50%, 0.9837 98.75%, 1.0000 100.00%), linear;
  }
  .contact-arrow-glint--a,
  .contact-arrow-glint--b { stroke-dasharray: 113.67 2220; }
  .contact-arrow-glint--a { stroke-dashoffset: 113.67; }
  .contact-arrow-glint--b { stroke-dashoffset: 712.12; }
  .contact-art.is-drawn .contact-arrow-glint--a { animation: contact-shine-a 0.75s cubic-bezier(0.65, 0, 0.35, 1) 3.57s both, glint-shine-fade 0.75s linear 3.57s both; }
  .contact-art.is-drawn .contact-arrow-glint--b { animation: contact-shine-b 0.75s cubic-bezier(0.65, 0, 0.35, 1) 3.57s both, glint-shine-fade 0.75s linear 3.57s both; }

  .contact-form { gap: max(22px, 1.6vw); }
  .form-row { gap: max(22px, 1.6vw) max(24px, 1.67vw); }
  .field label, .field legend { font-size: max(14px, 0.97vw); }
  .field input,
  .field textarea { font-size: max(16px, 1.11vw); padding: max(9px, 0.63vw) 0 max(10px, 0.69vw); }
  .field textarea { height: max(92px, 6.39vw); }
  .chip span { font-size: max(14px, 0.97vw); padding: max(7px, 0.49vw) max(13px, 0.9vw); }
  .form-submit { padding-top: max(4px, 0.28vw); }
  .contact-send { height: max(48px, 3.33vw); padding: 0 max(26px, 1.81vw); font-size: max(16px, 1.11vw); }
  .contact-privacy { font-size: max(13px, 0.9vw); }
  .quote-attached { border-radius: max(20px, 1.39vw); }
  .budget-hint { font-size: max(14px, 0.9vw); }
  .quote-attached-title { font-size: max(14px, 0.97vw); }
  .quote-attached-sum { font-size: max(16px, 1.11vw); }
  .quote-attached-redo { font-size: max(14px, 0.97vw); }
  .cr-title { font-size: max(26px, 1.94vw); }
  .cr-text { font-size: max(16px, 1.11vw); }
}

/* ── FOOTER ── */
/* The orange bar that rises at the very bottom of the page.
   Its height comes from its content; the script measures it (--footer-h),
   so the Contact block always leaves exactly enough room above it. */
.footer {
  position: absolute;
  bottom: 0; left: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--bar-h);
  padding: 26px var(--gutter) calc(22px + env(safe-area-inset-bottom, 0px));
  background: var(--orange);
  border-radius: var(--radius) var(--radius) 0 0;
  color: var(--footer-text);
  transform: translateY(100%);
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.footer.visible,
.footer:focus-within { transform: translateY(0); } /* also when a keyboard user tabs into it */

/* phones: everything centred, one under another */
.footer-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  text-align: center;
}
.footer-brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
/* the logo takes the footer's text colour (fill="currentColor" in the SVG) */
.footer-logo {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
}
/* who and where: two lines next to the logo */
.footer-id { text-align: left; }
.footer-copy {
  font-weight: 600;
  font-size: 15px;
}
.footer-place {
  margin-top: 2px;
  font-weight: 500;
  font-size: 14px;
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 22px;
}
.footer-links a {
  font-weight: 600;
  font-size: 15px;
  color: inherit;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 4px;
  transition: text-decoration-color 0.2s ease;
}
/* "Back to top" is an action, not information, so it's a button of its own:
   the light pill used across the site, with a soft arrow pointing up */
.footer-top {
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 18px 0 20px;
  border-radius: 999px;
  background: var(--white);
  font-weight: 600;
  font-size: 15px;
  color: var(--on-orange);
  text-decoration: none;
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.footer-top::after {
  content: '';
  display: inline-block;
  width: 1.05em;
  height: 1.05em;
  margin-left: 0.35em;
  vertical-align: -0.18em;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 19V6M6.5 11.5L12 6l5.5 5.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 19V6M6.5 11.5L12 6l5.5 5.5'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 0.25s ease;
}
.footer a:focus-visible {
  outline: 2px solid var(--footer-text); /* dark ring: the usual orange one wouldn't show here */
  outline-offset: 3px;
  border-radius: 4px;
}
.footer .footer-top:focus-visible { border-radius: 999px; }
@media (hover: hover) {
  .footer-links a:hover { text-decoration-color: currentColor; }
  /* like the other light buttons: rises a little, a soft shadow appears, the arrow nudges up */
  .footer-top:hover { transform: translateY(-3px); box-shadow: 0 8px 18px rgb(62 58 55 / 0.18); }
  .footer-top:hover::after { transform: translateY(-2px); }
}

/* tablets: two rows, spread out */
@media (width >= 744px) {
  .footer-inner {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 12px 24px;
    text-align: left;
  }
}
/* desktop: one row — logo and © on the left, links in the middle, place and "top" on the right */
@media (width >= 1024px) and (orientation: landscape) {
  .footer {
    padding: max(18px, 1.25vw) 4.10vw calc(max(18px, 1.25vw) + env(safe-area-inset-bottom, 0px));
  }
  .footer-inner { flex-wrap: nowrap; }
  .footer-logo { width: max(44px, 3.47vw); height: max(44px, 3.47vw); }
  .footer-copy, .footer-links a, .footer-top { font-size: max(15px, 1.04vw); }
  .footer-place { font-size: max(14px, 0.97vw); }
  .footer-top { height: max(44px, 3.06vw); padding: 0 max(18px, 1.25vw) 0 max(20px, 1.39vw); }
  .footer-links { gap: 6px max(22px, 2.08vw); }
}

/* ── BURGER (mobile) ── */
.burger-btn {
  display: none;
  position: relative;
  flex-shrink: 0;
  width: 44px;          /* comfortable touch target… */
  height: 44px;
  margin-right: -13px;  /* …while the icon stays exactly where it was */
  background: none;
  border: none;
  cursor: pointer;
}
.burger-icon, .close-icon {
  position: absolute;
  inset: 0;
  width: 18px;
  height: 18px;
  margin: auto;
  fill: var(--text);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.close-icon {
  opacity: 0;
  transform: rotate(-90deg);
}
.burger-btn.open .burger-icon {
  opacity: 0;
  transform: rotate(90deg);
}
.burger-btn.open .close-icon {
  opacity: 1;
  transform: rotate(0deg);
}

/* ── MOBILE MENU (slides down from the top) ── */
.menu-drawer {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 97;
  height: 100vh;   /* fallback */
  height: 100dvh;
  overflow-y: auto; /* scrolls if the links don't fit, e.g. on a phone in landscape */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(28px, 5vh, 48px);
  padding-top: clamp(60px, 12vh, 120px);
  padding-bottom: clamp(40px, 8vh, 80px);
  background: rgba(255, 255, 253, 0.6);
  backdrop-filter: blur(30px);
  -webkit-backdrop-filter: blur(30px);
  border-radius: 0 0 var(--radius) var(--radius);
  transform: translateY(-100%);
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
  pointer-events: none;
}
.menu-drawer.open {
  transform: translateY(0);
  pointer-events: auto;
}
/* Auto margins centre the links while there's room, and let them start
   from the top (and scroll) when there isn't. justify-content: center
   would push the first links off the top of the screen instead. */
.menu-drawer > :first-child { margin-top: auto; }
.menu-drawer > :last-child  { margin-bottom: auto; }

.mobile-nav {
  font-weight: 700;
  font-size: 32px;
  color: var(--text);
  text-decoration: none;
  transition: color 0.3s ease;
}
.mobile-nav.active { color: var(--orange-text); }

/* the same button at the bottom of the mobile menu */
.mobile-cta {
  margin-top: clamp(36px, 7vh, 72px);
  padding: 14px 30px;
  border-radius: 999px;
  background: var(--orange);
  font-weight: 700;
  font-size: 22px;
  color: var(--on-orange); /* dark text: 5:1 on orange (white was 2.3:1) */
  text-decoration: none;
}
.mobile-cta:focus-visible { border-radius: 999px; }

/* Parallax behind the open menu */
body.menu-open-body .page {
  transform: translateY(40px) scale(0.97);
  filter: blur(4px);
}

/* ── HOVER (only on devices with a real pointer, so taps don't "stick") ── */
@media (hover: hover) {
  /* the text gets lighter (only the text, so the white line stays bright) and the line opens out;
     not on the active link: it already sits on the white capsule */
  .nav a:not(.active):hover { color: rgb(86 82 78 / 0.7); }
  .nav a:not(.active):hover::after { transform: scaleX(1); }
  .nav a.active:hover { opacity: 0.7; }
  .mobile-nav:hover { color: var(--orange-text); }
  /* Hover, the same everywhere: a button keeps its colour, rises 3px and a soft
     shadow appears under it; pressing pushes it back down.
     (Contact me, the outline one, also fills with its orange.)
     Yellow is kept for highlights (the marker, the Concept tag). */
  .btn-primary:hover,
  .btn-contact:hover,
  .header-cta:hover,
  .calc-next:not(:disabled):hover,
  .contact-send:not(:disabled):hover,
  .cr-btn:not(.cr-btn-outline):hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 18px rgb(246 149 64 / 0.45);
  }
  .btn-contact:hover { background: var(--orange); border-color: var(--orange); color: var(--on-orange); }
  /* light buttons: the same rise, a neutral shadow and a darker outline */
  .result-restart:hover,
  .cr-btn-outline:hover,
  .project-dialog-visit:hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 18px rgb(86 82 78 / 0.14);
  }
  /* pressed */
  .btn-primary:active, .btn-contact:active, .header-cta:active, .calc-next:not(:disabled):active,
  .contact-send:not(:disabled):active, .cr-btn:active, .result-restart:active, .project-dialog-visit:active {
    transform: translateY(0);
    box-shadow: 0 2px 6px rgb(246 149 64 / 0.35);
  }
  /* soft orange waves radiate from the header button while the mouse is on it */
  .header-cta:hover { animation: cta-waves 2s ease-out infinite; }
}

/* ── KEYBOARD FOCUS ── */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 4px;
  border-radius: 8px;
}
.btn:focus-visible { border-radius: 999px; } /* keep the pill shape */

/* ── RESPONSIVE ── */
@media (max-width: 768px) {
  .burger-btn { display: block; }
  .nav,
  .header-cta { display: none; }
  .header-inner { grid-template-columns: 1fr auto; }
  .header-label { font-size: 22px; }
  .header-dot { --dot: 10px; }
}

@media (min-width: 769px) {
  .menu-drawer { display: none; }
}

/* Phones in landscape: not much height for the menu */
@media (max-width: 768px) and (max-height: 500px) {
  .menu-drawer { gap: 12px; }
  .mobile-nav { font-size: 24px; }
  .mobile-cta { margin-top: 16px; font-size: 18px; padding: 10px 24px; }
}

/* ── REDUCED MOTION ── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .header-dot { animation: none; box-shadow: 0 0 6px 2px rgb(73 249 29 / 0.45); }
  .header, .header-content, .nav, .header-right { animation: none; }
  .hero-first, .hero-last, .hero-person, .hero-shape-top, .hero-shape-bottom,
  .hero-actions .btn { animation: none; }
  .skills li { opacity: 1; translate: none; transition: none; }
  .about-person, .about-tag, .about-content p, .about-btn { opacity: 1; translate: none; transition: none; }
  .about-content mark { background-size: 100% 100%; transition: none; }
  .about-content .accent > span { color: var(--orange-text); font-weight: 800; transition: none; animation: none !important; }
  .projects-list > li, .projects-list .project-tag { opacity: 1; translate: none; scale: none; transition: none; }
  .chip span::after, .budget-hint-wrap, .budget-hint, .calc-other { transition: none; }
  .process-step > *, .process-dot, .process-dot::after { scale: none !important; opacity: 1 !important; translate: none !important; transition: none !important; animation: none !important; }
  .calc-card, .quote-note { opacity: 1; translate: none; scale: none; transition: none; }
  .calc-question, .calc-option, .calc-result > *, .result-list li { animation: none !important; opacity: 1 !important; }
  .quote-note mark, .result-price mark { background-size: 100% 100% !important; transition: none; animation: none !important; }
  .hero-arrow .arrow-line, .about-arrow .arrow-line { animation: none; stroke-dashoffset: 0; }
  .nav a::after { transition: none; }
  body.menu-open-body .page { transform: none; filter: none; }
  .header, .nav-pill, .page, .contact-group,
  .contact-backdrop, .footer, .menu-drawer { transition-duration: 0.01ms; }
  .project-card img { transition: none; }
  .header-cta:hover { animation: none; box-shadow: 0 0 12px 4px rgb(246 149 64 / 0.45); }
  .btn.is-cue, .contact-send.is-cue, .hero-actions .btn.is-cue { animation: none; }
  .arrow-head { animation: none !important; transform: none !important; }
  .contact-arrow-glint { display: none; }
  .btn:hover, .header-cta:hover, .calc-next:hover, .contact-send:hover, .cr-btn:hover,
  .result-restart:hover, .project-dialog-visit:hover, .footer-top:hover, .footer-top:hover::after { transform: none !important; }
  .arrow-shadow { opacity: 1 !important; animation: none !important; }
  .project-dialog-visit:hover svg,
  .project-dialog-close:hover svg { transform: none; }
  .project-card:hover img { transform: none; }
}
